gimptoolgui.c 25.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * gimptoolgui.c
 * Copyright (C) 2013  Michael Natterer <mitch@gimp.org>
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <gegl.h>
#include <gtk/gtk.h>

#include "libgimpwidgets/gimpwidgets.h"

#include "display-types.h"

#include "core/gimpcontext.h"
31
#include "core/gimpmarshal.h"
32 33 34 35 36
#include "core/gimptoolinfo.h"

#include "widgets/gimpdialogfactory.h"
#include "widgets/gimpoverlaybox.h"
#include "widgets/gimpoverlaydialog.h"
37
#include "widgets/gimpwidgets-utils.h"
38 39 40 41 42 43

#include "gimpdisplayshell.h"
#include "gimptooldialog.h"
#include "gimptoolgui.h"


44 45 46 47 48 49 50
enum
{
  RESPONSE,
  LAST_SIGNAL
};


51 52 53 54 55
typedef struct _ResponseEntry ResponseEntry;

struct _ResponseEntry
{
  gint      response_id;
56
  gchar    *button_text;
57 58 59 60
  gint      alternative_position;
  gboolean  sensitive;
};

61 62 63 64
typedef struct _GimpToolGuiPrivate GimpToolGuiPrivate;

struct _GimpToolGuiPrivate
{
65
  GimpToolInfo     *tool_info;
66
  gchar            *title;
67
  gchar            *description;
68
  gchar            *icon_name;
69
  gchar            *help_id;
70 71
  GList            *response_entries;
  gint              default_response;
72
  gboolean          focus_on_map;
73

74
  gboolean          overlay;
75
  gboolean          auto_overlay;
76

77
  GimpDisplayShell *shell;
78
  GimpViewable     *viewable;
79 80 81 82 83 84 85 86 87 88

  GtkWidget        *dialog;
  GtkWidget        *vbox;
};

#define GET_PRIVATE(gui) G_TYPE_INSTANCE_GET_PRIVATE (gui, \
                                                      GIMP_TYPE_TOOL_GUI, \
                                                      GimpToolGuiPrivate)


89 90 91
static void   gimp_tool_gui_dispose         (GObject       *object);
static void   gimp_tool_gui_finalize        (GObject       *object);

92
static void   gimp_tool_gui_create_dialog   (GimpToolGui   *gui,
93
                                             GdkMonitor    *monitor);
94 95 96 97
static void   gimp_tool_gui_update_buttons  (GimpToolGui   *gui);
static void   gimp_tool_gui_update_shell    (GimpToolGui   *gui);
static void   gimp_tool_gui_update_viewable (GimpToolGui   *gui);

98 99 100
static void   gimp_tool_gui_dialog_response (GtkWidget     *dialog,
                                             gint           response_id,
                                             GimpToolGui   *gui);
101 102 103
static void   gimp_tool_gui_canvas_resized  (GtkWidget     *canvas,
                                             GtkAllocation *allocation,
                                             GimpToolGui   *gui);
104

105
static ResponseEntry * response_entry_new   (gint           response_id,
106
                                             const gchar   *button_text);
107 108 109
static void            response_entry_free  (ResponseEntry *entry);
static ResponseEntry * response_entry_find  (GList         *entries,
                                             gint           response_id);
110 111 112 113


G_DEFINE_TYPE (GimpToolGui, gimp_tool_gui, GIMP_TYPE_OBJECT)

114 115 116 117
static guint signals[LAST_SIGNAL] = { 0, };

#define parent_class gimp_tool_gui_parent_class

118 119 120 121 122 123 124 125 126

static void
gimp_tool_gui_class_init (GimpToolGuiClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose  = gimp_tool_gui_dispose;
  object_class->finalize = gimp_tool_gui_finalize;

127 128 129 130 131 132 133 134 135 136
  signals[RESPONSE] =
    g_signal_new ("response",
                  G_OBJECT_CLASS_TYPE (klass),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GimpToolGuiClass, response),
                  NULL, NULL,
                  gimp_marshal_VOID__INT,
                  G_TYPE_NONE, 1,
                  G_TYPE_INT);

137 138 139 140 141 142
  g_type_class_add_private (klass, sizeof (GimpToolGuiPrivate));
}

static void
gimp_tool_gui_init (GimpToolGui *gui)
{
143 144
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);

145
  private->default_response = -1;
146
  private->focus_on_map     = TRUE;
147

