gimpimagemaptool.c 24.4 KB
Newer Older
Michael Natterer's avatar
Michael Natterer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

21 22
#include <errno.h>

23
#include <glib/gstdio.h>
Michael Natterer's avatar
Michael Natterer committed
24
#include <gtk/gtk.h>
25
#include <gdk/gdkkeysyms.h>
Michael Natterer's avatar
Michael Natterer committed
26

27
#include "libgimpbase/gimpbase.h"
28 29
#include "libgimpwidgets/gimpwidgets.h"

Michael Natterer's avatar
Michael Natterer committed
30 31
#include "tools-types.h"

32 33
#include "core/gimp.h"
#include "core/gimpcontext.h"
34 35
#include "core/gimpdrawable.h"
#include "core/gimpimage.h"
36
#include "core/gimpimage-pick-color.h"
37
#include "core/gimpimagemap.h"
38
#include "core/gimppickable.h"
Michael Natterer's avatar
Michael Natterer committed
39
#include "core/gimpprojection.h"
40
#include "core/gimptoolinfo.h"
Michael Natterer's avatar
Michael Natterer committed
41

42
#include "widgets/gimptooldialog.h"
43
#include "widgets/gimpviewabledialog.h"
44
#include "widgets/gimpwidgets-utils.h"
45 46 47

#include "display/gimpdisplay.h"

48
#include "gimpcoloroptions.h"
49
#include "gimpimagemaptool.h"
50
#include "gimptoolcontrol.h"
51

52
#include "gimp-intl.h"
Michael Natterer's avatar
Michael Natterer committed
53 54 55 56


/*  local function prototypes  */

57
static void     gimp_image_map_tool_finalize   (GObject          *object);
58

59 60 61 62 63
static gboolean gimp_image_map_tool_initialize (GimpTool         *tool,
                                                GimpDisplay      *gdisp);
static void     gimp_image_map_tool_control    (GimpTool         *tool,
                                                GimpToolAction    action,
                                                GimpDisplay      *gdisp);
64 65 66
static gboolean gimp_image_map_tool_key_press  (GimpTool         *tool,
                                                GdkEventKey      *kevent,
                                                GimpDisplay      *gdisp);
67

68 69 70 71 72 73
static gboolean gimp_image_map_tool_pick_color (GimpColorTool    *color_tool,
                                                gint              x,
                                                gint              y,
                                                GimpImageType    *sample_type,
                                                GimpRGB          *color,
                                                gint             *color_index);
74 75 76
static void     gimp_image_map_tool_map        (GimpImageMapTool *im_tool);
static void     gimp_image_map_tool_dialog     (GimpImageMapTool *im_tool);
static void     gimp_image_map_tool_reset      (GimpImageMapTool *im_tool);
77

78
static void     gimp_image_map_tool_flush      (GimpImageMap     *image_map,
79
                                                GimpImageMapTool *im_tool);
80

81 82
static void     gimp_image_map_tool_response   (GtkWidget        *widget,
                                                gint              response_id,
83
                                                GimpImageMapTool *im_tool);
84

85 86 87 88 89 90 91 92 93 94 95
static void     gimp_image_map_tool_load_clicked     (GtkWidget        *widget,
                                                      GimpImageMapTool *tool);
static void     gimp_image_map_tool_load_ext_clicked (GtkWidget        *widget,
                                                      GdkModifierType   state,
                                                      GimpImageMapTool *tool);
static void     gimp_image_map_tool_save_clicked     (GtkWidget        *widget,
                                                      GimpImageMapTool *tool);
static void     gimp_image_map_tool_save_ext_clicked (GtkWidget        *widget,
                                                      GdkModifierType   state,
                                                      GimpImageMapTool *tool);

96
static void     gimp_image_map_tool_settings_dialog  (GimpImageMapTool *im_tool,
97 98
                                                      const gchar      *title,
                                                      gboolean          save);
99

100 101 102
static void     gimp_image_map_tool_notify_preview   (GObject          *config,
                                                      GParamSpec       *pspec,
                                                      GimpImageMapTool *im_tool);
