[gimp] app: add a trivial attach-dialog-to-arbitrary-object utility



commit 61c260c727841f9998751e44a023ff9004fe614b
Author: Michael Natterer <mitch gimp org>
Date:   Mon Sep 12 00:03:22 2016 +0200

    app: add a trivial attach-dialog-to-arbitrary-object utility
    
    Namely dialogs_attach_dialog(), _detach_dialog(), _get_dialog()
    
    So we don't create the same dialogs multiple times, but raise the
    already existing ones. Port some places that did this manually
    to the new functions, and use it for many other dialogs.

 app/actions/drawable-commands.c  |   18 ++-
 app/actions/file-commands.c      |   76 +++-----
 app/actions/image-commands.c     |  182 ++++++++-----------
 app/actions/layers-commands.c    |   49 ++++--
 app/actions/select-commands.c    |  358 ++++++++++++++++++++++----------------
 app/actions/text-tool-commands.c |   26 +--
 app/actions/vectors-commands.c   |   50 ++++--
 app/dialogs/dialogs.c            |   50 ++++++
 app/dialogs/dialogs.h            |   12 ++
 9 files changed, 463 insertions(+), 358 deletions(-)
---
diff --git a/app/actions/drawable-commands.c b/app/actions/drawable-commands.c
index c99cd46..7b3fd79 100644
--- a/app/actions/drawable-commands.c
+++ b/app/actions/drawable-commands.c
@@ -35,6 +35,7 @@
 #include "core/gimplayermask.h"
 #include "core/gimpprogress.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/offset-dialog.h"
 
 #include "actions.h"