148 149
  private->vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
  g_object_ref_sink (private->vbox);
150 151 152 153 154 155 156
}

static void
gimp_tool_gui_dispose (GObject *object)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (object);

157
  g_clear_object (&private->tool_info);
158

159 160 161
  if (private->shell)
    gimp_tool_gui_set_shell (GIMP_TOOL_GUI (object), NULL);

162 163 164
  if (private->viewable)
    gimp_tool_gui_set_viewable (GIMP_TOOL_GUI (object), NULL);

165
  g_clear_object (&private->vbox);
166

167 168
  if (private->dialog)
    {
169 170 171
      if (gtk_widget_get_visible (private->dialog))
        gimp_tool_gui_hide (GIMP_TOOL_GUI (object));

172 173 174 175 176 177 178 179
      if (private->overlay)
        g_object_unref (private->dialog);
      else
        gtk_widget_destroy (private->dialog);

      private->dialog = NULL;
    }

180
  G_OBJECT_CLASS (parent_class)->dispose (object);
181 182 183 184 185 186 187
}

static void
gimp_tool_gui_finalize (GObject *object)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (object);

188 189 190 191
  g_clear_pointer (&private->title,       g_free);
  g_clear_pointer (&private->description, g_free);
  g_clear_pointer (&private->icon_name,   g_free);
  g_clear_pointer (&private->help_id,     g_free);
192

193 194 195 196 197 198 199
  if (private->response_entries)
    {
      g_list_free_full (private->response_entries,
                        (GDestroyNotify) response_entry_free);
      private->response_entries = NULL;
    }

200
  G_OBJECT_CLASS (parent_class)->finalize (object);
201 202 203 204 205
}


/**
 * gimp_tool_gui_new:
206 207 208 209 210
 * @tool_info:   a #GimpToolInfo
 * @description: a string to use in the gui header or %NULL to use the help
 *               field from #GimpToolInfo
 * @...:         a %NULL-terminated valist of button parameters as described in
 *               gtk_gui_new_with_buttons().
211 212 213 214 215 216 217
 *
 * This function creates a #GimpToolGui using the information stored
 * in @tool_info.
 *
 * Return value: a new #GimpToolGui
 **/
GimpToolGui *
218
gimp_tool_gui_new (GimpToolInfo *tool_info,
219
                   const gchar  *title,
220
                   const gchar  *description,
221 222
                   const gchar  *icon_name,
                   const gchar  *help_id,
223
                   GdkMonitor   *monitor,
224
                   gboolean      overlay,
225 226 227 228 229
                   ...)
{
  GimpToolGui        *gui;
  GimpToolGuiPrivate *private;
  va_list             args;
230
  const gchar        *button_text;
231 232 233 234 235 236 237

  g_return_val_if_fail (GIMP_IS_TOOL_INFO (tool_info), NULL);

  gui = g_object_new (GIMP_TYPE_TOOL_GUI, NULL);

  private = GET_PRIVATE (gui);

238
  if (! title)
239
    title = tool_info->label;
240 241

  if (! description)
242
    description = tool_info->label;
243 244 245 246 247 248 249

  if (! icon_name)
    icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));

  if (! help_id)
    help_id = tool_info->help_id;

250
  private->tool_info   = g_object_ref (tool_info);
251
  private->title       = g_strdup (title);
252
  private->description = g_strdup (description);
253 254
  private->icon_name   = g_strdup (icon_name);
  private->help_id     = g_strdup (help_id);
255
  private->overlay     = overlay;
256

257
  va_start (args, overlay);
258

259 260 261
  for (button_text = va_arg (args, const gchar *);
       button_text;
       button_text = va_arg (args, const gchar *))
262 263
    {
      gint response_id = va_arg (args, gint);
264

265 266
      private->response_entries = g_list_append (private->response_entries,
                                                 response_entry_new (response_id,
267
                                                                     button_text));
268 269
    }

270
  va_end (args);
271

272
  gimp_tool_gui_create_dialog (gui, monitor);
273 274 275 276

  return gui;
}

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
void
gimp_tool_gui_set_title (GimpToolGui *gui,
                         const gchar *title)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (title == private->title)
    return;

  g_free (private->title);
  private->title = g_strdup (title);

  if (! title)
294
    title = private->tool_info->label;
295 296 297 298

  g_object_set (private->dialog, "title", title, NULL);
}

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
void
gimp_tool_gui_set_description (GimpToolGui *gui,
                               const gchar *description)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (description == private->description)
    return;

  g_free (private->description);
  private->description = g_strdup (description);

  if (! description)