103 104


105
G_DEFINE_TYPE (GimpImageMapTool, gimp_image_map_tool, GIMP_TYPE_COLOR_TOOL);
Michael Natterer's avatar
Michael Natterer committed
106

107
#define parent_class gimp_image_map_tool_parent_class
Michael Natterer's avatar
Michael Natterer committed
108 109 110 111 112


static void
gimp_image_map_tool_class_init (GimpImageMapToolClass *klass)
{
113 114 115
  GObjectClass       *object_class     = G_OBJECT_CLASS (klass);
  GimpToolClass      *tool_class       = GIMP_TOOL_CLASS (klass);
  GimpColorToolClass *color_tool_class = GIMP_COLOR_TOOL_CLASS (klass);
116

117
  object_class->finalize   = gimp_image_map_tool_finalize;
118

119 120 121
  tool_class->initialize   = gimp_image_map_tool_initialize;
  tool_class->control      = gimp_image_map_tool_control;
  tool_class->key_press    = gimp_image_map_tool_key_press;
122

123
  color_tool_class->pick   = gimp_image_map_tool_pick_color;
124

125 126 127
  klass->shell_desc        = NULL;
  klass->settings_name     = NULL;
  klass->load_dialog_title = NULL;
128
  klass->load_button_tip   = NULL;
129
  klass->save_dialog_title = NULL;
130
  klass->save_button_tip   = NULL;
131

132 133 134 135 136
  klass->map               = NULL;
  klass->dialog            = NULL;
  klass->reset             = NULL;
  klass->settings_load     = NULL;
  klass->settings_save     = NULL;
Michael Natterer's avatar
Michael Natterer committed
137 138 139 140 141
}

static void
gimp_image_map_tool_init (GimpImageMapTool *image_map_tool)
{
142
  GimpTool *tool = GIMP_TOOL (image_map_tool);
Michael Natterer's avatar
Michael Natterer committed
143

Michael Natterer's avatar
Michael Natterer committed
144 145
  gimp_tool_control_set_scroll_lock (tool->control, TRUE);
  gimp_tool_control_set_preserve    (tool->control, FALSE);
146 147 148 149 150
  gimp_tool_control_set_dirty_mask  (tool->control,
                                     GIMP_DIRTY_IMAGE           |
                                     GIMP_DIRTY_IMAGE_STRUCTURE |
                                     GIMP_DIRTY_DRAWABLE        |
                                     GIMP_DIRTY_SELECTION);
151

152 153
  image_map_tool->drawable  = NULL;
  image_map_tool->image_map = NULL;
154

155 156 157 158
  image_map_tool->shell       = NULL;
  image_map_tool->main_vbox   = NULL;
  image_map_tool->load_button = NULL;
  image_map_tool->save_button = NULL;
159 160 161 162 163
}

