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 <string.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #include "libgimpmath/gimpmath.h"
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpconfig/gimpconfig.h"
28 #include "libgimpwidgets/gimpwidgets.h"
29 
30 #include "widgets-types.h"
31 
32 #include "config/gimpcoreconfig.h"
33 
34 #include "gegl/gimp-babl.h"
35 
36 #include "core/gimp.h"
37 #include "core/gimptemplate.h"
38 
39 #include "gimppropwidgets.h"
40 #include "gimptemplateeditor.h"
41 #include "gimpwidgets-utils.h"
42 
43 #include "gimp-intl.h"
44 
45 
46 #define SB_WIDTH            8
47 #define MAX_COMMENT_LENGTH  512  /* arbitrary */
48 
49 
50 enum
51 {
52   PROP_0,
53   PROP_GIMP,
54   PROP_TEMPLATE
55 };
56 
57 
58 typedef struct _GimpTemplateEditorPrivate GimpTemplateEditorPrivate;
59 
60 struct _GimpTemplateEditorPrivate
61 {
62   Gimp          *gimp;
63 
64   GimpTemplate  *template;
65 
66   GtkWidget     *aspect_button;
67   gboolean       block_aspect;
68 
69   GtkWidget     *expander;
70   GtkWidget     *size_se;
71   GtkWidget     *memsize_label;
72   GtkWidget     *pixel_label;
73   GtkWidget     *more_label;
74   GtkWidget     *resolution_se;
75   GtkWidget     *chain_button;
76   GtkWidget     *precision_combo;
77   GtkWidget     *profile_combo;
78 };
79 
80 #define GET_PRIVATE(editor) \
81         ((GimpTemplateEditorPrivate *) gimp_template_editor_get_instance_private ((GimpTemplateEditor *) (editor)))
82 
83 
84 static void    gimp_template_editor_constructed    (GObject            *object);
85 static void    gimp_template_editor_finalize       (GObject            *object);
86 static void    gimp_template_editor_set_property   (GObject            *object,
87                                                     guint               property_id,
88                                                     const GValue       *value,
89                                                     GParamSpec         *pspec);
90 static void    gimp_template_editor_get_property   (GObject            *object,
91                                                     guint               property_id,
92                                                     GValue             *value,
93                                                     GParamSpec         *pspec);
94 
95 static void gimp_template_editor_precision_changed (GtkWidget          *widget,
96                                                     GimpTemplateEditor *editor);
97 static void gimp_template_editor_aspect_callback   (GtkWidget          *widget,
98                                                     GimpTemplateEditor *editor);
99 static void gimp_template_editor_template_notify   (GimpTemplate       *template,
100                                                     GParamSpec         *param_spec,
101                                                     GimpTemplateEditor *editor);
102 
103 
G_DEFINE_TYPE_WITH_PRIVATE(GimpTemplateEditor,gimp_template_editor,GTK_TYPE_BOX)104 G_DEFINE_TYPE_WITH_PRIVATE (GimpTemplateEditor, gimp_template_editor,
105                             GTK_TYPE_BOX)
106 
107 #define parent_class gimp_template_editor_parent_class
108 
109 
110 static void
111 gimp_template_editor_class_init (GimpTemplateEditorClass *klass)
112 {
113   GObjectClass *object_class = G_OBJECT_CLASS (klass);
114 
115   object_class->constructed  = gimp_template_editor_constructed;
116   object_class->finalize     = gimp_template_editor_finalize;
117   object_class->set_property = gimp_template_editor_set_property;
118   object_class->get_property = gimp_template_editor_get_property;
119 
120   g_object_class_install_property (object_class, PROP_GIMP,
121                                    g_param_spec_object ("gimp", NULL, NULL,
122                                                         GIMP_TYPE_GIMP,
123                                                         GIMP_PARAM_READWRITE |
124                                                         G_PARAM_CONSTRUCT_ONLY));
125 
126   g_object_class_install_property (object_class, PROP_TEMPLATE,
127                                    g_param_spec_object ("template", NULL, NULL,
128                                                         GIMP_TYPE_TEMPLATE,
129                                                         GIMP_PARAM_READWRITE |
130                                                         G_PARAM_CONSTRUCT_ONLY));
131 }
132 
133 static void
gimp_template_editor_init(GimpTemplateEditor * editor)134 gimp_template_editor_init (GimpTemplateEditor *editor)
135 {
136   gtk_orientable_set_orientation (GTK_ORIENTABLE (editor),
137                                   GTK_ORIENTATION_VERTICAL);
138 
139   gtk_box_set_spacing (GTK_BOX (editor), 12);
140 }
141 
142 static void
gimp_template_editor_constructed(GObject * object)143 gimp_template_editor_constructed (GObject *object)
144 {
145   GimpTemplateEditor        *editor  = GIMP_TEMPLATE_EDITOR (object);
146   GimpTemplateEditorPrivate *private = GET_PRIVATE (object);
147   GimpTemplate              *template;
148   GtkWidget                 *aspect_box;
149   GtkWidget                 *frame;
150   GtkWidget                 *hbox;
151   GtkWidget                 *vbox;
152   GtkWidget                 *table;
153   GtkWidget                 *label;
154   GtkAdjustment             *adjustment;
155   GtkWidget                 *width;
156   GtkWidget                 *height;
157   GtkWidget                 *xres;
158   GtkWidget                 *yres;
159   GtkWidget                 *combo;
160   GtkWidget                 *toggle;
161   GtkWidget                 *scrolled_window;
162   GtkWidget                 *text_view;
163   GtkTextBuffer             *text_buffer;
164   GtkListStore              *store;
165   GList                     *focus_chain = NULL;
166   gchar                     *text;
167   gint                       row;
168 
169   G_OBJECT_CLASS (parent_class)->constructed (object);
170 
171   gimp_assert (private->gimp != NULL);
172   gimp_assert (private->template != NULL);
173 
174   template = private->template;
175 
176   /*  Image size frame  */
177   frame = gimp_frame_new (_("Image Size"));
178   gtk_box_pack_start (GTK_BOX (editor), frame, FALSE, FALSE, 0);
179   gtk_widget_show (frame);
180 
181   table = gtk_table_new (3, 2, FALSE);
182   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 6);
183   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
184   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
185   gtk_container_add (GTK_CONTAINER (frame), table);
186   gtk_widget_show (table);
187 
188   adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
189   width = gimp_spin_button_new (adjustment, 1.0, 2);
190   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (width), TRUE);
191   gtk_entry_set_width_chars (GTK_ENTRY (width), SB_WIDTH);
192 
193   adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
194   height = gimp_spin_button_new (adjustment, 1.0, 2);
195   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (height), TRUE);
196   gtk_entry_set_width_chars (GTK_ENTRY (height), SB_WIDTH);
197 
198   /*  the image size labels  */
199   label = gtk_label_new_with_mnemonic (_("_Width:"));
200   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
201   gtk_label_set_mnemonic_widget (GTK_LABEL (label), width);
202   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
203                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
204   gtk_widget_show (label);
205 
206   label = gtk_label_new_with_mnemonic (_("H_eight:"));
207   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
208   gtk_label_set_mnemonic_widget (GTK_LABEL (label), height);
209   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
210                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
211   gtk_widget_show (label);
212 
213   /*  create the sizeentry which keeps it all together  */
214   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
215   gtk_table_attach_defaults (GTK_TABLE (table), hbox, 1, 2, 0, 2);
216   gtk_widget_show (hbox);
217 
218   private->size_se = gimp_size_entry_new (0,
219                                           gimp_template_get_unit (template),
220                                           _("%p"),
221                                           TRUE, FALSE, FALSE, SB_WIDTH,
222                                           GIMP_SIZE_ENTRY_UPDATE_SIZE);
223 
224   gtk_table_set_row_spacing (GTK_TABLE (private->size_se), 0, 2);
225   gtk_table_set_col_spacing (GTK_TABLE (private->size_se), 1, 6);
226 
227   gtk_box_pack_start (GTK_BOX (hbox), private->size_se, FALSE, FALSE, 0);
228   gtk_widget_show (private->size_se);
229 
230   gimp_size_entry_add_field (GIMP_SIZE_ENTRY (private->size_se),
231                              GTK_SPIN_BUTTON (height), NULL);
232   gtk_table_attach_defaults (GTK_TABLE (private->size_se), height, 0, 1, 1, 2);
233   gtk_widget_show (height);
234 
235   gimp_size_entry_add_field (GIMP_SIZE_ENTRY (private->size_se),
236                              GTK_SPIN_BUTTON (width), NULL);
237   gtk_table_attach_defaults (GTK_TABLE (private->size_se), width, 0, 1, 0, 1);
238   gtk_widget_show (width);
239 
240   gimp_prop_coordinates_connect (G_OBJECT (template),
241                                  "width", "height", "unit",
242                                  private->size_se, NULL,
243                                  gimp_template_get_resolution_x (template),
244                                  gimp_template_get_resolution_y (template));
245 
246   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
247   gtk_table_attach_defaults (GTK_TABLE (table), hbox, 1, 3, 2, 3);
248   gtk_widget_show (hbox);
249 
250   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
251   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
252   gtk_widget_show (vbox);
253 
254   aspect_box = gimp_enum_icon_box_new (GIMP_TYPE_ASPECT_TYPE,
255                                        "gimp", GTK_ICON_SIZE_MENU,
256                                        G_CALLBACK (gimp_template_editor_aspect_callback),
257                                        editor,
258                                        &private->aspect_button);
259   gtk_widget_hide (private->aspect_button); /* hide "square" */
260 
261   gtk_box_pack_start (GTK_BOX (vbox), aspect_box, FALSE, FALSE, 0);
262   gtk_widget_show (aspect_box);
263 
264   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
265   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
266   gtk_widget_show (vbox);
267 
268   private->pixel_label = gtk_label_new (NULL);
269   gimp_label_set_attributes (GTK_LABEL (private->pixel_label),
270                              PANGO_ATTR_SCALE,  PANGO_SCALE_SMALL,
271                              -1);
272   gtk_label_set_xalign (GTK_LABEL (private->pixel_label), 0.0);
273   gtk_box_pack_start (GTK_BOX (vbox), private->pixel_label, FALSE, FALSE, 0);
274   gtk_widget_show (private->pixel_label);
275 
276   private->more_label = gtk_label_new (NULL);
277   gimp_label_set_attributes (GTK_LABEL (private->more_label),
278                              PANGO_ATTR_SCALE,  PANGO_SCALE_SMALL,
279                              -1);
280   gtk_label_set_xalign (GTK_LABEL (private->more_label), 0.0);
281   gtk_box_pack_start (GTK_BOX (vbox), private->more_label, FALSE, FALSE, 0);
282   gtk_widget_show (private->more_label);
283 
284 #ifdef ENABLE_MEMSIZE_LABEL
285   private->memsize_label = gtk_label_new (NULL);
286   gimp_label_set_attributes (GTK_LABEL (private->memsize_label),
287                              PANGO_ATTR_SCALE,  PANGO_SCALE_SMALL,
288                              PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
289                              -1);
290   gtk_label_set_xalign (GTK_LABEL (private->memsize_label), 0.0);
291   gtk_box_pack_start (GTK_BOX (vbox), private->memsize_label, FALSE, FALSE, 0);
292   gtk_widget_show (private->memsize_label);
293 #endif
294 
295   text = g_strdup_printf ("<b>%s</b>", _("_Advanced Options"));
296   private->expander = g_object_new (GTK_TYPE_EXPANDER,
297                                     "label",         text,
298                                     "use-markup",    TRUE,
299                                     "use-underline", TRUE,
300                                     NULL);
301   g_free (text);
302 
303   gtk_box_pack_start (GTK_BOX (editor), private->expander, TRUE, TRUE, 0);
304   gtk_widget_show (private->expander);
305 
306   frame = gimp_frame_new ("<expander>");
307   gtk_container_add (GTK_CONTAINER (private->expander), frame);
308   gtk_widget_show (frame);
309 
310   table = gtk_table_new (9, 2, FALSE);
311   gtk_table_set_col_spacing (GTK_TABLE (table), 0, 6);
312   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
313   gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
314   gtk_container_add (GTK_CONTAINER (frame), table);
315   gtk_widget_show (table);
316 
317   adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
318   xres = gimp_spin_button_new (adjustment, 1.0, 2);
319   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (xres), TRUE);
320   gtk_entry_set_width_chars (GTK_ENTRY (xres), SB_WIDTH);
321 
322   adjustment = (GtkAdjustment *) gtk_adjustment_new (1, 1, 1, 1, 10, 0);
323   yres = gimp_spin_button_new (adjustment, 1.0, 2);
324   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (yres), TRUE);
325   gtk_entry_set_width_chars (GTK_ENTRY (yres), SB_WIDTH);
326 
327   /*  the resolution labels  */
328   label = gtk_label_new_with_mnemonic (_("_X resolution:"));
329   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
330   gtk_label_set_mnemonic_widget (GTK_LABEL (label), xres);
331   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
332                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
333   gtk_widget_show (label);
334 
335   label = gtk_label_new_with_mnemonic (_("_Y resolution:"));
336   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
337   gtk_label_set_mnemonic_widget (GTK_LABEL (label), yres);
338   gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
339                     GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
340   gtk_widget_show (label);
341 
342   /*  the resolution sizeentry  */
343   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
344   gtk_table_attach_defaults (GTK_TABLE (table), hbox, 1, 2, 0, 2);
345   gtk_widget_show (hbox);
346 
347   private->resolution_se =
348     gimp_size_entry_new (0,
349                          gimp_template_get_resolution_unit (template),
350                          _("pixels/%s"),
351                          FALSE, FALSE, FALSE, SB_WIDTH,
352                          GIMP_SIZE_ENTRY_UPDATE_RESOLUTION);
353 
354   gtk_table_set_row_spacing (GTK_TABLE (private->resolution_se), 0, 2);
355   gtk_table_set_col_spacing (GTK_TABLE (private->resolution_se), 1, 2);
356   gtk_table_set_col_spacing (GTK_TABLE (private->resolution_se), 2, 2);
357 
358   gtk_box_pack_start (GTK_BOX (hbox), private->resolution_se, FALSE, FALSE, 0);
359   gtk_widget_show (private->resolution_se);
360 
361   gimp_size_entry_add_field (GIMP_SIZE_ENTRY (private->resolution_se),
362                              GTK_SPIN_BUTTON (yres), NULL);
363   gtk_table_attach_defaults (GTK_TABLE (private->resolution_se), yres,
364                              0, 1, 1, 2);
365   gtk_widget_show (yres);
366 
367   gimp_size_entry_add_field (GIMP_SIZE_ENTRY (private->resolution_se),
368                              GTK_SPIN_BUTTON (xres), NULL);
369   gtk_table_attach_defaults (GTK_TABLE (private->resolution_se), xres,
370                              0, 1, 0, 1);
371   gtk_widget_show (xres);
372 
373   gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 0,
374                                   gimp_template_get_resolution_x (template),
375                                   FALSE);
376   gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 1,
377                                   gimp_template_get_resolution_y (template),
378                                   FALSE);
379 
380   /*  the resolution chainbutton  */
381   private->chain_button = gimp_chain_button_new (GIMP_CHAIN_RIGHT);
382   gtk_table_attach_defaults (GTK_TABLE (private->resolution_se),
383                              private->chain_button, 1, 2, 0, 2);
384   gtk_widget_show (private->chain_button);
385 
386   gimp_prop_coordinates_connect (G_OBJECT (template),
387                                  "xresolution", "yresolution",
388                                  "resolution-unit",
389                                  private->resolution_se, private->chain_button,
390                                  1.0, 1.0);
391 
392   focus_chain = g_list_prepend (focus_chain,
393                                 GIMP_SIZE_ENTRY (private->resolution_se)->unitmenu);
394   focus_chain = g_list_prepend (focus_chain, private->chain_button);
395   focus_chain = g_list_prepend (focus_chain, yres);
396   focus_chain = g_list_prepend (focus_chain, xres);
397 
398   gtk_container_set_focus_chain (GTK_CONTAINER (private->resolution_se),
399                                  focus_chain);
400   g_list_free (focus_chain);
401 
402   row = 2;
403 
404   combo = gimp_prop_enum_combo_box_new (G_OBJECT (template),
405                                         "image-type",
406                                         GIMP_RGB, GIMP_GRAY);
407   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
408                              _("Color _space:"), 0.0, 0.5,
409                              combo, 1, FALSE);
410 
411   /* construct the precision combo manually, instead of using
412    * gimp_prop_enum_combo_box_new(), so that we only reset the gamma combo when
413    * the precision is changed through the ui.  see issue #3025.
414    */
415   store = gimp_enum_store_new_with_range (GIMP_TYPE_COMPONENT_TYPE,
416                                           GIMP_COMPONENT_TYPE_U8,
417                                           GIMP_COMPONENT_TYPE_FLOAT);
418 
419   private->precision_combo = g_object_new (GIMP_TYPE_ENUM_COMBO_BOX,
420                                            "model", store,
421                                            NULL);
422   g_object_unref (store);
423 
424   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
425                              _("_Precision:"), 0.0, 0.5,
426                              private->precision_combo, 1, FALSE);
427 
428   gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (private->precision_combo),
429                                  gimp_babl_component_type (
430                                    gimp_template_get_precision (template)));
431 
432   g_signal_connect (private->precision_combo, "changed",
433                     G_CALLBACK (gimp_template_editor_precision_changed),
434                     editor);
435 
436   combo = gimp_prop_boolean_combo_box_new (G_OBJECT (template),
437                                            "linear",
438                                            _("Linear light"),
439                                            _("Perceptual gamma (sRGB)"));
440   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
441                              _("_Gamma:"), 0.0, 0.5,
442                              combo, 1, FALSE);
443 
444   toggle = gimp_prop_check_button_new (G_OBJECT (template),
445                                        "color-managed",
446                                        _("Color _manage this image"));
447   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
448                              NULL, 0.0, 0.5,
449                              toggle, 1, FALSE);
450 
451   private->profile_combo =
452     gimp_prop_profile_combo_box_new (G_OBJECT (template),
453                                      "color-profile",
454                                      NULL,
455                                      _("Choose A Color Profile"),
456                                      G_OBJECT (private->gimp->config),
457                                      "color-profile-path");
458   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
459                              _("Co_lor profile:"), 0.0, 0.5,
460                              private->profile_combo, 1, FALSE);
461 
462   combo = gimp_prop_enum_combo_box_new (G_OBJECT (template),
463                                         "fill-type",
464                                         0, 0);
465   gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
466                              _("_Fill with:"), 0.0, 0.5,
467                              combo, 1, FALSE);
468 
469   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
470   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
471                                        GTK_SHADOW_IN);
472   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
473                                   GTK_POLICY_AUTOMATIC,
474                                   GTK_POLICY_AUTOMATIC);
475   label = gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
476                                      _("Comme_nt:"), 0.0, 0.0,
477                                      scrolled_window, 1, FALSE);
478 
479   text_buffer = gimp_prop_text_buffer_new (G_OBJECT (template),
480                                            "comment", MAX_COMMENT_LENGTH);
481 
482   text_view = gtk_text_view_new_with_buffer (text_buffer);
483   g_object_unref (text_buffer);
484 
485   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), GTK_WRAP_WORD);
486   gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
487   gtk_widget_show (text_view);
488 
489   gtk_label_set_mnemonic_widget (GTK_LABEL (label), text_view);
490 
491   g_signal_connect_object (template, "notify",
492                            G_CALLBACK (gimp_template_editor_template_notify),
493                            editor, 0);
494 
495   /*  call the notify callback once to get the labels set initially  */
496   gimp_template_editor_template_notify (template, NULL, editor);
497 }
498 
499 static void
gimp_template_editor_finalize(GObject * object)500 gimp_template_editor_finalize (GObject *object)
501 {
502   GimpTemplateEditorPrivate *private = GET_PRIVATE (object);
503 
504   g_clear_object (&private->template);
505 
506   G_OBJECT_CLASS (parent_class)->finalize (object);
507 }
508 
509 static void
gimp_template_editor_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)510 gimp_template_editor_set_property (GObject      *object,
511                                    guint         property_id,
512                                    const GValue *value,
513                                    GParamSpec   *pspec)
514 {
515   GimpTemplateEditorPrivate *private = GET_PRIVATE (object);
516 
517   switch (property_id)
518     {
519     case PROP_GIMP:
520       private->gimp = g_value_get_object (value); /* don't ref */
521       break;
522 
523     case PROP_TEMPLATE:
524       private->template = g_value_dup_object (value);
525       break;
526 
527     default:
528       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
529       break;
530     }
531 }
532 
533 static void
gimp_template_editor_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)534 gimp_template_editor_get_property (GObject      *object,
535                                    guint         property_id,
536                                    GValue       *value,
537                                    GParamSpec   *pspec)
538 {
539   GimpTemplateEditorPrivate *private = GET_PRIVATE (object);
540 
541   switch (property_id)
542     {
543     case PROP_GIMP:
544       g_value_set_object (value, private->gimp);
545       break;
546 
547     case PROP_TEMPLATE:
548       g_value_set_object (value, private->template);
549       break;
550 
551     default:
552       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
553       break;
554     }
555 }
556 
557 GtkWidget *
gimp_template_editor_new(GimpTemplate * template,Gimp * gimp,gboolean edit_template)558 gimp_template_editor_new (GimpTemplate *template,
559                           Gimp         *gimp,
560                           gboolean      edit_template)
561 {
562   GimpTemplateEditor        *editor;
563   GimpTemplateEditorPrivate *private;
564 
565   g_return_val_if_fail (GIMP_IS_TEMPLATE (template), NULL);
566   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
567 
568   editor = g_object_new (GIMP_TYPE_TEMPLATE_EDITOR,
569                          "gimp",     gimp,
570                          "template", template,
571                          NULL);
572 
573   private = GET_PRIVATE (editor);
574 
575   if (edit_template)
576     {
577       GtkWidget   *table;
578       GtkWidget   *entry;
579       GtkWidget   *icon_picker;
580 
581       table = gtk_table_new (2, 2, FALSE);
582       gtk_table_set_col_spacings (GTK_TABLE (table), 6);
583       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
584       gtk_box_pack_start (GTK_BOX (editor), table, FALSE, FALSE, 0);
585       gtk_box_reorder_child (GTK_BOX (editor), table, 0);
586       gtk_widget_show (table);
587 
588       entry = gimp_prop_entry_new (G_OBJECT (private->template), "name", 128);
589 
590       gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
591                                  _("_Name:"), 1.0, 0.5,
592                                  entry, 1, FALSE);
593 
594       icon_picker = gimp_prop_icon_picker_new (GIMP_VIEWABLE (private->template),
595                                                gimp);
596       gimp_table_attach_aligned (GTK_TABLE (table), 0, 1,
597                                  _("_Icon:"), 1.0, 0.5,
598                                  icon_picker, 1, TRUE);
599     }
600 
601   return GTK_WIDGET (editor);
602 }
603 
604 GimpTemplate *
gimp_template_editor_get_template(GimpTemplateEditor * editor)605 gimp_template_editor_get_template (GimpTemplateEditor *editor)
606 {
607   g_return_val_if_fail (GIMP_IS_TEMPLATE_EDITOR (editor), NULL);
608 
609   return GET_PRIVATE (editor)->template;
610 }
611 
612 void
gimp_template_editor_show_advanced(GimpTemplateEditor * editor,gboolean expanded)613 gimp_template_editor_show_advanced (GimpTemplateEditor *editor,
614                                     gboolean            expanded)
615 {
616   GimpTemplateEditorPrivate *private;
617 
618   g_return_if_fail (GIMP_IS_TEMPLATE_EDITOR (editor));
619 
620   private = GET_PRIVATE (editor);
621 
622   gtk_expander_set_expanded (GTK_EXPANDER (private->expander), expanded);
623 }
624 
625 GtkWidget *
gimp_template_editor_get_size_se(GimpTemplateEditor * editor)626 gimp_template_editor_get_size_se (GimpTemplateEditor *editor)
627 {
628   g_return_val_if_fail (GIMP_IS_TEMPLATE_EDITOR (editor), NULL);
629 
630   return GET_PRIVATE (editor)->size_se;
631 }
632 
633 GtkWidget *
gimp_template_editor_get_resolution_se(GimpTemplateEditor * editor)634 gimp_template_editor_get_resolution_se (GimpTemplateEditor *editor)
635 {
636   g_return_val_if_fail (GIMP_IS_TEMPLATE_EDITOR (editor), NULL);
637 
638   return GET_PRIVATE (editor)->resolution_se;
639 }
640 
641 GtkWidget *
gimp_template_editor_get_resolution_chain(GimpTemplateEditor * editor)642 gimp_template_editor_get_resolution_chain (GimpTemplateEditor *editor)
643 {
644   g_return_val_if_fail (GIMP_IS_TEMPLATE_EDITOR (editor), NULL);
645 
646   return GET_PRIVATE (editor)->chain_button;
647 }
648 
649 
650 /*  private functions  */
651 
652 static void
gimp_template_editor_precision_changed(GtkWidget * widget,GimpTemplateEditor * editor)653 gimp_template_editor_precision_changed (GtkWidget          *widget,
654                                         GimpTemplateEditor *editor)
655 {
656   GimpTemplateEditorPrivate *private = GET_PRIVATE (editor);
657   GimpComponentType          component_type;
658 
659   gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget),
660                                  (gint *) &component_type);
661 
662   g_object_set (private->template,
663                 "component-type", component_type,
664                 NULL);
665 
666   /* when changing this logic, also change the same switch()
667    * in convert-precision-dialog.c
668    */
669   switch (component_type)
670     {
671     case GIMP_COMPONENT_TYPE_U8:
672       /* default to gamma for 8 bit */
673       g_object_set (private->template,
674                     "linear", FALSE,
675                     NULL);
676       break;
677 
678     case GIMP_COMPONENT_TYPE_U16:
679     case GIMP_COMPONENT_TYPE_U32:
680     default:
681       /* leave gamma alone by default for 16/32 bit int */
682       break;
683 
684     case GIMP_COMPONENT_TYPE_HALF:
685     case GIMP_COMPONENT_TYPE_FLOAT:
686     case GIMP_COMPONENT_TYPE_DOUBLE:
687       /* default to linear for floating point */
688       g_object_set (private->template,
689                     "linear", TRUE,
690                     NULL);
691       break;
692     }
693 }
694 
695 static void
gimp_template_editor_set_pixels(GimpTemplateEditor * editor,GimpTemplate * template)696 gimp_template_editor_set_pixels (GimpTemplateEditor *editor,
697                                  GimpTemplate       *template)
698 {
699   GimpTemplateEditorPrivate *private = GET_PRIVATE (editor);
700   gchar                     *text;
701 
702   text = g_strdup_printf (ngettext ("%d × %d pixel",
703                                     "%d × %d pixels",
704                                     gimp_template_get_height (template)),
705                           gimp_template_get_width (template),
706                           gimp_template_get_height (template));
707   gtk_label_set_text (GTK_LABEL (private->pixel_label), text);
708   g_free (text);
709 }
710 
711 static void
gimp_template_editor_aspect_callback(GtkWidget * widget,GimpTemplateEditor * editor)712 gimp_template_editor_aspect_callback (GtkWidget          *widget,
713                                       GimpTemplateEditor *editor)
714 {
715   GimpTemplateEditorPrivate *private = GET_PRIVATE (editor);
716 
717   if (! private->block_aspect &&
718       gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
719     {
720       GimpTemplate *template    = private->template;
721       gint          width       = gimp_template_get_width (template);
722       gint          height      = gimp_template_get_height (template);
723       gdouble       xresolution = gimp_template_get_resolution_x (template);
724       gdouble       yresolution = gimp_template_get_resolution_y (template);
725 
726       if (width == height)
727         {
728           private->block_aspect = TRUE;
729           gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (private->aspect_button),
730                                            GIMP_ASPECT_SQUARE);
731           private->block_aspect = FALSE;
732           return;
733        }
734 
735       g_signal_handlers_block_by_func (template,
736                                        gimp_template_editor_template_notify,
737                                        editor);
738 
739       gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 0,
740                                       yresolution, FALSE);
741       gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 1,
742                                       xresolution, FALSE);
743 
744       g_object_set (template,
745                     "width",       height,
746                     "height",      width,
747                     "xresolution", yresolution,
748                     "yresolution", xresolution,
749                     NULL);
750 
751       g_signal_handlers_unblock_by_func (template,
752                                          gimp_template_editor_template_notify,
753                                          editor);
754 
755       gimp_template_editor_set_pixels (editor, template);
756     }
757 }
758 
759 static void
gimp_template_editor_template_notify(GimpTemplate * template,GParamSpec * param_spec,GimpTemplateEditor * editor)760 gimp_template_editor_template_notify (GimpTemplate       *template,
761                                       GParamSpec         *param_spec,
762                                       GimpTemplateEditor *editor)
763 {
764   GimpTemplateEditorPrivate *private = GET_PRIVATE (editor);
765   GimpAspectType             aspect;
766   const gchar               *desc;
767   gchar                     *text;
768   gint                       width;
769   gint                       height;
770   gint                       xres;
771   gint                       yres;
772 
773   if (param_spec)
774     {
775       if (! strcmp (param_spec->name, "xresolution"))
776         {
777           gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 0,
778                                           gimp_template_get_resolution_x (template),
779                                           FALSE);
780         }
781       else if (! strcmp (param_spec->name, "yresolution"))
782         {
783           gimp_size_entry_set_resolution (GIMP_SIZE_ENTRY (private->size_se), 1,
784                                           gimp_template_get_resolution_y (template),
785                                           FALSE);
786         }
787       else if (! strcmp (param_spec->name, "component-type"))
788         {
789           g_signal_handlers_block_by_func (private->precision_combo,
790                                            gimp_template_editor_precision_changed,
791                                            editor);
792 
793           gimp_int_combo_box_set_active (
794             GIMP_INT_COMBO_BOX (private->precision_combo),
795             gimp_babl_component_type (gimp_template_get_precision (template)));
796 
797           g_signal_handlers_unblock_by_func (private->precision_combo,
798                                              gimp_template_editor_precision_changed,
799                                              editor);
800         }
801     }
802 
803 #ifdef ENABLE_MEMSIZE_LABEL
804   text = g_format_size (gimp_template_get_initial_size (template));
805   gtk_label_set_text (GTK_LABEL (private->memsize_label), text);
806   g_free (text);
807 #endif
808 
809   gimp_template_editor_set_pixels (editor, template);
810 
811   width  = gimp_template_get_width (template);
812   height = gimp_template_get_height (template);
813 
814   if (width > height)
815     aspect = GIMP_ASPECT_LANDSCAPE;
816   else if (height > width)
817     aspect = GIMP_ASPECT_PORTRAIT;
818   else
819     aspect = GIMP_ASPECT_SQUARE;
820 
821   private->block_aspect = TRUE;
822   gimp_int_radio_group_set_active (GTK_RADIO_BUTTON (private->aspect_button),
823                                    aspect);
824   private->block_aspect = FALSE;
825 
826   gimp_enum_get_value (GIMP_TYPE_IMAGE_BASE_TYPE,
827                        gimp_template_get_base_type (template),
828                        NULL, NULL, &desc, NULL);
829 
830   xres = ROUND (gimp_template_get_resolution_x (template));
831   yres = ROUND (gimp_template_get_resolution_y (template));
832 
833   if (xres != yres)
834     text = g_strdup_printf (_("%d × %d ppi, %s"), xres, yres, desc);
835   else
836     text = g_strdup_printf (_("%d ppi, %s"), yres, desc);
837 
838   gtk_label_set_text (GTK_LABEL (private->more_label), text);
839   g_free (text);
840 
841   if (! param_spec                              ||
842       ! strcmp (param_spec->name, "image-type") ||
843       ! strcmp (param_spec->name, "precision"))
844     {
845       GtkListStore *profile_store;
846       GFile        *profile;
847       gchar        *filename;
848 
849       filename = gimp_personal_rc_file ("profilerc");
850       profile_store = gimp_color_profile_store_new (filename);
851       g_free (filename);
852 
853       gimp_color_profile_store_add_defaults (GIMP_COLOR_PROFILE_STORE (profile_store),
854                                              private->gimp->config->color_management,
855                                              gimp_template_get_base_type (template),
856                                              gimp_template_get_precision (template),
857                                              NULL);
858 
859       gtk_combo_box_set_model (GTK_COMBO_BOX (private->profile_combo),
860                                GTK_TREE_MODEL (profile_store));
861       g_object_unref (profile_store);
862 
863       g_object_get (template,
864                     "color-profile", &profile,
865                     NULL);
866 
867       gimp_color_profile_combo_box_set_active_file (GIMP_COLOR_PROFILE_COMBO_BOX (private->profile_combo),
868                                                     profile, NULL);
869 
870       if (profile)
871         g_object_unref (profile);
872     }
873 }
874