316
    description = private->tool_info->tooltip;
317 318 319

  if (private->overlay)
    {
320
      /* TODO */
321 322 323 324 325 326 327
    }
  else
    {
      g_object_set (private->dialog, "description", description, NULL);
    }
}

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
void
gimp_tool_gui_set_icon_name (GimpToolGui *gui,
                             const gchar *icon_name)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (icon_name == private->icon_name)
    return;

  g_free (private->icon_name);
  private->icon_name = g_strdup (icon_name);

  if (! icon_name)
    icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (private->tool_info));

347
  g_object_set (private->dialog, "icon-name", icon_name, NULL);
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 377 378
void
gimp_tool_gui_set_help_id (GimpToolGui *gui,
                           const gchar *help_id)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (help_id == private->help_id)
    return;

  g_free (private->help_id);
  private->help_id = g_strdup (help_id);

  if (! help_id)
    help_id = private->tool_info->help_id;

  if (private->overlay)
    {
      /* TODO */
    }
  else
    {
      g_object_set (private->dialog, "help-id", help_id, NULL);
    }
}

379 380 381 382 383 384 385 386 387 388 389 390 391 392
void
gimp_tool_gui_set_shell (GimpToolGui      *gui,
                         GimpDisplayShell *shell)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));
  g_return_if_fail (shell == NULL || GIMP_IS_DISPLAY_SHELL (shell));

  private = GET_PRIVATE (gui);

  if (shell == private->shell)
    return;

393 394 395 396 397 398 399 400 401
  if (private->shell)
    {
      g_object_remove_weak_pointer (G_OBJECT (private->shell),
                                    (gpointer) &private->shell);
      g_signal_handlers_disconnect_by_func (private->shell->canvas,
                                            gimp_tool_gui_canvas_resized,
                                            gui);
    }

402
  private->shell = shell;
403

404 405 406 407 408 409 410 411 412
  if (private->shell)
    {
      g_signal_connect (private->shell->canvas, "size-allocate",
                        G_CALLBACK (gimp_tool_gui_canvas_resized),
                        gui);
      g_object_add_weak_pointer (G_OBJECT (private->shell),
                                 (gpointer) &private->shell);
    }

413
  gimp_tool_gui_update_shell (gui);
414 415 416 417 418 419 420 421 422
}

void
gimp_tool_gui_set_viewable (GimpToolGui  *gui,
                            GimpViewable *viewable)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));
423
  g_return_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable));
424 425 426

  private = GET_PRIVATE (gui);

427 428 429
  if (private->viewable == viewable)
    return;

430 431 432 433
  if (private->viewable)
    g_object_remove_weak_pointer (G_OBJECT (private->viewable),
                                  (gpointer) &private->viewable);

434 435
  private->viewable = viewable;

436 437 438 439
  if (private->viewable)
    g_object_add_weak_pointer (G_OBJECT (private->viewable),
                               (gpointer) &private->viewable);

440
  gimp_tool_gui_update_viewable (gui);
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
}

GtkWidget *
gimp_tool_gui_get_dialog (GimpToolGui *gui)
{
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), NULL);

  return GET_PRIVATE (gui)->dialog;
}

GtkWidget *
gimp_tool_gui_get_vbox (GimpToolGui *gui)
{
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), NULL);

  return GET_PRIVATE (gui)->vbox;
}

459 460 461 462 463
gboolean
gimp_tool_gui_get_visible (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private;

464
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), FALSE);
465 466 467 468 469 470 471 472 473

  private = GET_PRIVATE (gui);

  if (private->overlay)
    return gtk_widget_get_parent (private->dialog) != NULL;
  else
    return gtk_widget_get_visible (private->dialog);
}

474 475 476 477 478 479 480 481 482
void
gimp_tool_gui_show (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

483 484
  g_return_if_fail (private->shell != NULL);

485 486 487 488 489
  if (private->overlay)
    {
      if (! gtk_widget_get_parent (private->dialog))
        {
          gimp_overlay_box_add_child (GIMP_OVERLAY_BOX (private->shell->canvas),
490
                                      private->dialog, 1.0, 0.0);
491 492 493 494 495
          gtk_widget_show (private->dialog);
        }
    }
  else
    {
496 497 498 499
      if (gtk_widget_get_visible (private->dialog))
        gdk_window_show (gtk_widget_get_window (private->dialog));
      else
        gtk_widget_show (private->dialog);
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    }
}