static void
gimp_image_map_tool_finalize (GObject *object)
{
164
  GimpImageMapTool *image_map_tool = GIMP_IMAGE_MAP_TOOL (object);
165 166 167 168

  if (image_map_tool->shell)
    {
      gtk_widget_destroy (image_map_tool->shell);
169 170 171 172
      image_map_tool->shell       = NULL;
      image_map_tool->main_vbox   = NULL;
      image_map_tool->load_button = NULL;
      image_map_tool->save_button = NULL;
173 174 175 176 177
    }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

178 179
#define RESPONSE_RESET 1

180
static gboolean
181
gimp_image_map_tool_initialize (GimpTool    *tool,
182
                                GimpDisplay *gdisp)
183
{
184
  GimpImageMapTool *image_map_tool = GIMP_IMAGE_MAP_TOOL (tool);
185
  GimpToolInfo     *tool_info;
186 187
  GimpDrawable     *drawable;

188 189
  tool_info = tool->tool_info;

190 191 192
  /*  set gdisp so the dialog can be hidden on display destruction  */
  tool->gdisp = gdisp;

193 194
  if (! image_map_tool->shell)
    {
195 196 197 198 199 200 201
      GimpImageMapToolClass *klass;
      GtkWidget             *shell;
      GtkWidget             *vbox;
      GtkWidget             *toggle;
      const gchar           *stock_id;

      klass = GIMP_IMAGE_MAP_TOOL_GET_CLASS (image_map_tool);
202 203

      stock_id = gimp_viewable_get_stock_id (GIMP_VIEWABLE (tool_info));
204 205

      image_map_tool->shell = shell =
206
        gimp_tool_dialog_new (tool_info,
207
                              gdisp->shell,
208
                              klass->shell_desc,
209

210 211 212
                              GIMP_STOCK_RESET, RESPONSE_RESET,
                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                              GTK_STOCK_OK,     GTK_RESPONSE_OK,
213

214
                              NULL);
215

216 217 218 219 220
      gtk_dialog_set_alternative_button_order (GTK_DIALOG (shell),
                                               RESPONSE_RESET,
                                               GTK_RESPONSE_OK,
                                               GTK_RESPONSE_CANCEL,
                                               -1);
221 222


223 224 225 226
      g_signal_connect_object (shell, "response",
                               G_CALLBACK (gimp_image_map_tool_response),
                               G_OBJECT (image_map_tool), 0);

227 228
      image_map_tool->main_vbox = vbox = gtk_vbox_new (FALSE, 6);
      gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
229 230 231
      gtk_container_add (GTK_CONTAINER (GTK_DIALOG (shell)->vbox), vbox);

      /*  The preview toggle  */
232 233 234 235
      toggle = gimp_prop_check_button_new (G_OBJECT (tool_info->tool_options),
                                           "preview",
                                           _("_Preview"));

236 237
      gtk_box_pack_end (GTK_BOX (image_map_tool->main_vbox), toggle,
                        FALSE, FALSE, 0);
238 239
      gtk_widget_show (toggle);

240 241 242
      g_signal_connect_object (tool_info->tool_options, "notify::preview",
                               G_CALLBACK (gimp_image_map_tool_notify_preview),
                               image_map_tool, 0);
243

244 245 246
      if (klass->load_dialog_title)
        {
          image_map_tool->load_button =
247 248
            g_object_new (GIMP_TYPE_BUTTON,
                          "label",         GTK_STOCK_OPEN,
249 250
                          "use-stock",     TRUE,
                          "use-underline", TRUE,
251
                          NULL);
252 253 254 255

          g_signal_connect (image_map_tool->load_button, "clicked",
                            G_CALLBACK (gimp_image_map_tool_load_clicked),
                            image_map_tool);
256
          g_signal_connect (image_map_tool->load_button, "extended-clicked",
257 258 259 260 261 262
                            G_CALLBACK (gimp_image_map_tool_load_ext_clicked),
                            image_map_tool);

          if (klass->load_button_tip)
            {
              gchar *str = g_strdup_printf ("%s\n"
263
                                            "(%s)  %s",
264 265 266 267 268 269 270
                                            klass->load_button_tip,
                                            gimp_get_mod_string (GDK_SHIFT_MASK),
                                            _("Quick Load"));

              gimp_help_set_help_data (image_map_tool->load_button, str, NULL);
              g_free (str);
            }
271 272 273 274 275
        }

      if (klass->save_dialog_title)
        {
          image_map_tool->save_button =
276 277
            g_object_new (GIMP_TYPE_BUTTON,
                          "label",         GTK_STOCK_SAVE,
Sven Neumann's avatar
Sven Neumann committed
278 279
                          "use-stock",     TRUE,
                          "use-underline", TRUE,
280
                          NULL);
281 282 283 284

          g_signal_connect (image_map_tool->save_button, "clicked",
                            G_CALLBACK (gimp_image_map_tool_save_clicked),
                            image_map_tool);
285
          g_signal_connect (image_map_tool->save_button, "extended-clicked",
286 287 288 289 290 291
                            G_CALLBACK (gimp_image_map_tool_save_ext_clicked),
                            image_map_tool);

          if (klass->save_button_tip)
            {
              gchar *str = g_strdup_printf ("%s\n"
292
                                            "(%s)  %s",
293 294 295 296 297 298 299
                                            klass->save_button_tip,
                                            gimp_get_mod_string (GDK_SHIFT_MASK),
                                            _("Quick Save"));

              gimp_help_set_help_data (image_map_tool->save_button, str, NULL);
              g_free (str);
            }
300 301
        }

302 303 304 305 306 307
      /*  Fill in subclass widgets  */
      gimp_image_map_tool_dialog (image_map_tool);

      gtk_widget_show (vbox);
    }

308 309
  drawable = gimp_image_active_drawable (gdisp->gimage);

310 311
  gimp_viewable_dialog_set_viewable (GIMP_VIEWABLE_DIALOG (image_map_tool->shell),
                                     GIMP_VIEWABLE (drawable));
312 313 314 315

  gtk_widget_show (image_map_tool->shell);

  image_map_tool->drawable  = drawable;
316
  image_map_tool->image_map = gimp_image_map_new (drawable, tool_info->blurb);
317

318
  g_signal_connect (image_map_tool->image_map, "flush",
319 320 321
                    G_CALLBACK (gimp_image_map_tool_flush),
                    image_map_tool);

322
  return TRUE;
323 324 325 326
}

static void
gimp_image_map_tool_control (GimpTool       *tool,
327 328
                             GimpToolAction  action,
                             GimpDisplay    *gdisp)
329
{
330
  GimpImageMapTool *image_map_tool = GIMP_IMAGE_MAP_TOOL (tool);
331 332 333 334 335

  switch (action)
    {
    case HALT:
      if (image_map_tool->shell)
336 337
        gtk_dialog_response (GTK_DIALOG (image_map_tool->shell),
                             GTK_RESPONSE_CANCEL);
338 339 340 341 342 343 344 345 346
      break;

    default:
      break;
    }

  GIMP_TOOL_CLASS (parent_class)->control (tool, action, gdisp);
}

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
static gboolean
gimp_image_map_tool_key_press (GimpTool    *tool,
                               GdkEventKey *kevent,
                               GimpDisplay *gdisp)
{
  GimpImageMapTool *image_map_tool = GIMP_IMAGE_MAP_TOOL (tool);

  if (gdisp == tool->gdisp)
    {
      switch (kevent->keyval)
        {
        case GDK_KP_Enter:
        case GDK_Return:
          gimp_image_map_tool_response (NULL, GTK_RESPONSE_OK, image_map_tool);
          return TRUE;

        case GDK_Delete:
        case GDK_BackSpace:
          gimp_image_map_tool_response (NULL, RESPONSE_RESET, image_map_tool);
          return TRUE;

        case GDK_Escape:
          gimp_image_map_tool_response (NULL, GTK_RESPONSE_CANCEL, image_map_tool);
          return TRUE;
        }
    }

  return FALSE;
}

377 378 379 380 381 382 383 384 385
static gboolean
gimp_image_map_tool_pick_color (GimpColorTool *color_tool,
                                gint           x,
                                gint           y,
                                GimpImageType *sample_type,
                                GimpRGB       *color,
                                gint          *color_index)
{
  GimpImageMapTool *tool = GIMP_IMAGE_MAP_TOOL (color_tool);
386 387 388 389 390
  gint              off_x, off_y;

  gimp_item_offsets (GIMP_ITEM (tool->drawable), &off_x, &off_y);
  x -= off_x;
  y -= off_y;
391 392 393

  *sample_type = gimp_drawable_type (tool->drawable);

394 395 396 397
  return gimp_pickable_pick_color (GIMP_PICKABLE (tool->image_map), x, y,
                                   color_tool->options->sample_average,
                                   color_tool->options->average_radius,
                                   color, color_index);
398 399
}

400
static void
401
gimp_image_map_tool_map (GimpImageMapTool *tool)
402
{
403
  GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->map (tool);
404 405 406
}

static void
407
gimp_image_map_tool_dialog (GimpImageMapTool *tool)
408
{
409
  GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->dialog (tool);
410 411 412
}

static void
413 414 415 416 417 418
gimp_image_map_tool_reset (GimpImageMapTool *tool)
{
  GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->reset (tool);
}

static gboolean
419 420
gimp_image_map_tool_settings_load (GimpImageMapTool *tool,
                                   gpointer          file)
421
{
Michael Natterer's avatar
Michael Natterer committed
422
  GimpImageMapToolClass *tool_class = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool);
423 424 425

  g_return_val_if_fail (tool_class->settings_load != NULL, FALSE);

426 427 428 429 430 431 432
  if (tool_class->settings_load (tool, file))
    {
      gimp_image_map_tool_preview (tool);
      return TRUE;
    }

  return FALSE;
433 434 435
}

