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 "libgimpconfig/gimpconfig.h"
24 #include "libgimpwidgets/gimpwidgets.h"
25
26 #include "tools-types.h"
27
28 #include "widgets/gimppropwidgets.h"
29 #include "widgets/gimpwidgets-utils.h"
30
31 #include "gimpselectionoptions.h"
32 #include "gimptooloptions-gui.h"
33
34 #include "gimp-intl.h"
35
36
37 enum
38 {
39 PROP_0,
40 PROP_OPERATION,
41 PROP_ANTIALIAS,
42 PROP_FEATHER,
43 PROP_FEATHER_RADIUS
44 };
45
46
47 static void gimp_selection_options_set_property (GObject *object,
48 guint property_id,
49 const GValue *value,
50 GParamSpec *pspec);
51 static void gimp_selection_options_get_property (GObject *object,
52 guint property_id,
53 GValue *value,
54 GParamSpec *pspec);
55
56
G_DEFINE_TYPE(GimpSelectionOptions,gimp_selection_options,GIMP_TYPE_TOOL_OPTIONS)57 G_DEFINE_TYPE (GimpSelectionOptions, gimp_selection_options,
58 GIMP_TYPE_TOOL_OPTIONS)
59
60 #define parent_class gimp_selection_options_parent_class
61
62
63 static void
64 gimp_selection_options_class_init (GimpSelectionOptionsClass *klass)
65 {
66 GObjectClass *object_class = G_OBJECT_CLASS (klass);
67
68 object_class->set_property = gimp_selection_options_set_property;
69 object_class->get_property = gimp_selection_options_get_property;
70
71 GIMP_CONFIG_PROP_ENUM (object_class, PROP_OPERATION,
72 "operation",
73 NULL, NULL,
74 GIMP_TYPE_CHANNEL_OPS,
75 GIMP_CHANNEL_OP_REPLACE,
76 GIMP_PARAM_STATIC_STRINGS);
77
78 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_ANTIALIAS,
79 "antialias",
80 _("Antialiasing"),
81 _("Smooth edges"),
82 TRUE,
83 GIMP_PARAM_STATIC_STRINGS);
84
85 GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_FEATHER,
86 "feather",
87 _("Feather edges"),
88 _("Enable feathering of selection edges"),
89 FALSE,
90 GIMP_PARAM_STATIC_STRINGS);
91
92 GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_FEATHER_RADIUS,
93 "feather-radius",
94 _("Radius"),
95 _("Radius of feathering"),
96 0.0, 100.0, 10.0,
97 GIMP_PARAM_STATIC_STRINGS);
98 }
99
100 static void
gimp_selection_options_init(GimpSelectionOptions * options)101 gimp_selection_options_init (GimpSelectionOptions *options)
102 {
103 }
104
105 static void
gimp_selection_options_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)106 gimp_selection_options_set_property (GObject *object,
107 guint property_id,
108 const GValue *value,
109 GParamSpec *pspec)
110 {
111 GimpSelectionOptions *options = GIMP_SELECTION_OPTIONS (object);
112
113 switch (property_id)
114 {
115 case PROP_OPERATION:
116 options->operation = g_value_get_enum (value);
117 break;
118
119 case PROP_ANTIALIAS:
120 options->antialias = g_value_get_boolean (value);
121 break;
122
123 case PROP_FEATHER:
124 options->feather = g_value_get_boolean (value);
125 break;
126
127 case PROP_FEATHER_RADIUS:
128 options->feather_radius = g_value_get_double (value);
129 break;
130
131 default:
132 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
133 break;
134 }
135 }
136
137 static void
gimp_selection_options_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)138 gimp_selection_options_get_property (GObject *object,
139 guint property_id,
140 GValue *value,
141 GParamSpec *pspec)
142 {
143 GimpSelectionOptions *options = GIMP_SELECTION_OPTIONS (object);
144
145 switch (property_id)
146 {
147 case PROP_OPERATION:
148 g_value_set_enum (value, options->operation);
149 break;
150
151 case PROP_ANTIALIAS:
152 g_value_set_boolean (value, options->antialias);
153 break;
154
155 case PROP_FEATHER:
156 g_value_set_boolean (value, options->feather);
157 break;
158
159 case PROP_FEATHER_RADIUS:
160 g_value_set_double (value, options->feather_radius);
161 break;
162
163 default:
164 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
165 break;
166 }
167 }
168
169 static const gchar *
gimp_selection_options_get_modifiers(GimpChannelOps operation)170 gimp_selection_options_get_modifiers (GimpChannelOps operation)
171 {
172 GdkModifierType extend_mask;
173 GdkModifierType modify_mask;
174 GdkModifierType modifiers = 0;
175
176 extend_mask = gimp_get_extend_selection_mask ();
177 modify_mask = gimp_get_modify_selection_mask ();
178
179 switch (operation)
180 {
181 case GIMP_CHANNEL_OP_ADD:
182 modifiers = extend_mask;
183 break;
184
185 case GIMP_CHANNEL_OP_SUBTRACT:
186 modifiers = modify_mask;
187 break;
188
189 case GIMP_CHANNEL_OP_REPLACE:
190 modifiers = 0;
191 break;
192
193 case GIMP_CHANNEL_OP_INTERSECT:
194 modifiers = extend_mask | modify_mask;
195 break;
196 }
197
198 return gimp_get_mod_string (modifiers);
199 }
200
201 GtkWidget *
gimp_selection_options_gui(GimpToolOptions * tool_options)202 gimp_selection_options_gui (GimpToolOptions *tool_options)
203 {
204 GObject *config = G_OBJECT (tool_options);
205 GimpSelectionOptions *options = GIMP_SELECTION_OPTIONS (tool_options);
206 GtkWidget *vbox = gimp_tool_options_gui (tool_options);
207 GtkWidget *button;
208
209 /* the selection operation radio buttons */
210 {
211 GtkWidget *hbox;
212 GtkWidget *label;
213 GtkWidget *box;
214 GList *children;
215 GList *list;
216 gint i;
217
218 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
219 gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
220 gtk_widget_show (hbox);
221
222 options->mode_box = hbox;
223
224 label = gtk_label_new (_("Mode:"));
225 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
226 gtk_widget_show (label);
227
228 box = gimp_prop_enum_icon_box_new (config, "operation",
229 "gimp-selection", 0, 0);
230 gtk_box_pack_start (GTK_BOX (hbox), box, FALSE, FALSE, 0);
231 gtk_widget_show (box);
232
233 children = gtk_container_get_children (GTK_CONTAINER (box));
234
235 /* add modifier keys to the tooltips */
236 for (list = children, i = 0; list; list = list->next, i++)
237 {
238 GtkWidget *button = list->data;
239 const gchar *modifier = gimp_selection_options_get_modifiers (i);
240 gchar *tooltip;
241
242 if (! modifier)
243 continue;
244
245 tooltip = gtk_widget_get_tooltip_text (button);
246
247 if (tooltip)
248 {
249 gchar *tip = g_strdup_printf ("%s <b>%s</b>", tooltip, modifier);
250
251 gimp_help_set_help_data_with_markup (button, tip, NULL);
252
253 g_free (tip);
254 g_free (tooltip);
255 }
256 else
257 {
258 gimp_help_set_help_data (button, modifier, NULL);
259 }
260 }
261
262 /* move GIMP_CHANNEL_OP_REPLACE to the front */
263 gtk_box_reorder_child (GTK_BOX (box),
264 GTK_WIDGET (children->next->next->data), 0);
265
266 g_list_free (children);
267 }
268
269 /* the antialias toggle button */
270 button = gimp_prop_check_button_new (config, "antialias", NULL);
271 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
272 gtk_widget_show (button);
273
274 options->antialias_toggle = button;
275
276 /* the feather frame */
277 {
278 GtkWidget *frame;
279 GtkWidget *scale;
280
281 /* the feather radius scale */
282 scale = gimp_prop_spin_scale_new (config, "feather-radius", NULL,
283 1.0, 10.0, 1);
284
285 frame = gimp_prop_expanding_frame_new (config, "feather", NULL,
286 scale, NULL);
287 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
288 gtk_widget_show (frame);
289 }
290
291 return vbox;
292 }
293