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