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