1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpoverlaydialog.c
5  * Copyright (C) 2009-2010  Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 
27 #include "libgimpwidgets/gimpwidgets.h"
28 
29 #include "widgets-types.h"
30 
31 #include "core/gimpmarshal.h"
32 #include "core/gimptoolinfo.h"
33 
34 #include "gimpoverlaydialog.h"
35 
36 #include "gimp-intl.h"
37 
38 
39 enum
40 {
41   PROP_0,
42   PROP_TITLE,
43   PROP_ICON_NAME
44 };
45 
46 enum
47 {
48   RESPONSE,
49   DETACH,
50   CLOSE,
51   LAST_SIGNAL
52 };
53 
54 
55 typedef struct _ResponseData ResponseData;
56 
57 struct _ResponseData
58 {
59   gint response_id;
60 };
61 
62 
63 static void       gimp_overlay_dialog_constructed   (GObject           *object);
64 static void       gimp_overlay_dialog_dispose       (GObject           *object);
65 static void       gimp_overlay_dialog_finalize      (GObject           *object);
66 static void       gimp_overlay_dialog_set_property  (GObject           *object,
67                                                      guint              property_id,
68                                                      const GValue      *value,
69                                                      GParamSpec        *pspec);
70 static void       gimp_overlay_dialog_get_property  (GObject           *object,
71                                                      guint              property_id,
72                                                      GValue            *value,
73                                                      GParamSpec        *pspec);
74 
75 static void       gimp_overlay_dialog_size_request  (GtkWidget         *widget,
76                                                      GtkRequisition    *requisition);
77 static void       gimp_overlay_dialog_size_allocate (GtkWidget         *widget,
78                                                      GtkAllocation     *allocation);
79 
80 static void       gimp_overlay_dialog_forall        (GtkContainer      *container,
81                                                      gboolean           include_internals,
82                                                      GtkCallback        callback,
83                                                      gpointer           callback_data);
84 
85 static void       gimp_overlay_dialog_detach        (GimpOverlayDialog *dialog);
86 static void       gimp_overlay_dialog_real_detach   (GimpOverlayDialog *dialog);
87 
88 static void       gimp_overlay_dialog_close         (GimpOverlayDialog *dialog);
89 static void       gimp_overlay_dialog_real_close    (GimpOverlayDialog *dialog);
90 
91 static ResponseData * get_response_data             (GtkWidget         *widget,
92                                                      gboolean          create);
93 
94 
95 G_DEFINE_TYPE (GimpOverlayDialog, gimp_overlay_dialog,
96                GIMP_TYPE_OVERLAY_FRAME)
97 
98 static guint signals[LAST_SIGNAL] = { 0, };
99 
100 #define parent_class gimp_overlay_dialog_parent_class
101 
102 
103 static void
gimp_overlay_dialog_class_init(GimpOverlayDialogClass * klass)104 gimp_overlay_dialog_class_init (GimpOverlayDialogClass *klass)
105 {
106   GObjectClass      *object_class    = G_OBJECT_CLASS (klass);
107   GtkWidgetClass    *widget_class    = GTK_WIDGET_CLASS (klass);
108   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
109 
110   object_class->constructed   = gimp_overlay_dialog_constructed;
111   object_class->dispose       = gimp_overlay_dialog_dispose;
112   object_class->finalize      = gimp_overlay_dialog_finalize;
113   object_class->get_property  = gimp_overlay_dialog_get_property;
114   object_class->set_property  = gimp_overlay_dialog_set_property;
115 
116   widget_class->size_request  = gimp_overlay_dialog_size_request;
117   widget_class->size_allocate = gimp_overlay_dialog_size_allocate;
118 
119   container_class->forall     = gimp_overlay_dialog_forall;
120 
121   klass->detach               = gimp_overlay_dialog_real_detach;
122   klass->close                = gimp_overlay_dialog_real_close;
123 
124   g_object_class_install_property (object_class, PROP_TITLE,
125                                    g_param_spec_string ("title",
126                                                         NULL, NULL,
127                                                         NULL,
128                                                         GIMP_PARAM_READWRITE |
129                                                         G_PARAM_CONSTRUCT));
130 
131   g_object_class_install_property (object_class, PROP_ICON_NAME,
132                                    g_param_spec_string ("icon-name",
133                                                         NULL, NULL,
134                                                         NULL,
135                                                         GIMP_PARAM_READWRITE |
136                                                         G_PARAM_CONSTRUCT));
137 
138   signals[RESPONSE] =
139     g_signal_new ("response",
140                   G_OBJECT_CLASS_TYPE (klass),
141                   G_SIGNAL_RUN_LAST,
142                   G_STRUCT_OFFSET (GimpOverlayDialogClass, response),
143                   NULL, NULL,
144                   gimp_marshal_VOID__INT,
145                   G_TYPE_NONE, 1,
146                   G_TYPE_INT);
147 
148   signals[DETACH] =
149     g_signal_new ("detach",
150                   G_OBJECT_CLASS_TYPE (klass),
151                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
152                   G_STRUCT_OFFSET (GimpOverlayDialogClass, detach),
153                   NULL, NULL,
154                   gimp_marshal_VOID__VOID,
155                   G_TYPE_NONE, 0);
156 
157   signals[CLOSE] =
158     g_signal_new ("close",
159                   G_OBJECT_CLASS_TYPE (klass),
160                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
161                   G_STRUCT_OFFSET (GimpOverlayDialogClass, close),
162                   NULL, NULL,
163                   gimp_marshal_VOID__VOID,
164                   G_TYPE_NONE, 0);
165 
166   gtk_binding_entry_add_signal (gtk_binding_set_by_class (klass),
167                                 GDK_KEY_Escape, 0, "close", 0);
168 }
169 
170 static void
gimp_overlay_dialog_init(GimpOverlayDialog * dialog)171 gimp_overlay_dialog_init (GimpOverlayDialog *dialog)
172 {
173   dialog->header = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
174   gtk_widget_set_parent (dialog->header, GTK_WIDGET (dialog));
175   gtk_widget_show (dialog->header);
176 
177   dialog->action_area = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
178   gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog->action_area),
179                              GTK_BUTTONBOX_END);
180   gtk_widget_set_parent (dialog->action_area, GTK_WIDGET (dialog));
181   gtk_widget_show (dialog->action_area);
182 }
183 
184 static void
gimp_overlay_dialog_constructed(GObject * object)185 gimp_overlay_dialog_constructed (GObject *object)
186 {
187   GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (object);
188   GtkWidget         *label;
189   GtkWidget         *button;
190   GtkWidget         *image;
191 
192   G_OBJECT_CLASS (parent_class)->constructed (object);
193 
194   dialog->icon_image = image = gtk_image_new_from_icon_name (dialog->icon_name,
195                                                              GTK_ICON_SIZE_MENU);
196   gtk_box_pack_start (GTK_BOX (dialog->header), image, FALSE, FALSE, 0);
197   gtk_widget_show (image);
198 
199   dialog->title_label = label = gtk_label_new (dialog->title);
200   gimp_label_set_attributes (GTK_LABEL (label),
201                              PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
202                              -1);
203   gtk_box_pack_start (GTK_BOX (dialog->header), label, TRUE, TRUE, 0);
204   gtk_widget_show (label);
205 
206   dialog->close_button = button = gtk_button_new ();
207   gtk_widget_set_can_focus (button, FALSE);
208   gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
209   gtk_box_pack_end (GTK_BOX (dialog->header), button, FALSE, FALSE, 0);
210   gtk_widget_show (button);
211 
212   image = gtk_image_new_from_icon_name (GIMP_ICON_CLOSE, GTK_ICON_SIZE_MENU);
213   gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
214   gtk_container_add (GTK_CONTAINER (button), image);
215   gtk_widget_show (image);
216 
217   g_signal_connect_object (button, "clicked",
218                            G_CALLBACK (gimp_overlay_dialog_close),
219                            G_OBJECT (dialog),
220                            G_CONNECT_SWAPPED);
221 
222   dialog->detach_button = button = gtk_button_new ();
223   gtk_widget_set_can_focus (button, FALSE);
224   gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
225   gtk_box_pack_end (GTK_BOX (dialog->header), button, FALSE, FALSE, 0);
226   gtk_widget_show (button);
227 
228   gimp_help_set_help_data (dialog->detach_button,
229                            _("Detach dialog from canvas"), NULL);
230 
231   image = gtk_image_new_from_icon_name (GIMP_ICON_DETACH,
232                                         GTK_ICON_SIZE_MENU);
233   gtk_image_set_pixel_size (GTK_IMAGE (image), 12);
234   gtk_container_add (GTK_CONTAINER (button), image);
235   gtk_widget_show (image);
236 
237   g_signal_connect_object (button, "clicked",
238                            G_CALLBACK (gimp_overlay_dialog_detach),
239                            G_OBJECT (dialog),
240                            G_CONNECT_SWAPPED);
241 }
242 
243 static void
gimp_overlay_dialog_dispose(GObject * object)244 gimp_overlay_dialog_dispose (GObject *object)
245 {
246   GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (object);
247 
248   if (dialog->header)
249     {
250       gtk_widget_unparent (dialog->header);
251       dialog->header = NULL;
252     }
253 
254   if (dialog->action_area)
255     {
256       gtk_widget_unparent (dialog->action_area);
257       dialog->action_area = NULL;
258     }
259 
260   G_OBJECT_CLASS (parent_class)->dispose (object);
261 }
262 
263 static void
gimp_overlay_dialog_finalize(GObject * object)264 gimp_overlay_dialog_finalize (GObject *object)
265 {
266   GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (object);
267 
268   g_clear_pointer (&dialog->title,     g_free);
269   g_clear_pointer (&dialog->icon_name, g_free);
270 
271   G_OBJECT_CLASS (parent_class)->finalize (object);
272 }
273 
274 static void
gimp_overlay_dialog_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)275 gimp_overlay_dialog_set_property (GObject      *object,
276                                   guint         property_id,
277                                   const GValue *value,
278                                   GParamSpec   *pspec)
279 {
280   GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (object);
281 
282   switch (property_id)
283     {
284     case PROP_TITLE:
285       g_free (dialog->title);
286       dialog->title = g_value_dup_string (value);
287       if (dialog->title_label)
288         gtk_label_set_text (GTK_LABEL (dialog->title_label), dialog->title);
289       break;
290 
291     case PROP_ICON_NAME:
292       g_free (dialog->icon_name);
293       dialog->icon_name = g_value_dup_string (value);
294       if (dialog->icon_image)
295         gtk_image_set_from_icon_name (GTK_IMAGE (dialog->icon_image),
296                                       dialog->icon_name, GTK_ICON_SIZE_MENU);
297       break;
298 
299     default:
300       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
301       break;
302     }
303 }
304 
305 static void
gimp_overlay_dialog_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)306 gimp_overlay_dialog_get_property (GObject    *object,
307                                   guint       property_id,
308                                   GValue     *value,
309                                   GParamSpec *pspec)
310 {
311   GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (object);
312 
313   switch (property_id)
314     {
315     case PROP_TITLE:
316       g_value_set_string (value, dialog->title);
317       break;
318 
319     case PROP_ICON_NAME:
320       g_value_set_string (value, dialog->icon_name);
321       break;
322 
323    default:
324       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
325       break;
326     }
327 }
328 
329 static void
gimp_overlay_dialog_size_request(GtkWidget * widget,GtkRequisition * requisition)330 gimp_overlay_dialog_size_request (GtkWidget      *widget,
331                                   GtkRequisition *requisition)
332 {
333   GtkContainer      *container = GTK_CONTAINER (widget);
334   GimpOverlayDialog *dialog    = GIMP_OVERLAY_DIALOG (widget);
335   GtkWidget         *child     = gtk_bin_get_child (GTK_BIN (widget));
336   GtkRequisition     child_requisition;
337   GtkRequisition     header_requisition;
338   GtkRequisition     action_requisition;
339   gint               border_width;
340 
341   border_width = gtk_container_get_border_width (container);
342 
343   requisition->width  = border_width * 2;
344   requisition->height = border_width * 2;
345 
346   if (child && gtk_widget_get_visible (child))
347     {
348       gtk_widget_size_request (child, &child_requisition);
349     }
350   else
351     {
352       child_requisition.width  = 0;
353       child_requisition.height = 0;
354     }
355 
356   gtk_widget_size_request (dialog->header,      &header_requisition);
357   gtk_widget_size_request (dialog->action_area, &action_requisition);
358 
359   requisition->width  += MAX (MAX (child_requisition.width,
360                                    action_requisition.width),
361                               header_requisition.width);
362   requisition->height += (child_requisition.height +
363                           2 * border_width +
364                           header_requisition.height +
365                           action_requisition.height);
366 }
367 
368 static void
gimp_overlay_dialog_size_allocate(GtkWidget * widget,GtkAllocation * allocation)369 gimp_overlay_dialog_size_allocate (GtkWidget     *widget,
370                                    GtkAllocation *allocation)
371 {
372   GtkContainer      *container = GTK_CONTAINER (widget);
373   GimpOverlayDialog *dialog    = GIMP_OVERLAY_DIALOG (widget);
374   GtkWidget         *child     = gtk_bin_get_child (GTK_BIN (widget));
375   GtkRequisition     header_requisition;
376   GtkRequisition     action_requisition;
377   GtkAllocation      child_allocation = { 0, };
378   GtkAllocation      header_allocation;
379   GtkAllocation      action_allocation;
380   gint               border_width;
381 
382   gtk_widget_set_allocation (widget, allocation);
383 
384   border_width = gtk_container_get_border_width (container);
385 
386   gtk_widget_size_request (dialog->header,      &header_requisition);
387   gtk_widget_size_request (dialog->action_area, &action_requisition);
388 
389   if (child && gtk_widget_get_visible (child))
390     {
391       child_allocation.x      = allocation->x + border_width;
392       child_allocation.y      = (allocation->y + 2 * border_width +
393                                  header_requisition.height);
394       child_allocation.width  = MAX (allocation->width  - 2 * border_width, 0);
395       child_allocation.height = MAX (allocation->height -
396                                      4 * border_width -
397                                      header_requisition.height -
398                                      action_requisition.height, 0);
399 
400       gtk_widget_size_allocate (child, &child_allocation);
401     }
402 
403   header_allocation.x = allocation->x + border_width;
404   header_allocation.y = allocation->y + border_width;
405   header_allocation.width  = MAX (allocation->width  - 2 * border_width, 0);
406   header_allocation.height = header_requisition.height;
407 
408   gtk_widget_size_allocate (dialog->header, &header_allocation);
409 
410   action_allocation.x = allocation->x + border_width;
411   action_allocation.y = (child_allocation.y + child_allocation.height +
412                          border_width);
413   action_allocation.width  = MAX (allocation->width  - 2 * border_width, 0);
414   action_allocation.height = action_requisition.height;
415 
416   gtk_widget_size_allocate (dialog->action_area, &action_allocation);
417 }
418 
419 static void
gimp_overlay_dialog_forall(GtkContainer * container,gboolean include_internals,GtkCallback callback,gpointer callback_data)420 gimp_overlay_dialog_forall (GtkContainer *container,
421                             gboolean      include_internals,
422                             GtkCallback   callback,
423                             gpointer      callback_data)
424 {
425   GTK_CONTAINER_CLASS (parent_class)->forall (container, include_internals,
426                                               callback, callback_data);
427 
428   if (include_internals)
429     {
430       GimpOverlayDialog *dialog = GIMP_OVERLAY_DIALOG (container);
431 
432       if (dialog->header)
433         (* callback) (dialog->header, callback_data);
434 
435       if (dialog->action_area)
436         (* callback) (dialog->action_area, callback_data);
437     }
438 }
439 
440 static void
gimp_overlay_dialog_detach(GimpOverlayDialog * dialog)441 gimp_overlay_dialog_detach (GimpOverlayDialog *dialog)
442 {
443   g_signal_emit (dialog, signals[DETACH], 0);
444 }
445 
446 static void
gimp_overlay_dialog_real_detach(GimpOverlayDialog * dialog)447 gimp_overlay_dialog_real_detach (GimpOverlayDialog *dialog)
448 {
449   gimp_overlay_dialog_response (dialog, GIMP_RESPONSE_DETACH);
450 }
451 
452 static void
gimp_overlay_dialog_close(GimpOverlayDialog * dialog)453 gimp_overlay_dialog_close (GimpOverlayDialog *dialog)
454 {
455   g_signal_emit (dialog, signals[CLOSE], 0);
456 }
457 
458 static void
gimp_overlay_dialog_real_close(GimpOverlayDialog * dialog)459 gimp_overlay_dialog_real_close (GimpOverlayDialog *dialog)
460 {
461   gimp_overlay_dialog_response (dialog, GTK_RESPONSE_DELETE_EVENT);
462 }
463 
464 GtkWidget *
gimp_overlay_dialog_new(GimpToolInfo * tool_info,const gchar * desc,...)465 gimp_overlay_dialog_new (GimpToolInfo *tool_info,
466                          const gchar  *desc,
467                          ...)
468 {
469   GimpOverlayDialog *dialog;
470   const gchar       *icon_name;
471   va_list            args;
472 
473   g_return_val_if_fail (GIMP_IS_TOOL_INFO (tool_info), NULL);
474 
475   icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));
476 
477   dialog = g_object_new (GIMP_TYPE_OVERLAY_DIALOG,
478                          "title",     tool_info->label,
479                          "icon-name", icon_name,
480                          NULL);
481 
482   va_start (args, desc);
483   gimp_overlay_dialog_add_buttons_valist (dialog, args);
484   va_end (args);
485 
486   return GTK_WIDGET (dialog);
487 }
488 
489 void
gimp_overlay_dialog_response(GimpOverlayDialog * dialog,gint response_id)490 gimp_overlay_dialog_response (GimpOverlayDialog *dialog,
491                               gint               response_id)
492 {
493   g_return_if_fail (GIMP_IS_OVERLAY_DIALOG (dialog));
494 
495   g_signal_emit (dialog, signals[RESPONSE], 0,
496                  response_id);
497 }
498 
499 void
gimp_overlay_dialog_add_buttons_valist(GimpOverlayDialog * dialog,va_list args)500 gimp_overlay_dialog_add_buttons_valist (GimpOverlayDialog *dialog,
501                                         va_list            args)
502 {
503   const gchar *button_text;
504   gint         response_id;
505 
506   g_return_if_fail (GIMP_IS_OVERLAY_DIALOG (dialog));
507 
508   while ((button_text = va_arg (args, const gchar *)))
509     {
510       response_id = va_arg (args, gint);
511 
512       gimp_overlay_dialog_add_button (dialog, button_text, response_id);
513     }
514 }
515 
516 static void
action_widget_activated(GtkWidget * widget,GimpOverlayDialog * dialog)517 action_widget_activated (GtkWidget         *widget,
518                          GimpOverlayDialog *dialog)
519 {
520   ResponseData *ad = get_response_data (widget, FALSE);
521 
522   gimp_overlay_dialog_response (dialog, ad->response_id);
523 }
524 
525 GtkWidget *
gimp_overlay_dialog_add_button(GimpOverlayDialog * dialog,const gchar * button_text,gint response_id)526 gimp_overlay_dialog_add_button (GimpOverlayDialog *dialog,
527                                 const gchar       *button_text,
528                                 gint               response_id)
529 {
530   GtkWidget    *button;
531   ResponseData *ad;
532   guint         signal_id;
533   GClosure     *closure;
534 
535   g_return_val_if_fail (GIMP_IS_OVERLAY_DIALOG (dialog), NULL);
536   g_return_val_if_fail (button_text != NULL, NULL);
537 
538   if (response_id == GTK_RESPONSE_CANCEL ||
539       response_id == GTK_RESPONSE_CLOSE  ||
540       response_id == GIMP_RESPONSE_DETACH)
541     return NULL;
542 
543   button = gtk_button_new_with_mnemonic (button_text);
544   gtk_widget_set_can_default (button, TRUE);
545   gtk_widget_show (button);
546 
547   ad = get_response_data (button, TRUE);
548 
549   ad->response_id = response_id;
550 
551   signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
552 
553   closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
554                                    G_OBJECT (dialog));
555   g_signal_connect_closure_by_id (button, signal_id, 0,
556                                   closure, FALSE);
557 
558   gtk_box_pack_end (GTK_BOX (dialog->action_area), button, FALSE, TRUE, 0);
559 
560   if (response_id == GTK_RESPONSE_HELP)
561     gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (dialog->action_area),
562                                         button, TRUE);
563 
564   return button;
565 }
566 
567 void
gimp_overlay_dialog_set_alternative_button_order(GimpOverlayDialog * overlay,gint n_ids,gint * ids)568 gimp_overlay_dialog_set_alternative_button_order (GimpOverlayDialog *overlay,
569                                                   gint               n_ids,
570                                                   gint              *ids)
571 {
572   /* TODO */
573 }
574 
575 void
gimp_overlay_dialog_set_default_response(GimpOverlayDialog * overlay,gint response_id)576 gimp_overlay_dialog_set_default_response (GimpOverlayDialog *overlay,
577                                           gint               response_id)
578 {
579   /* TODO */
580 }
581 
582 void
gimp_overlay_dialog_set_response_sensitive(GimpOverlayDialog * overlay,gint response_id,gboolean sensitive)583 gimp_overlay_dialog_set_response_sensitive (GimpOverlayDialog *overlay,
584                                             gint               response_id,
585                                             gboolean           sensitive)
586 {
587   GList *children;
588   GList *list;
589 
590   g_return_if_fail (GIMP_IS_OVERLAY_DIALOG (overlay));
591 
592   if (response_id == GTK_RESPONSE_CANCEL ||
593       response_id == GTK_RESPONSE_CLOSE)
594     {
595       gtk_widget_set_sensitive (overlay->close_button, sensitive);
596     }
597 
598   if (response_id == GIMP_RESPONSE_DETACH)
599     {
600       gtk_widget_set_sensitive (overlay->detach_button, sensitive);
601     }
602 
603   children = gtk_container_get_children (GTK_CONTAINER (overlay->action_area));
604 
605   for (list = children; list; list = g_list_next (list))
606     {
607       GtkWidget    *child = list->data;
608       ResponseData *ad    = get_response_data (child, FALSE);
609 
610       if (ad && ad->response_id == response_id)
611         {
612           gtk_widget_set_sensitive (child, sensitive);
613           break;
614         }
615     }
616 
617   g_list_free (children);
618 }
619 
620 static void
response_data_free(gpointer data)621 response_data_free (gpointer data)
622 {
623   g_slice_free (ResponseData, data);
624 }
625 
626 static ResponseData *
get_response_data(GtkWidget * widget,gboolean create)627 get_response_data (GtkWidget *widget,
628                    gboolean   create)
629 {
630   ResponseData *ad = g_object_get_data (G_OBJECT (widget),
631                                         "gimp-overlay-dialog-response-data");
632 
633   if (! ad && create)
634     {
635       ad = g_slice_new (ResponseData);
636 
637       g_object_set_data_full (G_OBJECT (widget),
638                               "gimp-overlay-dialog-response-data",
639                               ad, response_data_free);
640     }
641 
642   return ad;
643 }
644