static gboolean
436 437
gimp_image_map_tool_settings_save (GimpImageMapTool *tool,
                                   gpointer          file)
438
{
Michael Natterer's avatar
Michael Natterer committed
439
  GimpImageMapToolClass *tool_class = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool);
440 441 442 443

  g_return_val_if_fail (tool_class->settings_save != NULL, FALSE);

  return tool_class->settings_save (tool, file);
444 445 446 447 448 449
}

static void
gimp_image_map_tool_flush (GimpImageMap     *image_map,
                           GimpImageMapTool *image_map_tool)
{
450
  GimpTool *tool = GIMP_TOOL (image_map_tool);
451

Michael Natterer's avatar
Michael Natterer committed
452
  gimp_projection_flush_now (tool->gdisp->gimage->projection);
453 454 455 456
  gimp_display_flush_now (tool->gdisp);
}

static void
457 458 459
gimp_image_map_tool_response (GtkWidget        *widget,
                              gint              response_id,
                              GimpImageMapTool *image_map_tool)
460
{
461
  GimpTool *tool = GIMP_TOOL (image_map_tool);
462

463
  switch (response_id)
464
    {
465 466 467 468
    case RESPONSE_RESET:
      gimp_image_map_tool_reset (image_map_tool);
      gimp_image_map_tool_preview (image_map_tool);
      break;
469

470 471
    case GTK_RESPONSE_OK:
      gtk_widget_hide (image_map_tool->shell);
472

473 474 475
      if (image_map_tool->image_map)
        {
          GimpImageMapOptions *options;
476

477
          options = GIMP_IMAGE_MAP_OPTIONS (tool->tool_info->tool_options);
478

479 480 481 482
          gimp_tool_control_set_preserve (tool->control, TRUE);

          if (! options->preview)
            gimp_image_map_tool_map (image_map_tool);
483

484 485
          gimp_image_map_commit (image_map_tool->image_map);
          image_map_tool->image_map = NULL;
486

487 488 489 490
          gimp_tool_control_set_preserve (tool->control, FALSE);

          gimp_image_flush (tool->gdisp->gimage);
        }
491

492 493 494
      tool->gdisp    = NULL;
      tool->drawable = NULL;
      break;
495

496 497
    default:
      gtk_widget_hide (image_map_tool->shell);
498

499 500 501
      if (image_map_tool->image_map)
        {
          gimp_tool_control_set_preserve (tool->control, TRUE);
502

503 504
          gimp_image_map_abort (image_map_tool->image_map);
          image_map_tool->image_map = NULL;
505

506
          gimp_tool_control_set_preserve (tool->control, FALSE);
507

508 509
          gimp_image_flush (tool->gdisp->gimage);
        }
510

511 512 513 514
      tool->gdisp    = NULL;
      tool->drawable = NULL;
      break;
    }
515 516 517
}

