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