void
gimp_tool_gui_hide (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (private->overlay)
    {
      if (gtk_widget_get_parent (private->dialog))
        {
          gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (private->dialog)),
                                private->dialog);
          gtk_widget_hide (private->dialog);
        }
    }
  else
    {
      if (gimp_dialog_factory_from_widget (private->dialog, NULL))
        {
          gimp_dialog_factory_hide_dialog (private->dialog);
        }
      else
        {
          gtk_widget_hide (private->dialog);
        }
    }
}
533

534 535
void
gimp_tool_gui_set_overlay (GimpToolGui *gui,
536
                           GdkMonitor  *monitor,
537 538 539 540 541 542 543 544 545 546 547 548
                           gboolean     overlay)
{
  GimpToolGuiPrivate *private;
  gboolean            visible;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (private->overlay == overlay)
    return;

549 550 551 552 553 554
  if (! private->dialog)
    {
      private->overlay = overlay;
      return;
    }

555 556 557 558 559 560 561 562 563 564 565 566 567
  visible = gtk_widget_get_visible (private->dialog);

  if (visible)
    gimp_tool_gui_hide (gui);

  gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (private->vbox)),
                        private->vbox);

  if (private->overlay)
    g_object_unref (private->dialog);
  else
    gtk_widget_destroy (private->dialog);

568
  private->overlay = overlay;
569

570
  gimp_tool_gui_create_dialog (gui, monitor);
571 572 573 574 575 576 577 578 579 580 581 582 583

  if (visible)
    gimp_tool_gui_show (gui);
}

gboolean
gimp_tool_gui_get_overlay (GimpToolGui *gui)
{
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), FALSE);

  return GET_PRIVATE (gui)->overlay;
}

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
void
gimp_tool_gui_set_auto_overlay (GimpToolGui *gui,
                                gboolean     auto_overlay)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (private->auto_overlay != auto_overlay)
    {
      private->auto_overlay = auto_overlay;

      if (private->shell)
        gimp_tool_gui_canvas_resized (private->shell->canvas, NULL, gui);
    }
}

gboolean
gimp_tool_gui_get_auto_overlay (GimpToolGui *gui)
{
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), FALSE);

  return GET_PRIVATE (gui)->auto_overlay;
}

611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
void
gimp_tool_gui_set_focus_on_map (GimpToolGui *gui,
                                gboolean     focus_on_map)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  if (private->focus_on_map == focus_on_map)
    return;

  private->focus_on_map = focus_on_map ? TRUE : FALSE;

  if (! private->overlay)
    {
      gtk_window_set_focus_on_map (GTK_WINDOW (private->dialog),
                                   private->focus_on_map);
    }
}

gboolean
gimp_tool_gui_get_focus_on_map (GimpToolGui *gui)
{
  g_return_val_if_fail (GIMP_IS_TOOL_GUI (gui), FALSE);

  return GET_PRIVATE (gui)->focus_on_map;
}

641 642 643 644 645 646 647 648 649 650
void
gimp_tool_gui_set_default_response (GimpToolGui *gui,
                                    gint         response_id)
{
  GimpToolGuiPrivate *private;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

651 652 653 654 655
  g_return_if_fail (response_entry_find (private->response_entries,
                                         response_id) != NULL);

  private->default_response = response_id;

656 657
  if (private->overlay)
    {
658 659
      gimp_overlay_dialog_set_default_response (GIMP_OVERLAY_DIALOG (private->dialog),
                                                response_id);
660 661 662 663 664 665 666 667
    }
  else
    {
      gtk_dialog_set_default_response (GTK_DIALOG (private->dialog),
                                       response_id);
    }
}

668 669 670 671 672 673
void
gimp_tool_gui_set_response_sensitive (GimpToolGui *gui,
                                      gint         response_id,
                                      gboolean     sensitive)
{
  GimpToolGuiPrivate *private;
674
  ResponseEntry      *entry;
675 676 677 678 679

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

680 681 682 683 684 685
  entry = response_entry_find (private->response_entries, response_id);

  g_return_if_fail (entry != NULL);

  entry->sensitive = sensitive;

686 687
  if (private->overlay)
    {
688 689
      gimp_overlay_dialog_set_response_sensitive (GIMP_OVERLAY_DIALOG (private->dialog),
                                                  response_id, sensitive);
690 691 692 693 694 695 696
    }
  else
    {
      gtk_dialog_set_response_sensitive (GTK_DIALOG (private->dialog),
                                         response_id, sensitive);
    }
}
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712

