1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 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 "libgimpconfig/gimpconfig.h"
24 #include "libgimpwidgets/gimpwidgets.h"
25 
26 #include "tools-types.h"
27 
28 #include "core/gimpdata.h"
29 #include "core/gimpdatafactory.h"
30 #include "core/gimp-gradients.h"
31 
32 #include "widgets/gimppropwidgets.h"
33 #include "widgets/gimpviewablebox.h"
34 #include "widgets/gimpwidgets-utils.h"
35 
36 #include "gimpgradientoptions.h"
37 #include "gimppaintoptions-gui.h"
38 
39 #include "gimp-intl.h"
40 
41 
42 enum
43 {
44   PROP_0,
45   PROP_OFFSET,
46   PROP_GRADIENT_TYPE,
47   PROP_DISTANCE_METRIC,
48   PROP_SUPERSAMPLE,
49   PROP_SUPERSAMPLE_DEPTH,
50   PROP_SUPERSAMPLE_THRESHOLD,
51   PROP_DITHER,
52   PROP_INSTANT,
53   PROP_MODIFY_ACTIVE
54 };
55 
56 
57 static void   gimp_gradient_options_set_property           (GObject             *object,
58                                                             guint                property_id,
59                                                             const GValue        *value,
60                                                             GParamSpec          *pspec);
61 static void   gimp_gradient_options_get_property           (GObject             *object,
62                                                             guint                property_id,
63                                                             GValue              *value,
64                                                             GParamSpec          *pspec);
65 
66 static void   gradient_options_repeat_gradient_type_notify (GimpGradientOptions *options,
67                                                             GParamSpec          *pspec,
68                                                             GtkWidget           *repeat_combo);
69 static void   gradient_options_metric_gradient_type_notify (GimpGradientOptions *options,
70                                                             GParamSpec          *pspec,
71                                                             GtkWidget           *repeat_combo);
72 
73 
G_DEFINE_TYPE(GimpGradientOptions,gimp_gradient_options,GIMP_TYPE_PAINT_OPTIONS)74 G_DEFINE_TYPE (GimpGradientOptions, gimp_gradient_options,
75                GIMP_TYPE_PAINT_OPTIONS)
76 
77 
78 static void
79 gimp_gradient_options_class_init (GimpGradientOptionsClass *klass)
80 {
81   GObjectClass *object_class = G_OBJECT_CLASS (klass);
82 
83   object_class->set_property = gimp_gradient_options_set_property;
84   object_class->get_property = gimp_gradient_options_get_property;
85 
86   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OFFSET,
87                            "offset",
88                            _("Offset"),
89                            NULL,
90                            0.0, 100.0, 0.0,
91                            GIMP_PARAM_STATIC_STRINGS);
92   GIMP_CONFIG_PROP_ENUM (object_class, PROP_GRADIENT_TYPE,
93                          "gradient-type",
94                          _("Shape"),
95                          NULL,
96                          GIMP_TYPE_GRADIENT_TYPE,
97                          GIMP_GRADIENT_LINEAR,
98                          GIMP_PARAM_STATIC_STRINGS);
99   GIMP_CONFIG_PROP_ENUM (object_class, PROP_DISTANCE_METRIC,
100                          "distance-metric",
101                          _("Metric"),
102                          _("Metric to use for the distance calculation"),
103                          GEGL_TYPE_DISTANCE_METRIC,
104                          GEGL_DISTANCE_METRIC_EUCLIDEAN,
105                          GIMP_PARAM_STATIC_STRINGS);
106 
107   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SUPERSAMPLE,
108                             "supersample",
109                             _("Adaptive Supersampling"),
110                             NULL,
111                             FALSE,
112                             GIMP_PARAM_STATIC_STRINGS);
113   GIMP_CONFIG_PROP_INT (object_class, PROP_SUPERSAMPLE_DEPTH,
114                         "supersample-depth",
115                         _("Max depth"),
116                         NULL,
117                         1, 9, 3,
118                         GIMP_PARAM_STATIC_STRINGS);
119   GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_SUPERSAMPLE_THRESHOLD,
120                            "supersample-threshold",
121                            _("Threshold"),
122                            NULL,
123                            0.0, 4.0, 0.2,
124                            GIMP_PARAM_STATIC_STRINGS);
125 
126   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DITHER,
127                             "dither",
128                             _("Dithering"),
129                             NULL,
130                             TRUE,
131                             GIMP_PARAM_STATIC_STRINGS);
132 
133   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_INSTANT,
134                             "instant",
135                             _("Instant mode"),
136                             _("Commit gradient instantly"),
137                             FALSE,
138                             GIMP_PARAM_STATIC_STRINGS);
139 
140   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_MODIFY_ACTIVE,
141                             "modify-active",
142                             _("Modify active gradient"),
143                             _("Modify the active gradient in-place"),
144                             FALSE,
145                             GIMP_PARAM_STATIC_STRINGS);
146 }
147 
148 static void
gimp_gradient_options_init(GimpGradientOptions * options)149 gimp_gradient_options_init (GimpGradientOptions *options)
150 {
151 }
152 
153 static void
gimp_gradient_options_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)154 gimp_gradient_options_set_property (GObject      *object,
155                                     guint         property_id,
156                                     const GValue *value,
157                                     GParamSpec   *pspec)
158 {
159   GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (object);
160 
161   switch (property_id)
162     {
163     case PROP_OFFSET:
164       options->offset = g_value_get_double (value);
165       break;
166     case PROP_GRADIENT_TYPE:
167       options->gradient_type = g_value_get_enum (value);
168       break;
169     case PROP_DISTANCE_METRIC:
170       options->distance_metric = g_value_get_enum (value);
171       break;
172 
173     case PROP_SUPERSAMPLE:
174       options->supersample = g_value_get_boolean (value);
175       break;
176     case PROP_SUPERSAMPLE_DEPTH:
177       options->supersample_depth = g_value_get_int (value);
178       break;
179     case PROP_SUPERSAMPLE_THRESHOLD:
180       options->supersample_threshold = g_value_get_double (value);
181       break;
182 
183     case PROP_DITHER:
184       options->dither = g_value_get_boolean (value);
185       break;
186 
187     case PROP_INSTANT:
188       options->instant = g_value_get_boolean (value);
189       break;
190     case PROP_MODIFY_ACTIVE:
191       options->modify_active = g_value_get_boolean (value);
192       break;
193 
194     default:
195       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
196       break;
197     }
198 }
199 
200 static void
gimp_gradient_options_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)201 gimp_gradient_options_get_property (GObject    *object,
202                                     guint       property_id,
203                                     GValue     *value,
204                                     GParamSpec *pspec)
205 {
206   GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (object);
207 
208   switch (property_id)
209     {
210     case PROP_OFFSET:
211       g_value_set_double (value, options->offset);
212       break;
213     case PROP_GRADIENT_TYPE:
214       g_value_set_enum (value, options->gradient_type);
215       break;
216     case PROP_DISTANCE_METRIC:
217       g_value_set_enum (value, options->distance_metric);
218       break;
219 
220     case PROP_SUPERSAMPLE:
221       g_value_set_boolean (value, options->supersample);
222       break;
223     case PROP_SUPERSAMPLE_DEPTH:
224       g_value_set_int (value, options->supersample_depth);
225       break;
226     case PROP_SUPERSAMPLE_THRESHOLD:
227       g_value_set_double (value, options->supersample_threshold);
228       break;
229 
230     case PROP_DITHER:
231       g_value_set_boolean (value, options->dither);
232       break;
233 
234     case PROP_INSTANT:
235       g_value_set_boolean (value, options->instant);
236       break;
237     case PROP_MODIFY_ACTIVE:
238       g_value_set_boolean (value, options->modify_active);
239       break;
240 
241     default:
242       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
243       break;
244     }
245 }
246 
247 GtkWidget *
gimp_gradient_options_gui(GimpToolOptions * tool_options)248 gimp_gradient_options_gui (GimpToolOptions *tool_options)
249 {
250   GObject             *config  = G_OBJECT (tool_options);
251   GimpContext         *context = GIMP_CONTEXT (tool_options);
252   GimpGradientOptions *options = GIMP_GRADIENT_OPTIONS (tool_options);
253   GtkWidget           *vbox    = gimp_paint_options_gui (tool_options);
254   GtkWidget           *vbox2;
255   GtkWidget           *frame;
256   GtkWidget           *scale;
257   GtkWidget           *combo;
258   GtkWidget           *button;
259   GtkWidget           *label;
260   gchar               *str;
261   GdkModifierType      extend_mask;
262   GimpGradient        *gradient;
263 
264   extend_mask = gimp_get_extend_selection_mask ();
265 
266   /*  the gradient  */
267   button = gimp_prop_gradient_box_new (NULL, GIMP_CONTEXT (tool_options),
268                                        _("Gradient"), 2,
269                                        "gradient-view-type",
270                                        "gradient-view-size",
271                                        "gradient-reverse",
272                                        "gradient-blend-color-space",
273                                        "gimp-gradient-editor",
274                                        _("Edit this gradient"));
275   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
276   gtk_widget_show (button);
277 
278   /*  the blend color space  */
279   combo = gimp_prop_enum_combo_box_new (config, "gradient-blend-color-space",
280                                         0, 0);
281   gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo),
282                                 _("Blend Color Space"));
283   g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
284   gtk_box_pack_start (GTK_BOX (vbox), combo, TRUE, TRUE, 0);
285   gtk_widget_show (combo);
286 
287   /*  the gradient type menu  */
288   combo = gimp_prop_enum_combo_box_new (config, "gradient-type", 0, 0);
289   gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Shape"));
290   g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
291   gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (combo),
292                                        "gimp-gradient");
293   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
294   gtk_widget_show (combo);
295 
296   /*  the distance metric menu  */
297   combo = gimp_prop_enum_combo_box_new (config, "distance-metric", 0, 0);
298   gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Metric"));
299   g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
300   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
301   gtk_widget_show (combo);
302 
303   g_signal_connect (config, "notify::gradient-type",
304                     G_CALLBACK (gradient_options_metric_gradient_type_notify),
305                     combo);
306   gradient_options_metric_gradient_type_notify (options, NULL, combo);
307 
308   /*  the repeat option  */
309   combo = gimp_prop_enum_combo_box_new (config, "gradient-repeat", 0, 0);
310   gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (combo), _("Repeat"));
311   g_object_set (combo, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
312   gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
313   gtk_widget_show (combo);
314 
315   g_signal_connect (config, "notify::gradient-type",
316                     G_CALLBACK (gradient_options_repeat_gradient_type_notify),
317                     combo);
318   gradient_options_repeat_gradient_type_notify (options, NULL, combo);
319 
320   /*  the offset scale  */
321   scale = gimp_prop_spin_scale_new (config, "offset", NULL,
322                                     1.0, 10.0, 1);
323   gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
324   gtk_widget_show (scale);
325 
326   /*  the dither toggle  */
327   button = gimp_prop_check_button_new (config, "dither", NULL);
328   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
329   gtk_widget_show (button);
330 
331   /*  supersampling options  */
332   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
333   frame = gimp_prop_expanding_frame_new (config, "supersample", NULL,
334                                          vbox2, NULL);
335   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
336   gtk_widget_show (frame);
337 
338   /*  max depth scale  */
339   scale = gimp_prop_spin_scale_new (config, "supersample-depth", NULL,
340                                     1.0, 1.0, 0);
341   gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
342   gtk_widget_show (scale);
343 
344   /*  threshold scale  */
345   scale = gimp_prop_spin_scale_new (config, "supersample-threshold", NULL,
346                                     0.01, 0.1, 2);
347   gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
348   gtk_widget_show (scale);
349 
350   /* the instant toggle */
351   str = g_strdup_printf (_("Instant mode  (%s)"),
352                           gimp_get_mod_string (extend_mask));
353 
354   button = gimp_prop_check_button_new (config, "instant", str);
355   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
356   gtk_widget_show (button);
357 
358   g_free (str);
359 
360   options->instant_toggle = button;
361 
362   /*  the modify active toggle  */
363   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
364   frame = gimp_prop_expanding_frame_new (config, "modify-active", NULL,
365                                          vbox2, NULL);
366   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
367   gtk_widget_show (frame);
368 
369   options->modify_active_frame = frame;
370 
371   label = gtk_label_new (_("The active gradient is non-writable "
372                            "and cannot be edited directly. "
373                            "Uncheck this option "
374                            "to edit a copy of it."));
375   gtk_box_pack_start (GTK_BOX (vbox2), label, TRUE, TRUE, 0);
376   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
377   gtk_label_set_width_chars (GTK_LABEL (label), 24);
378   gtk_label_set_xalign (GTK_LABEL (label), 0.0);
379   gimp_label_set_attributes (GTK_LABEL (label),
380                              PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
381                              -1);
382 
383   options->modify_active_hint = label;
384 
385   gradient = gimp_context_get_gradient (GIMP_CONTEXT (options));
386 
387   gtk_widget_set_sensitive (options->modify_active_frame,
388                             gradient !=
389                             gimp_gradients_get_custom (context->gimp));
390   gtk_widget_set_visible (options->modify_active_hint,
391                           gradient &&
392                           ! gimp_data_is_writable (GIMP_DATA (gradient)));
393 
394   return vbox;
395 }
396 
397 static void
gradient_options_repeat_gradient_type_notify(GimpGradientOptions * options,GParamSpec * pspec,GtkWidget * repeat_combo)398 gradient_options_repeat_gradient_type_notify (GimpGradientOptions *options,
399                                               GParamSpec       *pspec,
400                                               GtkWidget        *repeat_combo)
401 {
402   gtk_widget_set_sensitive (repeat_combo,
403                             options->gradient_type < GIMP_GRADIENT_SHAPEBURST_ANGULAR);
404 }
405 
406 static void
gradient_options_metric_gradient_type_notify(GimpGradientOptions * options,GParamSpec * pspec,GtkWidget * repeat_combo)407 gradient_options_metric_gradient_type_notify (GimpGradientOptions *options,
408                                               GParamSpec       *pspec,
409                                               GtkWidget        *repeat_combo)
410 {
411   gtk_widget_set_sensitive (repeat_combo,
412                             options->gradient_type >= GIMP_GRADIENT_SHAPEBURST_ANGULAR &&
413                             options->gradient_type <= GIMP_GRADIENT_SHAPEBURST_DIMPLED);
414 }
415