static void
518 519 520
gimp_image_map_tool_notify_preview (GObject          *config,
                                    GParamSpec       *pspec,
                                    GimpImageMapTool *image_map_tool)
521
{
522 523
  GimpTool            *tool    = GIMP_TOOL (image_map_tool);
  GimpImageMapOptions *options = GIMP_IMAGE_MAP_OPTIONS (config);
524

525
  if (options->preview)
526 527 528 529 530 531 532 533 534 535
    {
      gimp_tool_control_set_preserve (tool->control, TRUE);

      gimp_image_map_tool_map (image_map_tool);

      gimp_tool_control_set_preserve (tool->control, FALSE);
    }
  else
    {
      if (image_map_tool->image_map)
536 537
        {
          gimp_tool_control_set_preserve (tool->control, TRUE);
538

539
          gimp_image_map_clear (image_map_tool->image_map);
540

541
          gimp_tool_control_set_preserve (tool->control, FALSE);
542

543 544
          gimp_image_flush (tool->gdisp->gimage);
        }
545
    }
Michael Natterer's avatar
Michael Natterer committed
546
}
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569

void
gimp_image_map_tool_preview (GimpImageMapTool *image_map_tool)
{
  GimpTool            *tool;
  GimpImageMapOptions *options;

  g_return_if_fail (GIMP_IS_IMAGE_MAP_TOOL (image_map_tool));

  tool = GIMP_TOOL (image_map_tool);

  options = GIMP_IMAGE_MAP_OPTIONS (tool->tool_info->tool_options);

  if (options->preview)
    {
      gimp_tool_control_set_preserve (tool->control, TRUE);

      gimp_image_map_tool_map (image_map_tool);

      gimp_tool_control_set_preserve (tool->control, FALSE);
    }
}