void
gimp_tool_gui_set_alternative_button_order (GimpToolGui *gui,
                                            ...)
{
  GimpToolGuiPrivate *private;
  va_list             args;
  gint                response_id;
  gint                i;

  g_return_if_fail (GIMP_IS_TOOL_GUI (gui));

  private = GET_PRIVATE (gui);

  va_start (args, gui);

713
  for (response_id = va_arg (args, gint), i = 0;
714
       response_id != -1;
715
       response_id = va_arg (args, gint), i++)
716
    {
717 718 719 720 721
      ResponseEntry *entry = response_entry_find (private->response_entries,
                                                  response_id);

      if (entry)
        entry->alternative_position = i;
722 723 724 725
    }

  va_end (args);

726 727 728
  gimp_tool_gui_update_buttons (gui);
}

729

730 731 732
/*  private functions  */

static void
733
gimp_tool_gui_create_dialog (GimpToolGui *gui,
734
                             GdkMonitor  *monitor)
735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
{
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);
  GList              *list;

  if (private->overlay)
    {
      private->dialog = gimp_overlay_dialog_new (private->tool_info,
                                                 private->description,
                                                 NULL);
      g_object_ref_sink (private->dialog);

      for (list = private->response_entries; list; list = g_list_next (list))
        {
          ResponseEntry *entry = list->data;

          gimp_overlay_dialog_add_button (GIMP_OVERLAY_DIALOG (private->dialog),
751
                                          entry->button_text,
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
                                          entry->response_id);

          if (! entry->sensitive)
            gimp_overlay_dialog_set_response_sensitive (GIMP_OVERLAY_DIALOG (private->dialog),
                                                        entry->response_id,
                                                        FALSE);
        }

      if (private->default_response != -1)
        gimp_overlay_dialog_set_default_response (GIMP_OVERLAY_DIALOG (private->dialog),
                                                  private->default_response);

      gtk_container_set_border_width (GTK_CONTAINER (private->dialog), 6);

      gtk_container_set_border_width (GTK_CONTAINER (private->vbox), 0);
      gtk_container_add (GTK_CONTAINER (private->dialog), private->vbox);
      gtk_widget_show (private->vbox);
    }
  else
771
    {
772
      private->dialog = gimp_tool_dialog_new (private->tool_info,
773
                                              monitor,
774
                                              private->title,
775
                                              private->description,
776 777
                                              private->icon_name,
                                              private->help_id,
778 779 780 781 782 783 784
                                              NULL);

      for (list = private->response_entries; list; list = g_list_next (list))
        {
          ResponseEntry *entry = list->data;

          gimp_dialog_add_button (GIMP_DIALOG (private->dialog),
785
                                  entry->button_text,
786 787 788 789 790 791 792 793 794 795 796 797
                                  entry->response_id);

          if (! entry->sensitive)
            gtk_dialog_set_response_sensitive (GTK_DIALOG (private->dialog),
                                               entry->response_id,
                                               FALSE);
        }

      if (private->default_response != -1)
        gtk_dialog_set_default_response (GTK_DIALOG (private->dialog),
                                         private->default_response);

798 799 800
      gtk_window_set_focus_on_map (GTK_WINDOW (private->dialog),
                                   private->focus_on_map);

801 802 803 804
      gtk_container_set_border_width (GTK_CONTAINER (private->vbox), 6);
      gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (private->dialog))),
                          private->vbox, TRUE, TRUE, 0);
      gtk_widget_show (private->vbox);
805 806
    }

807 808 809 810 811 812 813
  gimp_tool_gui_update_buttons (gui);

  if (private->shell)
    gimp_tool_gui_update_shell (gui);

  if (private->viewable)
    gimp_tool_gui_update_viewable (gui);
814 815 816 817

  g_signal_connect_object (private->dialog, "response",
                           G_CALLBACK (gimp_tool_gui_dialog_response),
                           G_OBJECT (gui), 0);
818 819 820 821 822 823 824 825 826
}

static void
gimp_tool_gui_update_buttons (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);
  GList              *list;
  gint               *ids;
  gint                n_ids;
