1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpwidgets/gimpwidgets.h"
24 
25 #include "widgets-types.h"
26 
27 #include "config/gimpconfig-utils.h"
28 
29 #include "core/gimp.h"
30 #include "core/gimpcontainer.h"
31 #include "core/gimpcontext.h"
32 #include "core/gimpdatafactory.h"
33 
34 #include "gimpcontainerentry.h"
35 #include "gimpdialogfactory.h"
36 #include "gimppropwidgets.h"
37 #include "gimpview.h"
38 #include "gimpviewablebutton.h"
39 #include "gimpviewablebox.h"
40 #include "gimpviewrenderergradient.h"
41 #include "gimpwidgets-utils.h"
42 #include "gimpwindowstrategy.h"
43 
44 #include "gimp-intl.h"
45 
46 
47 /*  local function prototypes  */
48 
49 static GtkWidget * gimp_viewable_box_new       (GimpContainer *container,
50                                                 GimpContext   *context,
51                                                 const gchar   *label,
52                                                 gint           spacing,
53                                                 GimpViewType   view_type,
54                                                 GimpViewSize   button_view_size,
55                                                 GimpViewSize   view_size,
56                                                 const gchar   *dialog_identifier,
57                                                 const gchar   *dialog_icon_name,
58                                                 const gchar   *dialog_tooltip,
59                                                 const gchar   *editor_id,
60                                                 const gchar   *editor_tooltip);
61 static GtkWidget * view_props_connect          (GtkWidget     *box,
62                                                 GimpContext   *context,
63                                                 const gchar   *view_type_prop,
64                                                 const gchar   *view_size_prop);
65 static void   gimp_viewable_box_edit_clicked   (GtkWidget          *widget,
66                                                 GimpViewableButton *button);
67 static void   gimp_gradient_box_reverse_notify (GObject       *object,
68                                                 GParamSpec    *pspec,
69                                                 GimpView      *view);
70 static void   gimp_gradient_box_blend_notify   (GObject       *object,
71                                                 GParamSpec    *pspec,
72                                                 GimpView      *view);
73 
74 
75 /*  brush boxes  */
76 
77 static GtkWidget *
brush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size,const gchar * editor_id,const gchar * editor_tooltip)78 brush_box_new (GimpContainer *container,
79                GimpContext   *context,
80                const gchar   *label,
81                gint           spacing,
82                GimpViewType   view_type,
83                GimpViewSize   view_size,
84                const gchar   *editor_id,
85                const gchar   *editor_tooltip)
86 {
87   if (! container)
88     container = gimp_data_factory_get_container (context->gimp->brush_factory);
89 
90   return gimp_viewable_box_new (container, context, label, spacing,
91                                 view_type, GIMP_VIEW_SIZE_SMALL, view_size,
92                                 "gimp-brush-grid|gimp-brush-list",
93                                 GIMP_ICON_BRUSH,
94                                 _("Open the brush selection dialog"),
95                                 editor_id, editor_tooltip);
96 }
97 
98 GtkWidget *
gimp_brush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)99 gimp_brush_box_new (GimpContainer *container,
100                     GimpContext   *context,
101                     const gchar   *label,
102                     gint           spacing)
103 {
104   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
105                         NULL);
106   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
107 
108   return brush_box_new (container, context, label, spacing,
109                         GIMP_VIEW_TYPE_GRID, GIMP_VIEW_SIZE_SMALL,
110                         NULL, NULL);
111 }
112 
113 GtkWidget *
gimp_prop_brush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop,const gchar * editor_id,const gchar * editor_tooltip)114 gimp_prop_brush_box_new (GimpContainer *container,
115                          GimpContext   *context,
116                          const gchar   *label,
117                          gint           spacing,
118                          const gchar   *view_type_prop,
119                          const gchar   *view_size_prop,
120                          const gchar   *editor_id,
121                          const gchar   *editor_tooltip)
122 {
123   GimpViewType view_type;
124   GimpViewSize view_size;
125 
126   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
127                         NULL);
128   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
129 
130   g_object_get (context,
131                 view_type_prop, &view_type,
132                 view_size_prop, &view_size,
133                 NULL);
134 
135   return view_props_connect (brush_box_new (container, context, label, spacing,
136                                             view_type, view_size,
137                                             editor_id, editor_tooltip),
138                              context,
139                              view_type_prop, view_size_prop);
140 }
141 
142 
143 /*  dynamics boxes  */
144 
145 static GtkWidget *
dynamics_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size,const gchar * editor_id,const gchar * editor_tooltip)146 dynamics_box_new (GimpContainer *container,
147                   GimpContext   *context,
148                   const gchar   *label,
149                   gint           spacing,
150                   GimpViewType   view_type,
151                   GimpViewSize   view_size,
152                   const gchar   *editor_id,
153                   const gchar   *editor_tooltip)
154 {
155   if (! container)
156     container = gimp_data_factory_get_container (context->gimp->dynamics_factory);
157 
158   return gimp_viewable_box_new (container, context, label, spacing,
159                                 view_type, GIMP_VIEW_SIZE_SMALL, view_size,
160                                 "gimp-dynamics-list|gimp-dynamics-grid",
161                                 GIMP_ICON_DYNAMICS,
162                                 _("Open the dynamics selection dialog"),
163                                 editor_id, editor_tooltip);
164 }
165 
166 GtkWidget *
gimp_dynamics_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)167 gimp_dynamics_box_new (GimpContainer *container,
168                        GimpContext   *context,
169                        const gchar   *label,
170                        gint           spacing)
171 {
172   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
173                         NULL);
174   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
175 
176   return dynamics_box_new (container, context, label, spacing,
177                            GIMP_VIEW_TYPE_LIST, GIMP_VIEW_SIZE_SMALL,
178                            NULL, NULL);
179 }
180 
181 GtkWidget *
gimp_prop_dynamics_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop,const gchar * editor_id,const gchar * editor_tooltip)182 gimp_prop_dynamics_box_new (GimpContainer *container,
183                             GimpContext   *context,
184                             const gchar   *label,
185                             gint           spacing,
186                             const gchar   *view_type_prop,
187                             const gchar   *view_size_prop,
188                             const gchar   *editor_id,
189                             const gchar   *editor_tooltip)
190 {
191   GimpViewType view_type;
192   GimpViewSize view_size;
193 
194   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
195                         NULL);
196   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
197 
198   g_object_get (context,
199                 view_type_prop, &view_type,
200                 view_size_prop, &view_size,
201                 NULL);
202 
203   return view_props_connect (dynamics_box_new (container, context, label,
204                                                spacing,
205                                                view_type, view_size,
206                                                editor_id, editor_tooltip),
207                              context,
208                              view_type_prop, view_size_prop);
209 }
210 
211 
212 /*  brush boxes  */
213 
214 static GtkWidget *
mybrush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size)215 mybrush_box_new (GimpContainer *container,
216                  GimpContext   *context,
217                  const gchar   *label,
218                  gint           spacing,
219                  GimpViewType   view_type,
220                  GimpViewSize   view_size)
221 {
222   if (! container)
223     container = gimp_data_factory_get_container (context->gimp->mybrush_factory);
224 
225   return gimp_viewable_box_new (container, context, label, spacing,
226                                 view_type, GIMP_VIEW_SIZE_LARGE, view_size,
227                                 "gimp-mypaint-brush-grid|gimp-mypaint-brush-list",
228                                 GIMP_ICON_BRUSH,
229                                 _("Open the MyPaint brush selection dialog"),
230                                 NULL, NULL);
231 }
232 
233 GtkWidget *
gimp_mybrush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)234 gimp_mybrush_box_new (GimpContainer *container,
235                       GimpContext   *context,
236                       const gchar   *label,
237                       gint           spacing)
238 {
239   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
240                         NULL);
241   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
242 
243   return mybrush_box_new (container, context, label, spacing,
244                           GIMP_VIEW_TYPE_GRID, GIMP_VIEW_SIZE_LARGE);
245 }
246 
247 GtkWidget *
gimp_prop_mybrush_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop)248 gimp_prop_mybrush_box_new (GimpContainer *container,
249                            GimpContext   *context,
250                            const gchar   *label,
251                            gint           spacing,
252                            const gchar   *view_type_prop,
253                            const gchar   *view_size_prop)
254 {
255   GimpViewType view_type = GIMP_VIEW_TYPE_GRID;
256   GimpViewSize view_size = GIMP_VIEW_SIZE_LARGE;
257 
258   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
259                         NULL);
260   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
261 
262   if (view_type_prop && view_size_prop)
263     g_object_get (context,
264                   view_type_prop, &view_type,
265                   view_size_prop, &view_size,
266                   NULL);
267 
268   return view_props_connect (mybrush_box_new (container, context, label, spacing,
269                                               view_type, view_size),
270                              context,
271                              view_type_prop, view_size_prop);
272 }
273 
274 
275 /*  pattern boxes  */
276 
277 static GtkWidget *
pattern_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size)278 pattern_box_new (GimpContainer *container,
279                  GimpContext   *context,
280                  const gchar   *label,
281                  gint           spacing,
282                  GimpViewType   view_type,
283                  GimpViewSize   view_size)
284 {
285   if (! container)
286     container = gimp_data_factory_get_container (context->gimp->pattern_factory);
287 
288   return gimp_viewable_box_new (container, context, label, spacing,
289                                 view_type, GIMP_VIEW_SIZE_SMALL, view_size,
290                                 "gimp-pattern-grid|gimp-pattern-list",
291                                 GIMP_ICON_PATTERN,
292                                 _("Open the pattern selection dialog"),
293                                 NULL, NULL);
294 }
295 
296 GtkWidget *
gimp_pattern_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)297 gimp_pattern_box_new (GimpContainer *container,
298                       GimpContext   *context,
299                       const gchar   *label,
300                       gint           spacing)
301 {
302   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
303                         NULL);
304   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
305 
306   return pattern_box_new (container, context, label, spacing,
307                           GIMP_VIEW_TYPE_GRID, GIMP_VIEW_SIZE_SMALL);
308 }
309 
310 GtkWidget *
gimp_prop_pattern_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop)311 gimp_prop_pattern_box_new (GimpContainer *container,
312                            GimpContext   *context,
313                            const gchar   *label,
314                            gint           spacing,
315                            const gchar   *view_type_prop,
316                            const gchar   *view_size_prop)
317 {
318   GimpViewType view_type;
319   GimpViewSize view_size;
320 
321   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
322                         NULL);
323   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
324 
325   g_object_get (context,
326                 view_type_prop, &view_type,
327                 view_size_prop, &view_size,
328                 NULL);
329 
330   return view_props_connect (pattern_box_new (container, context, label, spacing,
331                                               view_type, view_size),
332                              context,
333                              view_type_prop, view_size_prop);
334 }
335 
336 
337 /*  gradient boxes  */
338 
339 static GtkWidget *
gradient_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size,const gchar * reverse_prop,const gchar * blend_color_space_prop,const gchar * editor_id,const gchar * editor_tooltip)340 gradient_box_new (GimpContainer *container,
341                   GimpContext   *context,
342                   const gchar   *label,
343                   gint           spacing,
344                   GimpViewType   view_type,
345                   GimpViewSize   view_size,
346                   const gchar   *reverse_prop,
347                   const gchar   *blend_color_space_prop,
348                   const gchar   *editor_id,
349                   const gchar   *editor_tooltip)
350 {
351   GtkWidget *hbox;
352   GtkWidget *button;
353   GList     *children;
354 
355   if (! container)
356     container = gimp_data_factory_get_container (context->gimp->gradient_factory);
357 
358   hbox = gimp_viewable_box_new (container, context, label, spacing,
359                                 view_type, GIMP_VIEW_SIZE_SMALL, view_size,
360                                 "gimp-gradient-list|gimp-gradient-grid",
361                                 GIMP_ICON_GRADIENT,
362                                 _("Open the gradient selection dialog"),
363                                 editor_id, editor_tooltip);
364 
365   children = gtk_container_get_children (GTK_CONTAINER (hbox));
366   button = children->data;
367   g_list_free (children);
368 
369   GIMP_VIEWABLE_BUTTON (button)->button_view_size = GIMP_VIEW_SIZE_SMALL;
370 
371   if (reverse_prop)
372     {
373       GtkWidget *toggle;
374       GtkWidget *view;
375       GtkWidget *image;
376       gchar     *signal_name;
377 
378       toggle = gimp_prop_check_button_new (G_OBJECT (context), reverse_prop,
379                                            NULL);
380       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (toggle), FALSE);
381       gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
382       gtk_box_reorder_child (GTK_BOX (hbox), toggle, 1);
383       gtk_widget_show (toggle);
384 
385       gimp_help_set_help_data (toggle, _("Reverse"), NULL);
386 
387       image = gtk_image_new_from_icon_name (GIMP_ICON_OBJECT_FLIP_HORIZONTAL,
388                                             GTK_ICON_SIZE_MENU);
389       /* gimp_prop_check_button_new() adds the property nick as label of
390        * the button by default. */
391       gtk_container_remove (GTK_CONTAINER (toggle),
392                             gtk_bin_get_child (GTK_BIN (toggle)));
393       gtk_container_add (GTK_CONTAINER (toggle), image);
394       gtk_widget_show (image);
395 
396       view = gtk_bin_get_child (GTK_BIN (button));
397 
398       signal_name = g_strconcat ("notify::", reverse_prop, NULL);
399       g_signal_connect_object (context, signal_name,
400                                G_CALLBACK (gimp_gradient_box_reverse_notify),
401                                G_OBJECT (view), 0);
402       g_free (signal_name);
403 
404       gimp_gradient_box_reverse_notify (G_OBJECT (context),
405                                         NULL,
406                                         GIMP_VIEW (view));
407     }
408 
409   if (blend_color_space_prop)
410     {
411       GtkWidget *view;
412       gchar     *signal_name;
413 
414       view = gtk_bin_get_child (GTK_BIN (button));
415 
416       signal_name = g_strconcat ("notify::", blend_color_space_prop, NULL);
417       g_signal_connect_object (context, signal_name,
418                                G_CALLBACK (gimp_gradient_box_blend_notify),
419                                G_OBJECT (view), 0);
420       g_free (signal_name);
421 
422       gimp_gradient_box_blend_notify (G_OBJECT (context),
423                                       NULL,
424                                       GIMP_VIEW (view));
425     }
426 
427   return hbox;
428 }
429 
430 GtkWidget *
gimp_gradient_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * reverse_prop,const gchar * blend_color_space_prop)431 gimp_gradient_box_new (GimpContainer *container,
432                        GimpContext   *context,
433                        const gchar   *label,
434                        gint           spacing,
435                        const gchar   *reverse_prop,
436                        const gchar   *blend_color_space_prop)
437 {
438   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
439                         NULL);
440   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
441 
442   return gradient_box_new (container, context, label, spacing,
443                            GIMP_VIEW_TYPE_LIST, GIMP_VIEW_SIZE_LARGE,
444                            reverse_prop, blend_color_space_prop,
445                            NULL, NULL);
446 }
447 
448 GtkWidget *
gimp_prop_gradient_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop,const gchar * reverse_prop,const gchar * blend_color_space_prop,const gchar * editor_id,const gchar * editor_tooltip)449 gimp_prop_gradient_box_new (GimpContainer *container,
450                             GimpContext   *context,
451                             const gchar   *label,
452                             gint           spacing,
453                             const gchar   *view_type_prop,
454                             const gchar   *view_size_prop,
455                             const gchar   *reverse_prop,
456                             const gchar   *blend_color_space_prop,
457                             const gchar   *editor_id,
458                             const gchar   *editor_tooltip)
459 {
460   GimpViewType view_type;
461   GimpViewSize view_size;
462 
463   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
464                         NULL);
465   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
466 
467   g_object_get (context,
468                 view_type_prop, &view_type,
469                 view_size_prop, &view_size,
470                 NULL);
471 
472   return view_props_connect (gradient_box_new (container, context, label, spacing,
473                                                view_type, view_size,
474                                                reverse_prop,
475                                                blend_color_space_prop,
476                                                editor_id, editor_tooltip),
477                              context,
478                              view_type_prop, view_size_prop);
479 }
480 
481 
482 /*  palette boxes  */
483 
484 static GtkWidget *
palette_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size,const gchar * editor_id,const gchar * editor_tooltip)485 palette_box_new (GimpContainer *container,
486                  GimpContext   *context,
487                  const gchar   *label,
488                  gint           spacing,
489                  GimpViewType   view_type,
490                  GimpViewSize   view_size,
491                  const gchar   *editor_id,
492                  const gchar   *editor_tooltip)
493 {
494   if (! container)
495     container = gimp_data_factory_get_container (context->gimp->palette_factory);
496 
497   return gimp_viewable_box_new (container, context, label, spacing,
498                                 view_type, GIMP_VIEW_SIZE_MEDIUM, view_size,
499                                 "gimp-palette-list|gimp-palette-grid",
500                                 GIMP_ICON_PALETTE,
501                                 _("Open the palette selection dialog"),
502                                 editor_id, editor_tooltip);
503 }
504 
505 GtkWidget *
gimp_palette_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)506 gimp_palette_box_new (GimpContainer *container,
507                       GimpContext   *context,
508                       const gchar   *label,
509                       gint           spacing)
510 {
511   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
512                         NULL);
513   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
514 
515   return palette_box_new (container, context, label, spacing,
516                           GIMP_VIEW_TYPE_LIST, GIMP_VIEW_SIZE_MEDIUM,
517                           NULL, NULL);
518 }
519 
520 GtkWidget *
gimp_prop_palette_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop,const gchar * editor_id,const gchar * editor_tooltip)521 gimp_prop_palette_box_new (GimpContainer *container,
522                            GimpContext   *context,
523                            const gchar   *label,
524                            gint           spacing,
525                            const gchar   *view_type_prop,
526                            const gchar   *view_size_prop,
527                            const gchar   *editor_id,
528                            const gchar   *editor_tooltip)
529 {
530   GimpViewType view_type;
531   GimpViewSize view_size;
532 
533   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
534                         NULL);
535   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
536 
537   g_object_get (context,
538                 view_type_prop, &view_type,
539                 view_size_prop, &view_size,
540                 NULL);
541 
542   return view_props_connect (palette_box_new (container, context, label, spacing,
543                                               view_type, view_size,
544                                               editor_id, editor_tooltip),
545                              context,
546                              view_type_prop, view_size_prop);
547 }
548 
549 
550 /*  font boxes  */
551 
552 static GtkWidget *
font_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize view_size)553 font_box_new (GimpContainer *container,
554               GimpContext   *context,
555               const gchar   *label,
556               gint           spacing,
557               GimpViewType   view_type,
558               GimpViewSize   view_size)
559 {
560   if (! container)
561     container = gimp_data_factory_get_container (context->gimp->font_factory);
562 
563   return gimp_viewable_box_new (container, context, label, spacing,
564                                 view_type, GIMP_VIEW_SIZE_SMALL, view_size,
565                                 "gimp-font-list|gimp-font-grid",
566                                 GIMP_ICON_FONT,
567                                 _("Open the font selection dialog"),
568                                 NULL, NULL);
569 }
570 
571 GtkWidget *
gimp_font_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing)572 gimp_font_box_new (GimpContainer *container,
573                    GimpContext   *context,
574                    const gchar   *label,
575                    gint           spacing)
576 {
577   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
578                         NULL);
579   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
580 
581   return font_box_new (container, context, label, spacing,
582                        GIMP_VIEW_TYPE_LIST, GIMP_VIEW_SIZE_SMALL);
583 }
584 
585 GtkWidget *
gimp_prop_font_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,const gchar * view_type_prop,const gchar * view_size_prop)586 gimp_prop_font_box_new (GimpContainer *container,
587                         GimpContext   *context,
588                         const gchar   *label,
589                         gint           spacing,
590                         const gchar   *view_type_prop,
591                         const gchar   *view_size_prop)
592 {
593   GimpViewType view_type;
594   GimpViewSize view_size;
595 
596   g_return_val_if_fail (container == NULL || GIMP_IS_CONTAINER (container),
597                         NULL);
598   g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
599 
600   g_object_get (context,
601                 view_type_prop, &view_type,
602                 view_size_prop, &view_size,
603                 NULL);
604 
605   return view_props_connect (font_box_new (container, context, label, spacing,
606                                            view_type, view_size),
607                              context,
608                              view_type_prop, view_size_prop);
609 }
610 
611 
612 /*  private functions  */
613 
614 static GtkWidget *
gimp_viewable_box_new(GimpContainer * container,GimpContext * context,const gchar * label,gint spacing,GimpViewType view_type,GimpViewSize button_view_size,GimpViewSize view_size,const gchar * dialog_identifier,const gchar * dialog_icon_name,const gchar * dialog_tooltip,const gchar * editor_id,const gchar * editor_tooltip)615 gimp_viewable_box_new (GimpContainer *container,
616                        GimpContext   *context,
617                        const gchar   *label,
618                        gint           spacing,
619                        GimpViewType   view_type,
620                        GimpViewSize   button_view_size,
621                        GimpViewSize   view_size,
622                        const gchar   *dialog_identifier,
623                        const gchar   *dialog_icon_name,
624                        const gchar   *dialog_tooltip,
625                        const gchar   *editor_id,
626                        const gchar   *editor_tooltip)
627 {
628   GtkWidget *hbox;
629   GtkWidget *button;
630   GtkWidget *vbox;
631   GtkWidget *l;
632   GtkWidget *entry;
633 
634   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, spacing);
635 
636   button = gimp_viewable_button_new (container, context,
637                                      view_type, button_view_size, view_size, 1,
638                                      gimp_dialog_factory_get_singleton (),
639                                      dialog_identifier,
640                                      dialog_icon_name,
641                                      dialog_tooltip);
642 
643   gimp_view_renderer_set_size_full (GIMP_VIEW (GIMP_VIEWABLE_BUTTON (button)->view)->renderer,
644                                     button_view_size, button_view_size, 1);
645 
646   g_object_set_data (G_OBJECT (hbox), "viewable-button", button);
647 
648   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
649   gtk_widget_show (button);
650 
651   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
652   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
653   gtk_widget_show (vbox);
654 
655   if (label)
656     {
657       l = gtk_label_new_with_mnemonic (label);
658       gtk_label_set_xalign (GTK_LABEL (l), 0.0);
659       gtk_box_pack_start (GTK_BOX (vbox), l, FALSE, FALSE, 0);
660       gtk_widget_show (l);
661     }
662 
663   entry = gimp_container_entry_new (container, context, view_size, 1);
664 
665   /*  set a silly smally size request on the entry to disable
666    *  GtkEntry's minimal width of 150 pixels.
667    */
668   gtk_entry_set_width_chars (GTK_ENTRY (entry), 4);
669   gtk_box_pack_end (GTK_BOX (vbox), entry, label ? FALSE : TRUE, FALSE, 0);
670   gtk_widget_show (entry);
671 
672   if (editor_id)
673     {
674       GtkWidget *edit_button;
675       GtkWidget *image;
676 
677       edit_button = gtk_button_new ();
678       gtk_button_set_relief (GTK_BUTTON (edit_button), GTK_RELIEF_NONE);
679       gtk_box_pack_end (GTK_BOX (hbox), edit_button, FALSE, FALSE, 0);
680       gtk_widget_show (edit_button);
681 
682       if (editor_tooltip)
683         gimp_help_set_help_data (edit_button, editor_tooltip, NULL);
684 
685       image = gtk_image_new_from_icon_name (GIMP_ICON_EDIT,
686                                             GTK_ICON_SIZE_BUTTON);
687       gtk_misc_set_alignment (GTK_MISC (image), 0.5, 1.0);
688       gtk_container_add (GTK_CONTAINER (edit_button), image);
689       gtk_widget_show (image);
690 
691       g_object_set_data_full (G_OBJECT (button),
692                               "gimp-viewable-box-editor",
693                               g_strdup (editor_id),
694                               (GDestroyNotify) g_free);
695 
696       g_signal_connect (edit_button, "clicked",
697                         G_CALLBACK (gimp_viewable_box_edit_clicked),
698                         button);
699     }
700 
701   return hbox;
702 }
703 
704 static GtkWidget *
view_props_connect(GtkWidget * box,GimpContext * context,const gchar * view_type_prop,const gchar * view_size_prop)705 view_props_connect (GtkWidget   *box,
706                     GimpContext *context,
707                     const gchar *view_type_prop,
708                     const gchar *view_size_prop)
709 {
710   GtkWidget *button = g_object_get_data (G_OBJECT (box), "viewable-button");
711 
712   if (view_type_prop)
713     gimp_config_connect_full (G_OBJECT (context), G_OBJECT (button),
714                               view_type_prop, "popup-view-type");
715 
716   if (view_size_prop)
717     gimp_config_connect_full (G_OBJECT (context), G_OBJECT (button),
718                               view_size_prop, "popup-view-size");
719 
720   return box;
721 }
722 
723 static void
gimp_viewable_box_edit_clicked(GtkWidget * widget,GimpViewableButton * button)724 gimp_viewable_box_edit_clicked (GtkWidget          *widget,
725                                 GimpViewableButton *button)
726 {
727   const gchar *editor_id = g_object_get_data (G_OBJECT (button),
728                                               "gimp-viewable-box-editor");
729 
730   gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (button->context->gimp)),
731                                              button->context->gimp,
732                                              gimp_dialog_factory_get_singleton (),
733                                              gtk_widget_get_screen (widget),
734                                              gimp_widget_get_monitor (widget),
735                                              editor_id);
736 }
737 
738 static void
gimp_gradient_box_reverse_notify(GObject * object,GParamSpec * pspec,GimpView * view)739 gimp_gradient_box_reverse_notify (GObject    *object,
740                                   GParamSpec *pspec,
741                                   GimpView   *view)
742 {
743   GimpViewRendererGradient *rendergrad;
744   gboolean                  reverse;
745 
746   rendergrad = GIMP_VIEW_RENDERER_GRADIENT (view->renderer);
747 
748   g_object_get (object, "gradient-reverse", &reverse, NULL);
749 
750   gimp_view_renderer_gradient_set_reverse (rendergrad, reverse);
751 }
752 
753 static void
gimp_gradient_box_blend_notify(GObject * object,GParamSpec * pspec,GimpView * view)754 gimp_gradient_box_blend_notify (GObject    *object,
755                                 GParamSpec *pspec,
756                                 GimpView   *view)
757 {
758   GimpViewRendererGradient    *rendergrad;
759   GimpGradientBlendColorSpace  blend_color_space;
760 
761   rendergrad = GIMP_VIEW_RENDERER_GRADIENT (view->renderer);
762 
763   g_object_get (object,
764                 "gradient-blend-color-space", &blend_color_space,
765                 NULL);
766 
767   gimp_view_renderer_gradient_set_blend_color_space (rendergrad,
768                                                      blend_color_space);
769 }
770