@@ -189,9 +190,20 @@ drawable_offset_cmd_callback (GtkAction *action,
   return_if_no_drawable (image, drawable, data);
   return_if_no_widget (widget, data);
 
-  dialog = offset_dialog_new (drawable, action_data_get_context (data),
-                              widget);
-  gtk_widget_show (dialog);
+#define OFFSET_DIALOG_KEY "gimp-offset-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (drawable), OFFSET_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      dialog = offset_dialog_new (drawable, action_data_get_context (data),
+                                  widget);
+
+      dialogs_attach_dialog (G_OBJECT (drawable),
+                             OFFSET_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 
diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c
index 9b71bba..b4b79ce 100644
--- a/app/actions/file-commands.c
+++ b/app/actions/file-commands.c
@@ -57,6 +57,7 @@
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplay-foreach.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/file-save-dialog.h"
 
 #include "actions.h"
@@ -65,9 +66,6 @@
 #include "gimp-intl.h"
 
 
-#define REVERT_DATA_KEY "revert-confirm-dialog"
-
-
 /*  local function prototypes  */
 
 static void        file_open_dialog_show        (Gimp         *gimp,
@@ -89,13 +87,9 @@ static GtkWidget * file_export_dialog_show      (Gimp         *gimp,
 static void        file_save_dialog_response    (GtkWidget    *dialog,
                                                  gint          response_id,
                                                  gpointer      data);
-static void        file_save_dialog_destroyed   (GtkWidget    *dialog,
-                                                 GimpImage    *image);
 static void        file_export_dialog_response  (GtkWidget    *dialog,
                                                  gint          response_id,
                                                  gpointer      data);
-static void        file_export_dialog_destroyed (GtkWidget    *dialog,
-                                                 GimpImage    *image);
 static void        file_new_template_callback   (GtkWidget    *widget,
                                                  const gchar  *name,
                                                  gpointer      data);
@@ -423,20 +417,20 @@ file_revert_cmd_callback (GtkAction *action,
   if (! file)
     file = gimp_image_get_imported_file (image);
 
-  dialog = g_object_get_data (G_OBJECT (image), REVERT_DATA_KEY);
-
   if (! file)
     {
       gimp_message_literal (image->gimp,
                             G_OBJECT (display), GIMP_MESSAGE_ERROR,
                             _("Revert failed. "
                               "No file name associated with this image."));
+      return;
     }
-  else if (dialog)
-    {
-      gtk_window_present (GTK_WINDOW (dialog));
-    }
-  else
+
+#define REVERT_DIALOG_KEY "gimp-revert-confirm-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), REVERT_DIALOG_KEY);
+
+  if (! dialog)
     {
       dialog =
         gimp_message_dialog_new (_("Revert Image"), "document-revert",
@@ -472,10 +466,10 @@ file_revert_cmd_callback (GtkAction *action,
                                    "on disk, you will lose all changes, "
                                    "including all undo information."));
 
-      g_object_set_data (G_OBJECT (image), REVERT_DATA_KEY, dialog);
-
-      gtk_widget_show (dialog);
+      dialogs_attach_dialog (G_OBJECT (image), REVERT_DIALOG_KEY, dialog);
     }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -638,7 +632,9 @@ file_save_dialog_show (Gimp        *gimp,
 {
   GtkWidget *dialog;
 
-  dialog = g_object_get_data (G_OBJECT (image), "gimp-file-save-dialog");
+#define SAVE_DIALOG_KEY "gimp-file-save-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), SAVE_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -654,15 +650,14 @@ file_save_dialog_show (Gimp        *gimp,
           gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                         GTK_WINDOW (gtk_widget_get_toplevel (parent)));
 
-          g_object_set_data_full (G_OBJECT (image),
-                                  "gimp-file-save-dialog", dialog,
-                                  (GDestroyNotify) gtk_widget_destroy);
+          dialogs_attach_dialog (G_OBJECT (image), SAVE_DIALOG_KEY, dialog);
+          g_signal_connect_object (image, "disconnect",
+                                   G_CALLBACK (gtk_widget_destroy),
+                                   dialog, G_CONNECT_SWAPPED);
+
           g_signal_connect (dialog, "response",
                             G_CALLBACK (file_save_dialog_response),
                             image);
-          g_signal_connect (dialog, "destroy",
-                            G_CALLBACK (file_save_dialog_destroyed),
-                            image);
         }
     }
 
@@ -713,14 +708,6 @@ file_save_dialog_response (GtkWidget *dialog,
     }
 }
 
-static void
-file_save_dialog_destroyed (GtkWidget *dialog,
-                            GimpImage *image)
-{
-  if (GIMP_FILE_DIALOG (dialog)->image == image)
-    g_object_set_data (G_OBJECT (image), "gimp-file-save-dialog", NULL);
-}
-
 static GtkWidget *
 file_export_dialog_show (Gimp      *gimp,
                          GimpImage *image,
@@ -728,7 +715,9 @@ file_export_dialog_show (Gimp      *gimp,
 {
   GtkWidget *dialog;
 
-  dialog = g_object_get_data (G_OBJECT (image), "gimp-file-export-dialog");
+#define EXPORT_DIALOG_KEY "gimp-file-export-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -744,15 +733,14 @@ file_export_dialog_show (Gimp      *gimp,
           gtk_window_set_transient_for (GTK_WINDOW (dialog),
                                         GTK_WINDOW (gtk_widget_get_toplevel (parent)));
 
-          g_object_set_data_full (G_OBJECT (image),
-                                  "gimp-file-export-dialog", dialog,
-                                  (GDestroyNotify) gtk_widget_destroy);
+          dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
+          g_signal_connect_object (image, "disconnect",
+                                   G_CALLBACK (gtk_widget_destroy),
+                                   dialog, G_CONNECT_SWAPPED);
+
           g_signal_connect (dialog, "response",
                             G_CALLBACK (file_export_dialog_response),
                             image);
-          g_signal_connect (dialog, "destroy",
-                            G_CALLBACK (file_export_dialog_destroyed),
-                            image);
         }
     }
 
@@ -802,14 +790,6 @@ file_export_dialog_response (GtkWidget *dialog,
 }
 
 static void
-file_export_dialog_destroyed (GtkWidget *dialog,
-                              GimpImage *image)
-{
-  if (GIMP_FILE_DIALOG (dialog)->image == image)
-    g_object_set_data (G_OBJECT (image), "gimp-file-export-dialog", NULL);
-}
-
-static void
 file_new_template_callback (GtkWidget   *widget,
                             const gchar *name,
                             gpointer     data)
@@ -837,8 +817,6 @@ file_revert_confirm_response (GtkWidget   *dialog,
 
   gtk_widget_destroy (dialog);
 
-  g_object_set_data (G_OBJECT (old_image), REVERT_DATA_KEY, NULL);
-
   if (response_id == GTK_RESPONSE_OK)
     {
       Gimp              *gimp = old_image->gimp;
diff --git a/app/actions/image-commands.c b/app/actions/image-commands.c
index 666d528..2d64bbb 100644
--- a/app/actions/image-commands.c
+++ b/app/actions/image-commands.c
@@ -57,6 +57,7 @@
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/color-profile-dialog.h"
 #include "dialogs/convert-indexed-dialog.h"
 #include "dialogs/convert-precision-dialog.h"
@@ -74,13 +75,6 @@
 #include "gimp-intl.h"
 
 
-#define IMAGE_CONVERT_PRECISION_DIALOG_KEY "image-convert-precision-dialog"
-#define IMAGE_CONVERT_TYPE_DIALOG_KEY      "image-convert-type-dialog"
-#define IMAGE_PROFILE_CONVERT_DIALOG_KEY   "image-profile-convert-dialog"
-#define IMAGE_PROFILE_ASSIGN_DIALOG_KEY    "image-profile-assign-dialog"
-#define IMAGE_PROFILE_SAVE_DIALOG_KEY      "image-profile-save-dialog"
-
-
 typedef struct
 {
   GimpContext *context;
@@ -184,12 +178,6 @@ image_duplicate_cmd_callback (GtkAction *action,
   g_object_unref (new_image);
 }
 
-static void
-image_convert_type_dialog_unset (GimpImage *image)
-{
-  g_object_set_data (G_OBJECT (image), IMAGE_CONVERT_TYPE_DIALOG_KEY, NULL);
-}
-
 void
 image_convert_base_type_cmd_callback (GtkAction *action,
                                       GtkAction *current,
@@ -210,8 +198,9 @@ image_convert_base_type_cmd_callback (GtkAction *action,
   if (value == gimp_image_get_base_type (image))
     return;
 
-  dialog = g_object_get_data (G_OBJECT (image),
-                              IMAGE_CONVERT_TYPE_DIALOG_KEY);
+#define CONVERT_TYPE_DIALOG_KEY "gimp-convert-type-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_TYPE_DIALOG_KEY);
 
   if (dialog)
     {
@@ -257,13 +246,8 @@ image_convert_base_type_cmd_callback (GtkAction *action,
 
   if (dialog)
     {
-      g_object_set_data (G_OBJECT (image),
-                         IMAGE_CONVERT_TYPE_DIALOG_KEY, dialog);
-
-      g_signal_connect_object (dialog, "destroy",
-                               G_CALLBACK (image_convert_type_dialog_unset),
-                               image, G_CONNECT_SWAPPED);
-
+      dialogs_attach_dialog (G_OBJECT (image),
+                             CONVERT_TYPE_DIALOG_KEY, dialog);
       gtk_window_present (GTK_WINDOW (dialog));
     }
 
@@ -273,12 +257,6 @@ image_convert_base_type_cmd_callback (GtkAction *action,
   gimp_image_flush (image);
 }
 
-static void
-image_convert_precision_dialog_unset (GimpImage *image)
-{
-  g_object_set_data (G_OBJECT (image), IMAGE_CONVERT_PRECISION_DIALOG_KEY, NULL);
-}
-
 void
 image_convert_precision_cmd_callback (GtkAction *action,
                                       GtkAction *current,
@@ -298,8 +276,9 @@ image_convert_precision_cmd_callback (GtkAction *action,
   if (value == gimp_image_get_component_type (image))
     return;
 
-  dialog = g_object_get_data (G_OBJECT (image),
-                              IMAGE_CONVERT_PRECISION_DIALOG_KEY);
+#define CONVERT_PRECISION_DIALOG_KEY "gimp-convert-precision-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), CONVERT_PRECISION_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -309,12 +288,8 @@ image_convert_precision_cmd_callback (GtkAction *action,
                                              value,
                                              GIMP_PROGRESS (display));
 
-      g_object_set_data (G_OBJECT (image),
-                         IMAGE_CONVERT_PRECISION_DIALOG_KEY, dialog);
-
-      g_signal_connect_object (dialog, "destroy",
-                               G_CALLBACK (image_convert_precision_dialog_unset),
-                               image, G_CONNECT_SWAPPED);
+      dialogs_attach_dialog (G_OBJECT (image),
+                             CONVERT_PRECISION_DIALOG_KEY, dialog);
     }
 
   gtk_window_present (GTK_WINDOW (dialog));
@@ -366,12 +341,6 @@ image_color_management_enabled_cmd_callback (GtkAction *action,
     }
 }
 
-static void
-image_profile_assign_dialog_unset (GimpImage *image)
-{
-  g_object_set_data (G_OBJECT (image), IMAGE_PROFILE_ASSIGN_DIALOG_KEY, NULL);
-}
-
 void
 image_color_profile_assign_cmd_callback (GtkAction *action,
                                          gpointer   data)
@@ -384,8 +353,9 @@ image_color_profile_assign_cmd_callback (GtkAction *action,
   return_if_no_display (display, data);
   return_if_no_widget (widget, data);
 
-  dialog = g_object_get_data (G_OBJECT (image),
-                              IMAGE_PROFILE_ASSIGN_DIALOG_KEY);
+#define PROFILE_ASSIGN_DIALOG_KEY "gimp-profile-assign-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_ASSIGN_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -395,23 +365,13 @@ image_color_profile_assign_cmd_callback (GtkAction *action,
                                          widget,
                                          GIMP_PROGRESS (display));
 
-      g_object_set_data (G_OBJECT (image),
-                         IMAGE_PROFILE_ASSIGN_DIALOG_KEY, dialog);
-
-      g_signal_connect_object (dialog, "destroy",
-                               G_CALLBACK (image_profile_assign_dialog_unset),
-                               image, G_CONNECT_SWAPPED);
+      dialogs_attach_dialog (G_OBJECT (image),
+                             PROFILE_ASSIGN_DIALOG_KEY, dialog);
     }
 
   gtk_window_present (GTK_WINDOW (dialog));
 }
 
-static void
-image_profile_convert_dialog_unset (GimpImage *image)
-{
-  g_object_set_data (G_OBJECT (image), IMAGE_PROFILE_CONVERT_DIALOG_KEY, NULL);
-}
-
 void
 image_color_profile_convert_cmd_callback (GtkAction *action,
                                           gpointer   data)
@@ -424,8 +384,9 @@ image_color_profile_convert_cmd_callback (GtkAction *action,
   return_if_no_display (display, data);
   return_if_no_widget (widget, data);
 
-  dialog = g_object_get_data (G_OBJECT (image),
-                              IMAGE_PROFILE_CONVERT_DIALOG_KEY);
+#define PROFILE_CONVERT_DIALOG_KEY "gimp-profile-convert-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_CONVERT_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -435,12 +396,8 @@ image_color_profile_convert_cmd_callback (GtkAction *action,
                                          widget,
                                          GIMP_PROGRESS (display));
 
-      g_object_set_data (G_OBJECT (image),
-                         IMAGE_PROFILE_CONVERT_DIALOG_KEY, dialog);
-
-      g_signal_connect_object (dialog, "destroy",
-                               G_CALLBACK (image_profile_convert_dialog_unset),
-                               image, G_CONNECT_SWAPPED);
+      dialogs_attach_dialog (G_OBJECT (image),
+                             PROFILE_CONVERT_DIALOG_KEY, dialog);
     }
 
   gtk_window_present (GTK_WINDOW (dialog));
@@ -458,12 +415,6 @@ image_color_profile_discard_cmd_callback (GtkAction *action,
 }
 
 static void
-image_profile_save_dialog_unset (GimpImage *image)
-{
-  g_object_set_data (G_OBJECT (image), IMAGE_PROFILE_SAVE_DIALOG_KEY, NULL);
-}
-
-static void
 image_profile_save_dialog_response (GtkWidget *dialog,
                                     gint       response_id,
                                     GimpImage *image)
@@ -509,8 +460,9 @@ image_color_profile_save_cmd_callback (GtkAction *action,
   return_if_no_display (display, data);
   return_if_no_widget (widget, data);
 
-  dialog = g_object_get_data (G_OBJECT (image),
-                              IMAGE_PROFILE_SAVE_DIALOG_KEY);
+#define PROFILE_SAVE_DIALOG_KEY "gimp-profile-save-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), PROFILE_SAVE_DIALOG_KEY);
 
   if (! dialog)
     {
@@ -535,12 +487,8 @@ image_color_profile_save_cmd_callback (GtkAction *action,
                         G_CALLBACK (image_profile_save_dialog_response),
                         image);
 
-      g_object_set_data (G_OBJECT (image),
-                         IMAGE_PROFILE_SAVE_DIALOG_KEY, dialog);
-
-      g_signal_connect_object (dialog, "destroy",
-                               G_CALLBACK (image_profile_save_dialog_unset),
-                               image, G_CONNECT_SWAPPED);
+      dialogs_attach_dialog (G_OBJECT (image),
+                             PROFILE_SAVE_DIALOG_KEY, dialog);
     }
 
   gtk_window_present (GTK_WINDOW (dialog));
@@ -647,21 +595,31 @@ image_print_size_cmd_callback (GtkAction *action,
 
   image = gimp_display_get_image (display);
 
-  dialog = print_size_dialog_new (image,
-                                  action_data_get_context (data),
-                                  _("Set Image Print Resolution"),
-                                  "gimp-image-print-size",
-                                  widget,
-                                  gimp_standard_help_func,
-                                  GIMP_HELP_IMAGE_PRINT_SIZE,
-                                  image_print_size_callback,
-                                  NULL);
+#define PRINT_SIZE_DIALOG_KEY "gimp-print-size-dialog"
 
-  g_signal_connect_object (display, "disconnect",
-                           G_CALLBACK (gtk_widget_destroy),
-                           dialog, G_CONNECT_SWAPPED);
+  dialog = dialogs_get_dialog (G_OBJECT (image), PRINT_SIZE_DIALOG_KEY);
 
-  gtk_widget_show (dialog);
+  if (! dialog)
+    {
+      dialog = print_size_dialog_new (image,
+                                      action_data_get_context (data),
+                                      _("Set Image Print Resolution"),
+                                      "gimp-image-print-size",
+                                      widget,
+                                      gimp_standard_help_func,
+                                      GIMP_HELP_IMAGE_PRINT_SIZE,
+                                      image_print_size_callback,
+                                      NULL);
+
+      g_signal_connect_object (display, "disconnect",
+                               G_CALLBACK (gtk_widget_destroy),
+                               dialog, G_CONNECT_SWAPPED);
+
+      dialogs_attach_dialog (G_OBJECT (image),
+                             PRINT_SIZE_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -677,25 +635,35 @@ image_scale_cmd_callback (GtkAction *action,
 
   image = gimp_display_get_image (display);
 
-  if (image_scale_unit != GIMP_UNIT_PERCENT)
-    image_scale_unit = gimp_display_get_shell (display)->unit;
+#define SCALE_DIALOG_KEY "gimp-scale-dialog"
 
-  if (image_scale_interp == -1)
-    image_scale_interp = display->gimp->config->interpolation_type;
+  dialog = dialogs_get_dialog (G_OBJECT (image), SCALE_DIALOG_KEY);
 
-  dialog = image_scale_dialog_new (image,
-                                   action_data_get_context (data),
-                                   widget,
-                                   image_scale_unit,
-                                   image_scale_interp,
-                                   image_scale_callback,
-                                   display);
-
-  g_signal_connect_object (display, "disconnect",
-                           G_CALLBACK (gtk_widget_destroy),
-                           dialog, G_CONNECT_SWAPPED);
+  if (! dialog)
+    {
+      if (image_scale_unit != GIMP_UNIT_PERCENT)
+        image_scale_unit = gimp_display_get_shell (display)->unit;
+
+      if (image_scale_interp == -1)
+        image_scale_interp = display->gimp->config->interpolation_type;
+
+      dialog = image_scale_dialog_new (image,
+                                       action_data_get_context (data),
+                                       widget,
+                                       image_scale_unit,
+                                       image_scale_interp,
+                                       image_scale_callback,
+                                       display);
+
+      g_signal_connect_object (display, "disconnect",
+                               G_CALLBACK (gtk_widget_destroy),
+                               dialog, G_CONNECT_SWAPPED);
+
+      dialogs_attach_dialog (G_OBJECT (image),
+                             SCALE_DIALOG_KEY, dialog);
+    }
 
-  gtk_widget_show (dialog);
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index 6deaad1..636f23c 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -68,6 +68,7 @@
 #include "tools/gimptexttool.h"
 #include "tools/tool_manager.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/layer-add-mask-dialog.h"
 #include "dialogs/layer-options-dialog.h"
 #include "dialogs/resize-dialog.h"
@@ -610,30 +611,42 @@ void
 layers_resize_cmd_callback (GtkAction *action,
                             gpointer   data)
 {
-  GimpDisplay *display = NULL;
-  GimpImage   *image;
-  GimpLayer   *layer;
-  GtkWidget   *widget;
-  GtkWidget   *dialog;
+  GimpImage *image;
+  GimpLayer *layer;
+  GtkWidget *widget;
+  GtkWidget *dialog;
   return_if_no_layer (image, layer, data);
   return_if_no_widget (widget, data);
 
-  if (GIMP_IS_IMAGE_WINDOW (data))
-    display = action_data_get_display (data);
+#define RESIZE_DIALOG_KEY "gimp-resize-dialog"
 
-  if (layer_resize_unit != GIMP_UNIT_PERCENT && display)
-    layer_resize_unit = gimp_display_get_shell (display)->unit;
+  dialog = dialogs_get_dialog (G_OBJECT (layer), RESIZE_DIALOG_KEY);
 
-  dialog = resize_dialog_new (GIMP_VIEWABLE (layer),
-                              action_data_get_context (data),
-                              _("Set Layer Boundary Size"), "gimp-layer-resize",
-                              widget,
-                              gimp_standard_help_func, GIMP_HELP_LAYER_RESIZE,
-                              layer_resize_unit,
-                              layers_resize_layer_callback,
-                              action_data_get_context (data));
+  if (! dialog)
+    {
+      GimpDisplay *display = NULL;
+
+      if (GIMP_IS_IMAGE_WINDOW (data))
+        display = action_data_get_display (data);
+
+      if (layer_resize_unit != GIMP_UNIT_PERCENT && display)
+        layer_resize_unit = gimp_display_get_shell (display)->unit;
+
+      dialog = resize_dialog_new (GIMP_VIEWABLE (layer),
+                                  action_data_get_context (data),
+                                  _("Set Layer Boundary Size"),
+                                  "gimp-layer-resize",
+                                  widget,
+                                  gimp_standard_help_func,
+                                  GIMP_HELP_LAYER_RESIZE,
+                                  layer_resize_unit,
+                                  layers_resize_layer_callback,
+                                  action_data_get_context (data));
+
+      dialogs_attach_dialog (G_OBJECT (layer), RESIZE_DIALOG_KEY, dialog);
+    }
 
-  gtk_widget_show (dialog);
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
diff --git a/app/actions/select-commands.c b/app/actions/select-commands.c
index b1146d1..1cb7409 100644
--- a/app/actions/select-commands.c
+++ b/app/actions/select-commands.c
@@ -41,6 +41,7 @@
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/fill-dialog.h"
 #include "dialogs/stroke-dialog.h"
 
@@ -135,31 +136,41 @@ void
 select_feather_cmd_callback (GtkAction *action,
                              gpointer   data)
 {
-  GimpDisplay      *display;
-  GimpImage        *image;
-  GimpDialogConfig *config;
-  GtkWidget        *dialog;
-  gdouble           xres;
-  gdouble           yres;
+  GimpDisplay *display;
+  GimpImage   *image;
+  GtkWidget   *dialog;
   return_if_no_display (display, data);
 
-  image  = gimp_display_get_image (display);
-  config = GIMP_DIALOG_CONFIG (image->gimp->config);
-
-  gimp_image_get_resolution (image, &xres, &yres);
-
-  dialog = gimp_query_size_box (_("Feather Selection"),
-                                GTK_WIDGET (gimp_display_get_shell (display)),
-                                gimp_standard_help_func,
-                                GIMP_HELP_SELECTION_FEATHER,
-                                _("Feather selection by"),
-                                config->selection_feather_radius, 0, 32767, 3,
-                                gimp_display_get_shell (display)->unit,
-                                MIN (xres, yres),
-                                FALSE,
-                                G_OBJECT (image), "disconnect",
-                                select_feather_callback, image);
-  gtk_widget_show (dialog);
+  image = gimp_display_get_image (display);
+
+#define FEATHER_DIALOG_KEY "gimp-selection-feather-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), FEATHER_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+      gdouble           xres;
+      gdouble           yres;
+
+      gimp_image_get_resolution (image, &xres, &yres);
+
+      dialog = gimp_query_size_box (_("Feather Selection"),
+                                    GTK_WIDGET (gimp_display_get_shell (display)),
+                                    gimp_standard_help_func,
+                                    GIMP_HELP_SELECTION_FEATHER,
+                                    _("Feather selection by"),
+                                    config->selection_feather_radius, 0, 32767, 3,
+                                    gimp_display_get_shell (display)->unit,
+                                    MIN (xres, yres),
+                                    FALSE,
+                                    G_OBJECT (image), "disconnect",
+                                    select_feather_callback, image);
+
+      dialogs_attach_dialog (G_OBJECT (image), FEATHER_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -177,136 +188,165 @@ void
 select_shrink_cmd_callback (GtkAction *action,
                             gpointer   data)
 {
-  GimpDisplay      *display;
-  GimpImage        *image;
-  GimpDialogConfig *config;
-  GtkWidget        *dialog;
-  GtkWidget        *button;
-  gdouble           xres;
-  gdouble           yres;
+  GimpDisplay *display;
+  GimpImage   *image;
+  GtkWidget   *dialog;
   return_if_no_display (display, data);
 
-  image  = gimp_display_get_image (display);
-  config = GIMP_DIALOG_CONFIG (image->gimp->config);
-
-  gimp_image_get_resolution (image, &xres, &yres);
-
-  dialog = gimp_query_size_box (_("Shrink Selection"),
-                                GTK_WIDGET (gimp_display_get_shell (display)),
-                                gimp_standard_help_func,
-                                GIMP_HELP_SELECTION_SHRINK,
-                                _("Shrink selection by"),
-                                config->selection_shrink_radius, 1, 32767, 0,
-                                gimp_display_get_shell (display)->unit,
-                                MIN (xres, yres),
-                                FALSE,
-                                G_OBJECT (image), "disconnect",
-                                select_shrink_callback, image);
-
-  /* Edge lock button */
-  button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
-  g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
-  gimp_help_set_help_data (button,
-                           _("When shrinking, act as if selected areas "
-                             "continued outside the image."),
-                           NULL);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-                                config->selection_shrink_edge_lock);
-  gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
-                      FALSE, FALSE, 0);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
+  image = gimp_display_get_image (display);
+
+#define SHRINK_DIALOG_KEY "gimp-selection-shrink-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), SHRINK_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+      GtkWidget        *button;
+      gdouble           xres;
+      gdouble           yres;
+
+      gimp_image_get_resolution (image, &xres, &yres);
+
+      dialog = gimp_query_size_box (_("Shrink Selection"),
+                                    GTK_WIDGET (gimp_display_get_shell (display)),
+                                    gimp_standard_help_func,
+                                    GIMP_HELP_SELECTION_SHRINK,
+                                    _("Shrink selection by"),
+                                    config->selection_shrink_radius, 1, 32767, 0,
+                                    gimp_display_get_shell (display)->unit,
+                                    MIN (xres, yres),
+                                    FALSE,
+                                    G_OBJECT (image), "disconnect",
+                                    select_shrink_callback, image);
+
+      /* Edge lock button */
+      button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
+      g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
+      gimp_help_set_help_data (button,
+                               _("When shrinking, act as if selected areas "
+                                 "continued outside the image."),
+                               NULL);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+                                    config->selection_shrink_edge_lock);
+      gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
+                          FALSE, FALSE, 0);
+      gtk_widget_show (button);
+
+      dialogs_attach_dialog (G_OBJECT (image), SHRINK_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
 select_grow_cmd_callback (GtkAction *action,
                           gpointer   data)
 {
-  GimpDisplay      *display;
-  GimpImage        *image;
-  GimpDialogConfig *config;
-  GtkWidget        *dialog;
-  gdouble           xres;
-  gdouble           yres;
+  GimpDisplay *display;
+  GimpImage   *image;
+  GtkWidget   *dialog;
   return_if_no_display (display, data);
 
-  image  = gimp_display_get_image (display);
-  config = GIMP_DIALOG_CONFIG (image->gimp->config);
-
-  gimp_image_get_resolution (image, &xres, &yres);
-
-  dialog = gimp_query_size_box (_("Grow Selection"),
-                                GTK_WIDGET (gimp_display_get_shell (display)),
-                                gimp_standard_help_func,
-                                GIMP_HELP_SELECTION_GROW,
-                                _("Grow selection by"),
-                                config->selection_grow_radius, 1, 32767, 0,
-                                gimp_display_get_shell (display)->unit,
-                                MIN (xres, yres),
-                                FALSE,
-                                G_OBJECT (image), "disconnect",
-                                select_grow_callback, image);
-  gtk_widget_show (dialog);
+  image = gimp_display_get_image (display);
+
+#define GROW_DIALOG_KEY "gimp-selection-grow-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), GROW_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+      gdouble           xres;
+      gdouble           yres;
+
+      gimp_image_get_resolution (image, &xres, &yres);
+
+      dialog = gimp_query_size_box (_("Grow Selection"),
+                                    GTK_WIDGET (gimp_display_get_shell (display)),
+                                    gimp_standard_help_func,
+                                    GIMP_HELP_SELECTION_GROW,
+                                    _("Grow selection by"),
+                                    config->selection_grow_radius, 1, 32767, 0,
+                                    gimp_display_get_shell (display)->unit,
+                                    MIN (xres, yres),
+                                    FALSE,
+                                    G_OBJECT (image), "disconnect",
+                                    select_grow_callback, image);
+
+      dialogs_attach_dialog (G_OBJECT (image), GROW_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
 select_border_cmd_callback (GtkAction *action,
                             gpointer   data)
 {
-  GimpDisplay      *display;
-  GimpImage        *image;
-  GimpDialogConfig *config;
-  GtkWidget        *dialog;
-  GtkWidget        *combo;
-  GtkWidget        *button;
-  gdouble           xres;
-  gdouble           yres;
+  GimpDisplay *display;
+  GimpImage   *image;
+  GtkWidget   *dialog;
   return_if_no_display (display, data);
 
-  image  = gimp_display_get_image (display);
-  config = GIMP_DIALOG_CONFIG (image->gimp->config);
-
-  gimp_image_get_resolution (image, &xres, &yres);
-
-  dialog = gimp_query_size_box (_("Border Selection"),
-                                GTK_WIDGET (gimp_display_get_shell (display)),
-                                gimp_standard_help_func,
-                                GIMP_HELP_SELECTION_BORDER,
-                                _("Border selection by"),
-                                config->selection_border_radius, 1, 32767, 0,
-                                gimp_display_get_shell (display)->unit,
-                                MIN (xres, yres),
-                                FALSE,
-                                G_OBJECT (image), "disconnect",
-                                select_border_callback, image);
-
-  /* Border style combo */
-  combo = gimp_enum_combo_box_new (GIMP_TYPE_CHANNEL_BORDER_STYLE);
-  gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Border style"));
-
-  gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), combo,
-                      FALSE, FALSE, 0);
-
-  g_object_set_data (G_OBJECT (dialog), "border-style-combo", combo);
-  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
-                                 config->selection_border_style);
-  gtk_widget_show (combo);
-
-  /* Edge lock button */
-  button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
-  g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
-  gimp_help_set_help_data (button,
-                           _("When bordering, act as if selected areas "
-                             "continued outside the image."),
-                           NULL);
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
-                                config->selection_border_edge_lock);
-  gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
-                      FALSE, FALSE, 0);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
+  image = gimp_display_get_image (display);
+
+#define BORDER_DIALOG_KEY "gimp-selection-border-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (image), BORDER_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
+      GtkWidget        *combo;
+      GtkWidget        *button;
+      gdouble           xres;
+      gdouble           yres;
+
+      gimp_image_get_resolution (image, &xres, &yres);
+
+      dialog = gimp_query_size_box (_("Border Selection"),
+                                    GTK_WIDGET (gimp_display_get_shell (display)),
+                                    gimp_standard_help_func,
+                                    GIMP_HELP_SELECTION_BORDER,
+                                    _("Border selection by"),
+                                    config->selection_border_radius, 1, 32767, 0,
+                                    gimp_display_get_shell (display)->unit,
+                                    MIN (xres, yres),
+                                    FALSE,
+                                    G_OBJECT (image), "disconnect",
+                                    select_border_callback, image);
+
+      /* Border style combo */
+      combo = gimp_enum_combo_box_new (GIMP_TYPE_CHANNEL_BORDER_STYLE);
+      gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo),
+                                    _("Border style"));
+
+      gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), combo,
+                          FALSE, FALSE, 0);
+
+      g_object_set_data (G_OBJECT (dialog), "border-style-combo", combo);
+      gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo),
+                                     config->selection_border_style);
+      gtk_widget_show (combo);
+
+      /* Edge lock button */
+      button = gtk_check_button_new_with_mnemonic (_("_Selected areas continue outside the image"));
+      g_object_set_data (G_OBJECT (dialog), "edge-lock-toggle", button);
+      gimp_help_set_help_data (button,
+                               _("When bordering, act as if selected areas "
+                                 "continued outside the image."),
+                               NULL);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
+                                    config->selection_border_edge_lock);
+      gtk_box_pack_start (GTK_BOX (GIMP_QUERY_BOX_VBOX (dialog)), button,
+                          FALSE, FALSE, 0);
+      gtk_widget_show (button);
+
+      dialogs_attach_dialog (G_OBJECT (image), BORDER_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -361,13 +401,23 @@ select_fill_cmd_callback (GtkAction *action,
       return;
     }
 
-  dialog = fill_dialog_new (GIMP_ITEM (gimp_image_get_mask (image)),
-                            action_data_get_context (data),
-                            _("Fill Selection Outline"),
-                            GIMP_STOCK_TOOL_BUCKET_FILL,
-                            GIMP_HELP_SELECTION_FILL,
-                            widget);
-  gtk_widget_show (dialog);
+#define FILL_DIALOG_KEY "gimp-selection-fill-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (drawable), FILL_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      dialog = fill_dialog_new (GIMP_ITEM (gimp_image_get_mask (image)),
+                                action_data_get_context (data),
+                                _("Fill Selection Outline"),
+                                GIMP_STOCK_TOOL_BUCKET_FILL,
+                                GIMP_HELP_SELECTION_FILL,
+                                widget);
+
+      dialogs_attach_dialog (G_OBJECT (drawable), FILL_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -437,13 +487,23 @@ select_stroke_cmd_callback (GtkAction *action,
       return;
     }
 
-  dialog = stroke_dialog_new (GIMP_ITEM (gimp_image_get_mask (image)),
-                              action_data_get_context (data),
-                              _("Stroke Selection"),
-                              GIMP_STOCK_SELECTION_STROKE,
-                              GIMP_HELP_SELECTION_STROKE,
-                              widget);
-  gtk_widget_show (dialog);
+#define STROKE_DIALOG_KEY "gimp-selection-stroke-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (drawable), STROKE_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      dialog = stroke_dialog_new (GIMP_ITEM (gimp_image_get_mask (image)),
+                                  action_data_get_context (data),
+                                  _("Stroke Selection"),
+                                  GIMP_STOCK_SELECTION_STROKE,
+                                  GIMP_HELP_SELECTION_STROKE,
+                                  widget);
+
+      dialogs_attach_dialog (G_OBJECT (drawable), STROKE_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
diff --git a/app/actions/text-tool-commands.c b/app/actions/text-tool-commands.c
index 5ec458b..4e74fc6 100644
--- a/app/actions/text-tool-commands.c
+++ b/app/actions/text-tool-commands.c
@@ -37,6 +37,8 @@
 
 #include "tools/gimptexttool.h"
 
+#include "dialogs/dialogs.h"
+
 #include "text-tool-commands.h"
 
 #include "gimp-intl.h"
@@ -44,11 +46,9 @@
 
 /*  local function prototypes  */
 
-static void   text_tool_load_dialog_destroyed (GtkWidget    *dialog,
-                                              GObject      *tool);
-static void   text_tool_load_dialog_response  (GtkWidget    *dialog,
-                                              gint          response_id,
-                                              GimpTextTool *tool);
+static void   text_tool_load_dialog_response (GtkWidget    *dialog,
+                                              gint          response_id,
+                                              GimpTextTool *tool);
 
 
 /*  public functions  */
@@ -98,7 +98,7 @@ text_tool_load_cmd_callback (GtkAction *action,
   GtkWidget      *parent    = NULL;
   GtkFileChooser *chooser;
 
-  dialog = g_object_get_data (G_OBJECT (text_tool), "gimp-text-file-dialog");
+  dialog = dialogs_get_dialog (G_OBJECT (text_tool), "gimp-text-file-dialog");
 
   if (dialog)
     {
@@ -131,11 +131,8 @@ text_tool_load_cmd_callback (GtkAction *action,
                                            GTK_RESPONSE_CANCEL,
                                            -1);
 
-  g_object_set_data (G_OBJECT (text_tool), "gimp-text-file-dialog", dialog);
-
-  g_signal_connect (dialog, "destroy",
-                   G_CALLBACK (text_tool_load_dialog_destroyed),
-                   text_tool);
+  dialogs_attach_dialog (G_OBJECT (text_tool),
+                         "gimp-text-file-dialog", dialog);
 
   gtk_window_set_role (GTK_WINDOW (chooser), "gimp-text-load-file");
   gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_MOUSE);
@@ -202,13 +199,6 @@ text_tool_direction_cmd_callback (GtkAction *action,
 /*  private functions  */
 
 static void
-text_tool_load_dialog_destroyed (GtkWidget *dialog,
-                                GObject   *tool)
-{
-  g_object_set_data (tool, "gimp-text-file-dialog", NULL);
-}
-
-static void
 text_tool_load_dialog_response (GtkWidget    *dialog,
                                gint          response_id,
                                GimpTextTool *tool)
diff --git a/app/actions/vectors-commands.c b/app/actions/vectors-commands.c
index 038ed5e..e728794 100644
--- a/app/actions/vectors-commands.c
+++ b/app/actions/vectors-commands.c
@@ -58,6 +58,7 @@
 #include "tools/gimpvectortool.h"
 #include "tools/tool_manager.h"
 
+#include "dialogs/dialogs.h"
 #include "dialogs/fill-dialog.h"
 #include "dialogs/stroke-dialog.h"
 #include "dialogs/vectors-export-dialog.h"
@@ -397,13 +398,24 @@ vectors_fill_cmd_callback (GtkAction *action,
       return;
     }
 
-  dialog = fill_dialog_new (GIMP_ITEM (vectors),
-                            action_data_get_context (data),
-                            _("Fill Path"),
-                            GIMP_STOCK_TOOL_BUCKET_FILL,
-                            GIMP_HELP_PATH_FILL,
-                            widget);
-  gtk_widget_show (dialog);
+
+#define FILL_DIALOG_KEY "gimp-vectors-fill-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (drawable), FILL_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      dialog = fill_dialog_new (GIMP_ITEM (vectors),
+                                action_data_get_context (data),
+                                _("Fill Path"),
+                                GIMP_STOCK_TOOL_BUCKET_FILL,
+                                GIMP_HELP_PATH_FILL,
+                                widget);
+
+      dialogs_attach_dialog (G_OBJECT (drawable), FILL_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
@@ -474,13 +486,23 @@ vectors_stroke_cmd_callback (GtkAction *action,
       return;
     }
 
-  dialog = stroke_dialog_new (GIMP_ITEM (vectors),
-                              action_data_get_context (data),
-                              _("Stroke Path"),
-                              GIMP_STOCK_PATH_STROKE,
-                              GIMP_HELP_PATH_STROKE,
-                              widget);
-  gtk_widget_show (dialog);
+#define STROKE_DIALOG_KEY "gimp-vectors-stroke-dialog"
+
+  dialog = dialogs_get_dialog (G_OBJECT (drawable), STROKE_DIALOG_KEY);
+
+  if (! dialog)
+    {
+      dialog = stroke_dialog_new (GIMP_ITEM (vectors),
+                                  action_data_get_context (data),
+                                  _("Stroke Path"),
+                                  GIMP_STOCK_PATH_STROKE,
+                                  GIMP_HELP_PATH_STROKE,
+                                  widget);
+
+      dialogs_attach_dialog (G_OBJECT (drawable), STROKE_DIALOG_KEY, dialog);
+    }
+
+  gtk_window_present (GTK_WINDOW (dialog));
 }
 
 void
diff --git a/app/dialogs/dialogs.c b/app/dialogs/dialogs.c
index b1e2ccd..71fae44 100644
--- a/app/dialogs/dialogs.c
+++ b/app/dialogs/dialogs.c
@@ -679,3 +679,53 @@ dialogs_get_toolbox (void)
 
   return NULL;
 }
+
+GtkWidget *
+dialogs_get_dialog (GObject     *attach_object,
+                    const gchar *attach_key)
+{
+  g_return_val_if_fail (G_IS_OBJECT (attach_object), NULL);
+  g_return_val_if_fail (attach_key != NULL, NULL);
+
+  return g_object_get_data (attach_object, attach_key);
+}
+
+void
+dialogs_attach_dialog (GObject     *attach_object,
+                       const gchar *attach_key,
+                       GtkWidget   *dialog)
+{
+  g_return_if_fail (G_IS_OBJECT (attach_object));
+  g_return_if_fail (attach_key != NULL);
+  g_return_if_fail (GTK_IS_WIDGET (dialog));
+
+  g_object_set_data (attach_object, attach_key, dialog);
+  g_object_set_data (G_OBJECT (dialog), "gimp-dialogs-attach-key",
+                     (gpointer) attach_key);
+
+  g_signal_connect_object (dialog, "destroy",
+                           G_CALLBACK (dialogs_detach_dialog),
+                           attach_object,
+                           G_CONNECT_SWAPPED);
+}
+
+void
+dialogs_detach_dialog (GObject   *attach_object,
+                       GtkWidget *dialog)
+{
+  const gchar *attach_key;
+
+  g_return_if_fail (G_IS_OBJECT (attach_object));
+  g_return_if_fail (GTK_IS_WIDGET (dialog));
+
+  attach_key = g_object_get_data (G_OBJECT (dialog),
+                                  "gimp-dialogs-attach-key");
+
+  g_return_if_fail (attach_key != NULL);
+
+  g_object_set_data (attach_object, attach_key, NULL);
+
+  g_signal_handlers_disconnect_by_func (dialog,
+                                        dialogs_detach_dialog,
+                                        attach_object);
+}
diff --git a/app/dialogs/dialogs.h b/app/dialogs/dialogs.h
index b727c28..b55b208 100644
--- a/app/dialogs/dialogs.h
+++ b/app/dialogs/dialogs.h
@@ -33,4 +33,16 @@ void        dialogs_save_recent_docks (Gimp            *gimp);
 GtkWidget * dialogs_get_toolbox       (void);
 
 
+/* attaching dialogs to arbitrary objects, and detaching them
+ * automatically upon destruction
+ */
+GtkWidget * dialogs_get_dialog        (GObject         *attach_object,
+                                       const gchar     *attach_key);
+void        dialogs_attach_dialog     (GObject         *attach_object,
+                                       const gchar     *attach_key,
+                                       GtkWidget       *dialog);
+void        dialogs_detach_dialog     (GObject         *attach_object,
+                                       GtkWidget       *dialog);
+
+
 #endif /* __DIALOGS_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]