570 571 572 573 574
static void
gimp_image_map_tool_load_save (GimpImageMapTool *tool,
                               const gchar      *filename,
                               gboolean          save)
{
575
  FILE *file = g_fopen (filename, save ? "wt" : "rt");
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603

  if (! file)
    {
      g_message (save ?
                 _("Could not open '%s' for writing: %s") :
                 _("Could not open '%s' for reading: %s"),
                 gimp_filename_to_utf8 (filename),
                 g_strerror (errno));
      return;
    }

  g_object_set (GIMP_TOOL (tool)->tool_info->tool_options,
                "settings", filename,
                NULL);

  if (save)
    {
      gimp_image_map_tool_settings_save (tool, file);
    }
  else if (! gimp_image_map_tool_settings_load (tool, file))
    {
      g_message ("Error in reading file '%s'.",
                 gimp_filename_to_utf8 (filename));
    }

  fclose (file);
}

604 605 606 607 608
static void
settings_dialog_response (GtkWidget        *dialog,
                          gint              response_id,
                          GimpImageMapTool *tool)
{
Michael Natterer's avatar
Michael Natterer committed
609
  gboolean save;
610 611 612 613 614

  save = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), "save"));

  if (response_id == GTK_RESPONSE_OK)
    {
615
      gchar *filename;
616

617
      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
618

619
      gimp_image_map_tool_load_save (tool, filename, save);
620

621
      g_free (filename);
622 623
    }

624 625 626 627 628
  if (save)
    gtk_widget_set_sensitive (tool->load_button, TRUE);
  else
    gtk_widget_set_sensitive (tool->save_button, TRUE);

629 630 631
  gtk_widget_destroy (dialog);
}

632 633
static void
gimp_image_map_tool_load_clicked (GtkWidget        *widget,
634 635 636 637 638 639 640 641 642 643 644
                                  GimpImageMapTool *tool)
{
  GimpImageMapToolClass *klass = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool);

  gimp_image_map_tool_settings_dialog (tool, klass->load_dialog_title, FALSE);
}

static void
gimp_image_map_tool_load_ext_clicked (GtkWidget        *widget,
                                      GdkModifierType   state,
                                      GimpImageMapTool *tool)
645
{
646 647 648 649 650 651 652
  if (state & GDK_SHIFT_MASK)
    {
      gchar *filename;

      g_object_get (GIMP_TOOL (tool)->tool_info->tool_options,
                    "settings", &filename,
                    NULL);
653

654 655 656 657 658 659 660 661 662 663
      if (filename)
        {
          gimp_image_map_tool_load_save (tool, filename, FALSE);
          g_free (filename);
        }
      else
        {
          gimp_image_map_tool_load_clicked (widget, tool);
        }
    }
664 665 666 667
}

