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 
25 #include "actions-types.h"
26 
27 #include "config/gimpdialogconfig.h"
28 
29 #include "core/gimp.h"
30 #include "core/gimpcontext.h"
31 #include "core/gimpimage.h"
32 #include "core/gimpimage-undo.h"
33 #include "core/gimpitem.h"
34 #include "core/gimpitemundo.h"
35 
36 #include "dialogs/dialogs.h"
37 #include "dialogs/fill-dialog.h"
38 #include "dialogs/stroke-dialog.h"
39 
40 #include "actions.h"
41 #include "items-commands.h"
42 
43 #include "gimp-intl.h"
44 
45 
46 /*  local function prototypes  */
47 
48 static void   items_fill_callback   (GtkWidget         *dialog,
49                                      GimpItem          *item,
50                                      GimpDrawable      *drawable,
51                                      GimpContext       *context,
52                                      GimpFillOptions   *options,
53                                      gpointer           user_data);
54 static void   items_stroke_callback (GtkWidget         *dialog,
55                                      GimpItem          *item,
56                                      GimpDrawable      *drawable,
57                                      GimpContext       *context,
58                                      GimpStrokeOptions *options,
59                                      gpointer           user_data);
60 
61 
62 /*  public functions  */
63 
64 void
items_visible_cmd_callback(GimpAction * action,GVariant * value,GimpImage * image,GimpItem * item)65 items_visible_cmd_callback (GimpAction *action,
66                             GVariant   *value,
67                             GimpImage  *image,
68                             GimpItem   *item)
69 {
70   gboolean visible = g_variant_get_boolean (value);
71 
72   if (visible != gimp_item_get_visible (item))
73     {
74       GimpUndo *undo;
75       gboolean  push_undo = TRUE;
76 
77       undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
78                                            GIMP_UNDO_ITEM_VISIBILITY);
79 
80       if (undo && GIMP_ITEM_UNDO (undo)->item == item)
81         push_undo = FALSE;
82 
83       gimp_item_set_visible (item, visible, push_undo);
84       gimp_image_flush (image);
85     }
86 }
87 
88 void
items_linked_cmd_callback(GimpAction * action,GVariant * value,GimpImage * image,GimpItem * item)89 items_linked_cmd_callback (GimpAction *action,
90                            GVariant   *value,
91                            GimpImage  *image,
92                            GimpItem   *item)
93 {
94   gboolean linked = g_variant_get_boolean (value);
95 
96   if (linked != gimp_item_get_linked (item))
97     {
98       GimpUndo *undo;
99       gboolean  push_undo = TRUE;
100 
101       undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
102                                            GIMP_UNDO_ITEM_LINKED);
103 
104       if (undo && GIMP_ITEM_UNDO (undo)->item == item)
105         push_undo = FALSE;
106 
107       gimp_item_set_linked (item, linked, push_undo);
108       gimp_image_flush (image);
109     }
110 }
111 
112 void
items_lock_content_cmd_callback(GimpAction * action,GVariant * value,GimpImage * image,GimpItem * item)113 items_lock_content_cmd_callback (GimpAction *action,
114                                  GVariant   *value,
115                                  GimpImage  *image,
116                                  GimpItem   *item)
117 {
118   gboolean locked = g_variant_get_boolean (value);
119 
120   if (locked != gimp_item_get_lock_content (item))
121     {
122       GimpUndo *undo;
123       gboolean  push_undo = TRUE;
124 
125       undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
126                                            GIMP_UNDO_ITEM_LINKED);
127 
128       if (undo && GIMP_ITEM_UNDO (undo)->item == item)
129         push_undo = FALSE;
130 
131       gimp_item_set_lock_content (item, locked, push_undo);
132       gimp_image_flush (image);
133     }
134 }
135 
136 void
items_lock_position_cmd_callback(GimpAction * action,GVariant * value,GimpImage * image,GimpItem * item)137 items_lock_position_cmd_callback (GimpAction *action,
138                                   GVariant   *value,
139                                   GimpImage  *image,
140                                   GimpItem   *item)
141 {
142   gboolean locked = g_variant_get_boolean (value);
143 
144   if (locked != gimp_item_get_lock_position (item))
145     {
146       GimpUndo *undo;
147       gboolean  push_undo = TRUE;
148 
149       undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
150                                            GIMP_UNDO_ITEM_LOCK_POSITION);
151 
152       if (undo && GIMP_ITEM_UNDO (undo)->item == item)
153         push_undo = FALSE;
154 
155 
156       gimp_item_set_lock_position (item, locked, push_undo);
157       gimp_image_flush (image);
158     }
159 }
160 
161 void
items_color_tag_cmd_callback(GimpAction * action,GimpImage * image,GimpItem * item,GimpColorTag color_tag)162 items_color_tag_cmd_callback (GimpAction   *action,
163                               GimpImage    *image,
164                               GimpItem     *item,
165                               GimpColorTag  color_tag)
166 {
167   if (color_tag != gimp_item_get_color_tag (item))
168     {
169       GimpUndo *undo;
170       gboolean  push_undo = TRUE;
171 
172       undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
173                                            GIMP_UNDO_ITEM_COLOR_TAG);
174 
175       if (undo && GIMP_ITEM_UNDO (undo)->item == item)
176         push_undo = FALSE;
177 
178       gimp_item_set_color_tag (item, color_tag, push_undo);
179       gimp_image_flush (image);
180     }
181 }
182 
183 void
items_fill_cmd_callback(GimpAction * action,GimpImage * image,GimpItem * item,const gchar * dialog_key,const gchar * dialog_title,const gchar * dialog_icon_name,const gchar * dialog_help_id,gpointer data)184 items_fill_cmd_callback (GimpAction  *action,
185                          GimpImage   *image,
186                          GimpItem    *item,
187                          const gchar *dialog_key,
188                          const gchar *dialog_title,
189                          const gchar *dialog_icon_name,
190                          const gchar *dialog_help_id,
191                          gpointer     data)
192 {
193   GimpDrawable *drawable;
194   GtkWidget    *dialog;
195   GtkWidget    *widget;
196   return_if_no_widget (widget, data);
197 
198   drawable = gimp_image_get_active_drawable (image);
199 
200   if (! drawable)
201     {
202       gimp_message_literal (image->gimp,
203                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
204                             _("There is no active layer or channel to fill."));
205       return;
206     }
207 
208   dialog = dialogs_get_dialog (G_OBJECT (item), dialog_key);
209 
210   if (! dialog)
211     {
212       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
213 
214       dialog = fill_dialog_new (item,
215                                 drawable,
216                                 action_data_get_context (data),
217                                 dialog_title,
218                                 dialog_icon_name,
219                                 dialog_help_id,
220                                 widget,
221                                 config->fill_options,
222                                 items_fill_callback,
223                                 NULL);
224 
225       dialogs_attach_dialog (G_OBJECT (item), dialog_key, dialog);
226     }
227 
228   gtk_window_present (GTK_WINDOW (dialog));
229 }
230 
231 void
items_fill_last_vals_cmd_callback(GimpAction * action,GimpImage * image,GimpItem * item,gpointer data)232 items_fill_last_vals_cmd_callback (GimpAction *action,
233                                    GimpImage  *image,
234                                    GimpItem   *item,
235                                    gpointer    data)
236 {
237   GimpDrawable     *drawable;
238   GimpDialogConfig *config;
239   GtkWidget        *widget;
240   GError           *error = NULL;
241   return_if_no_widget (widget, data);
242 
243   drawable = gimp_image_get_active_drawable (image);
244 
245   if (! drawable)
246     {
247       gimp_message_literal (image->gimp,
248                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
249                             _("There is no active layer or channel to fill."));
250       return;
251     }
252 
253   config = GIMP_DIALOG_CONFIG (image->gimp->config);
254 
255   if (! gimp_item_fill (item, drawable,
256                         config->fill_options, TRUE, NULL, &error))
257     {
258       gimp_message_literal (image->gimp, G_OBJECT (widget),
259                             GIMP_MESSAGE_WARNING, error->message);
260       g_clear_error (&error);
261     }
262   else
263     {
264       gimp_image_flush (image);
265     }
266 }
267 
268 void
items_stroke_cmd_callback(GimpAction * action,GimpImage * image,GimpItem * item,const gchar * dialog_key,const gchar * dialog_title,const gchar * dialog_icon_name,const gchar * dialog_help_id,gpointer data)269 items_stroke_cmd_callback (GimpAction  *action,
270                            GimpImage   *image,
271                            GimpItem    *item,
272                            const gchar *dialog_key,
273                            const gchar *dialog_title,
274                            const gchar *dialog_icon_name,
275                            const gchar *dialog_help_id,
276                            gpointer     data)
277 {
278   GimpDrawable *drawable;
279   GtkWidget    *dialog;
280   GtkWidget    *widget;
281   return_if_no_widget (widget, data);
282 
283   drawable = gimp_image_get_active_drawable (image);
284 
285   if (! drawable)
286     {
287       gimp_message_literal (image->gimp,
288                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
289                             _("There is no active layer or channel to stroke to."));
290       return;
291     }
292 
293   dialog = dialogs_get_dialog (G_OBJECT (item), dialog_key);
294 
295   if (! dialog)
296     {
297       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
298 
299       dialog = stroke_dialog_new (item,
300                                   drawable,
301                                   action_data_get_context (data),
302                                   dialog_title,
303                                   dialog_icon_name,
304                                   dialog_help_id,
305                                   widget,
306                                   config->stroke_options,
307                                   items_stroke_callback,
308                                   NULL);
309 
310       dialogs_attach_dialog (G_OBJECT (item), dialog_key, dialog);
311     }
312 
313   gtk_window_present (GTK_WINDOW (dialog));
314 }
315 
316 void
items_stroke_last_vals_cmd_callback(GimpAction * action,GimpImage * image,GimpItem * item,gpointer data)317 items_stroke_last_vals_cmd_callback (GimpAction *action,
318                                      GimpImage  *image,
319                                      GimpItem   *item,
320                                      gpointer    data)
321 {
322   GimpDrawable     *drawable;
323   GimpDialogConfig *config;
324   GtkWidget        *widget;
325   GError           *error = NULL;
326   return_if_no_widget (widget, data);
327 
328   drawable = gimp_image_get_active_drawable (image);
329 
330   if (! drawable)
331     {
332       gimp_message_literal (image->gimp,
333                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
334                             _("There is no active layer or channel to stroke to."));
335       return;
336     }
337 
338   config = GIMP_DIALOG_CONFIG (image->gimp->config);
339 
340   if (! gimp_item_stroke (item, drawable,
341                           action_data_get_context (data),
342                           config->stroke_options, NULL,
343                           TRUE, NULL, &error))
344     {
345       gimp_message_literal (image->gimp, G_OBJECT (widget),
346                             GIMP_MESSAGE_WARNING, error->message);
347       g_clear_error (&error);
348     }
349   else
350     {
351       gimp_image_flush (image);
352     }
353 }
354 
355 
356 /*  private functions  */
357 
358 static void
items_fill_callback(GtkWidget * dialog,GimpItem * item,GimpDrawable * drawable,GimpContext * context,GimpFillOptions * options,gpointer user_data)359 items_fill_callback (GtkWidget       *dialog,
360                      GimpItem        *item,
361                      GimpDrawable    *drawable,
362                      GimpContext     *context,
363                      GimpFillOptions *options,
364                      gpointer         user_data)
365 {
366   GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
367   GimpImage        *image  = gimp_item_get_image (item);
368   GError           *error  = NULL;
369 
370   gimp_config_sync (G_OBJECT (options),
371                     G_OBJECT (config->fill_options), 0);
372 
373   if (! gimp_item_fill (item, drawable, options, TRUE, NULL, &error))
374     {
375       gimp_message_literal (context->gimp,
376                             G_OBJECT (dialog),
377                             GIMP_MESSAGE_WARNING,
378                             error ? error->message : "NULL");
379 
380       g_clear_error (&error);
381       return;
382     }
383 
384   gimp_image_flush (image);
385 
386   gtk_widget_destroy (dialog);
387 }
388 
389 static void
items_stroke_callback(GtkWidget * dialog,GimpItem * item,GimpDrawable * drawable,GimpContext * context,GimpStrokeOptions * options,gpointer data)390 items_stroke_callback (GtkWidget         *dialog,
391                        GimpItem          *item,
392                        GimpDrawable      *drawable,
393                        GimpContext       *context,
394                        GimpStrokeOptions *options,
395                        gpointer           data)
396 {
397   GimpDialogConfig *config = GIMP_DIALOG_CONFIG (context->gimp->config);
398   GimpImage        *image  = gimp_item_get_image (item);
399   GError           *error  = NULL;
400 
401   gimp_config_sync (G_OBJECT (options),
402                     G_OBJECT (config->stroke_options), 0);
403 
404   if (! gimp_item_stroke (item, drawable, context, options, NULL,
405                           TRUE, NULL, &error))
406     {
407       gimp_message_literal (context->gimp,
408                             G_OBJECT (dialog),
409                             GIMP_MESSAGE_WARNING,
410                             error ? error->message : "NULL");
411 
412       g_clear_error (&error);
413       return;
414     }
415 
416   gimp_image_flush (image);
417 
418   gtk_widget_destroy (dialog);
419 }
420