827
  gint                n_alternatives = 0;
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
  gint                i;

  n_ids = g_list_length (private->response_entries);
  ids   = g_new0 (gint, n_ids);

  for (list = private->response_entries, i = 0;
       list;
       list = g_list_next (list), i++)
    {
      ResponseEntry *entry = list->data;

      if (entry->alternative_position >= 0 &&
          entry->alternative_position < n_ids)
        {
          ids[entry->alternative_position] = entry->response_id;
843
          n_alternatives++;
844 845
        }
    }
846

847
  if (n_ids == n_alternatives)
848
    {
849 850
      if (private->overlay)
        {
851 852
          gimp_overlay_dialog_set_alternative_button_order (GIMP_OVERLAY_DIALOG (private->dialog),
                                                            n_ids, ids);
853 854 855
        }
      else
        {
856
          gimp_dialog_set_alternative_button_order_from_array (GTK_DIALOG (private->dialog),
857 858
                                                              n_ids, ids);
        }
859 860 861 862
    }

  g_free (ids);
}
863 864 865 866 867 868

static void
gimp_tool_gui_update_shell (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);

869 870 871 872 873 874 875 876 877 878 879
  if (private->overlay)
    {
      if (gtk_widget_get_parent (private->dialog))
        {
          gimp_tool_gui_hide (gui);

          if (private->shell)
            gimp_tool_gui_show (gui);
        }
    }
  else
880 881 882 883 884 885 886 887 888 889 890 891 892
    {
      gimp_tool_dialog_set_shell (GIMP_TOOL_DIALOG (private->dialog),
                                  private->shell);
    }
}

static void
gimp_tool_gui_update_viewable (GimpToolGui *gui)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);

  if (! private->overlay)
    {
893 894 895 896 897
      GimpContext *context = NULL;

      if (private->tool_info)
        context = GIMP_CONTEXT (private->tool_info->tool_options);

898
      gimp_viewable_dialog_set_viewable (GIMP_VIEWABLE_DIALOG (private->dialog),
899
                                         private->viewable, context);
900 901 902
    }
}

903 904 905 906 907
static void
gimp_tool_gui_dialog_response (GtkWidget   *dialog,
                               gint         response_id,
                               GimpToolGui *gui)
{
908 909 910 911 912 913 914 915 916 917 918 919
  if (response_id == GIMP_RESPONSE_DETACH)
    {
      gimp_tool_gui_set_auto_overlay (gui, FALSE);
      gimp_tool_gui_set_overlay (gui,
                                 gimp_widget_get_monitor (dialog),
                                 FALSE);
    }
  else
    {
      g_signal_emit (gui, signals[RESPONSE], 0,
                     response_id);
    }
920 921
}

922 923 924 925 926 927 928 929 930 931 932 933 934
static void
gimp_tool_gui_canvas_resized (GtkWidget     *canvas,
                              GtkAllocation *unused,
                              GimpToolGui   *gui)
{
  GimpToolGuiPrivate *private = GET_PRIVATE (gui);

  if (private->auto_overlay)
    {
      GtkRequisition requisition;
      GtkAllocation  allocation;
      gboolean       overlay = FALSE;

935
      gtk_widget_get_preferred_size (private->vbox, &requisition, NULL);
936 937 938 939 940 941 942 943 944 945 946 947 948 949
      gtk_widget_get_allocation (canvas, &allocation);

      if (allocation.width  > 2 * requisition.width &&
          allocation.height > 3 * requisition.height)
        {
          overlay = TRUE;
        }

      gimp_tool_gui_set_overlay (gui,
                                 gimp_widget_get_monitor (private->dialog),
                                 overlay);
    }
}

950 951
static ResponseEntry *
response_entry_new (gint         response_id,
952
                    const gchar *button_text)
953 954 955 956
{
  ResponseEntry *entry = g_slice_new0 (ResponseEntry);

  entry->response_id          = response_id;
957
  entry->button_text          = g_strdup (button_text);
958 959 960 961 962 963 964 965 966
  entry->alternative_position = -1;
  entry->sensitive            = TRUE;

  return entry;
}

static void
response_entry_free (ResponseEntry *entry)
{
967
  g_free (entry->button_text);
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985

  g_slice_free (ResponseEntry, entry);
}

static ResponseEntry *
response_entry_find (GList *entries,
                     gint   response_id)
{
  for (; entries; entries = g_list_next (entries))
    {
      ResponseEntry *entry = entries->data;

      if (entry->response_id == response_id)
        return entry;
    }

  return NULL;
}