static void
gimp_image_map_tool_save_clicked (GtkWidget        *widget,
668 669 670 671 672 673 674 675 676 677 678
                                  GimpImageMapTool *tool)
{
  GimpImageMapToolClass *klass = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool);

  gimp_image_map_tool_settings_dialog (tool, klass->save_dialog_title, TRUE);
}

static void
gimp_image_map_tool_save_ext_clicked (GtkWidget        *widget,
                                      GdkModifierType   state,
                                      GimpImageMapTool *tool)
679
{
680 681 682
  if (state & GDK_SHIFT_MASK)
    {
      gchar *filename;
683

684 685 686 687 688 689 690 691 692 693 694 695 696 697
      g_object_get (GIMP_TOOL (tool)->tool_info->tool_options,
                    "settings", &filename,
                    NULL);

      if (filename)
        {
          gimp_image_map_tool_load_save (tool, filename, TRUE);
          g_free (filename);
        }
      else
        {
          gimp_image_map_tool_save_clicked (widget, tool);
        }
    }
698 699 700
}

static void
701 702 703 704 705
gimp_image_map_tool_settings_dialog (GimpImageMapTool *tool,
                                     const gchar      *title,
                                     gboolean          save)
{
  GimpImageMapOptions *options;
706
  GtkFileChooser      *chooser;
707
  const gchar         *settings_name;
708
  gchar               *folder;
709 710 711

  g_return_if_fail (GIMP_IS_IMAGE_MAP_TOOL (tool));

712 713 714
  settings_name = GIMP_IMAGE_MAP_TOOL_GET_CLASS (tool)->settings_name;
  g_return_if_fail (settings_name != NULL);

715 716 717 718 719 720
  if (tool->settings_dialog)
    {
      gtk_window_present (GTK_WINDOW (tool->settings_dialog));
      return;
    }

721 722 723 724 725
  if (save)
    gtk_widget_set_sensitive (tool->load_button, FALSE);
  else
    gtk_widget_set_sensitive (tool->save_button, FALSE);

726 727 728 729 730
  tool->settings_dialog =
    gtk_file_chooser_dialog_new (title, GTK_WINDOW (tool->shell),
                                 save ?
                                 GTK_FILE_CHOOSER_ACTION_SAVE :
                                 GTK_FILE_CHOOSER_ACTION_OPEN,
731

732 733 734
                                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                 save ? GTK_STOCK_SAVE : GTK_STOCK_OPEN,
                                 GTK_RESPONSE_OK,
735

736
                                 NULL);
737

738
  chooser = GTK_FILE_CHOOSER (tool->settings_dialog);
739

740
  g_object_set_data (G_OBJECT (chooser), "save", GINT_TO_POINTER (save));
741

742 743 744 745
  gtk_window_set_role (GTK_WINDOW (chooser), "gimp-load-save-settings");
  gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_MOUSE);

  g_object_add_weak_pointer (G_OBJECT (chooser),
746 747
                             (gpointer) &tool->settings_dialog);

748
  gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
749

750
  g_signal_connect (chooser, "response",
751 752
                    G_CALLBACK (settings_dialog_response),
                    tool);
753
  g_signal_connect (chooser, "delete-event",
754 755
                    G_CALLBACK (gtk_true),
                    NULL);
756

757 758
  folder = g_build_filename (gimp_directory (), settings_name, NULL);
  gtk_file_chooser_add_shortcut_folder (chooser, folder, NULL);
759

760 761 762
  options = GIMP_IMAGE_MAP_OPTIONS (GIMP_TOOL (tool)->tool_info->tool_options);

  if (options->settings)
763 764 765
    gtk_file_chooser_set_filename (chooser, options->settings);
  else
    gtk_file_chooser_set_current_folder (chooser, folder);
766

767
  g_free (folder);
768 769 770 771 772 773

  gimp_help_connect (tool->settings_dialog, gimp_standard_help_func,
                     GIMP_TOOL (tool)->tool_info->help_id, NULL);

  gtk_widget_show (tool->settings_dialog);
}