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 <string.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #include "libgimpbase/gimpbase.h"
26 #include "libgimpconfig/gimpconfig.h"
27 #include "libgimpwidgets/gimpwidgets.h"
28 
29 #include "actions-types.h"
30 
31 #include "config/gimpdialogconfig.h"
32 
33 #include "core/gimp.h"
34 #include "core/gimp-utils.h"
35 #include "core/gimpchannel.h"
36 #include "core/gimpcontext.h"
37 #include "core/gimpimage.h"
38 #include "core/gimpimage-merge.h"
39 #include "core/gimpimage-undo.h"
40 #include "core/gimpparamspecs.h"
41 #include "core/gimpprogress.h"
42 #include "core/gimptoolinfo.h"
43 
44 #include "pdb/gimppdb.h"
45 #include "pdb/gimpprocedure.h"
46 
47 #include "vectors/gimpvectors.h"
48 #include "vectors/gimpvectors-export.h"
49 #include "vectors/gimpvectors-import.h"
50 
51 #include "widgets/gimpaction.h"
52 #include "widgets/gimpclipboard.h"
53 #include "widgets/gimphelp-ids.h"
54 
55 #include "display/gimpdisplay.h"
56 
57 #include "tools/gimpvectortool.h"
58 #include "tools/tool_manager.h"
59 
60 #include "dialogs/dialogs.h"
61 #include "dialogs/vectors-export-dialog.h"
62 #include "dialogs/vectors-import-dialog.h"
63 #include "dialogs/vectors-options-dialog.h"
64 
65 #include "actions.h"
66 #include "items-commands.h"
67 #include "vectors-commands.h"
68 
69 #include "gimp-intl.h"
70 
71 
72 /*  local function prototypes  */
73 
74 static void   vectors_new_callback             (GtkWidget    *dialog,
75                                                 GimpImage    *image,
76                                                 GimpVectors  *vectors,
77                                                 GimpContext  *context,
78                                                 const gchar  *vectors_name,
79                                                 gboolean      vectors_visible,
80                                                 gboolean      vectors_linked,
81                                                 GimpColorTag  vectors_color_tag,
82                                                 gboolean      vectors_lock_content,
83                                                 gboolean      vectors_lock_position,
84                                                 gpointer      user_data);
85 static void   vectors_edit_attributes_callback (GtkWidget    *dialog,
86                                                 GimpImage    *image,
87                                                 GimpVectors  *vectors,
88                                                 GimpContext  *context,
89                                                 const gchar  *vectors_name,
90                                                 gboolean      vectors_visible,
91                                                 gboolean      vectors_linked,
92                                                 GimpColorTag  vectors_color_tag,
93                                                 gboolean      vectors_lock_content,
94                                                 gboolean      vectors_lock_position,
95                                                 gpointer      user_data);
96 static void   vectors_import_callback          (GtkWidget    *dialog,
97                                                 GimpImage    *image,
98                                                 GFile        *file,
99                                                 GFile        *import_folder,
100                                                 gboolean      merge_vectors,
101                                                 gboolean      scale_vectors,
102                                                 gpointer      user_data);
103 static void   vectors_export_callback          (GtkWidget    *dialog,
104                                                 GimpImage    *image,
105                                                 GFile        *file,
106                                                 GFile        *export_folder,
107                                                 gboolean      active_only,
108                                                 gpointer      user_data);
109 
110 
111 /*  public functions  */
112 
113 void
vectors_edit_cmd_callback(GimpAction * action,GVariant * value,gpointer data)114 vectors_edit_cmd_callback (GimpAction *action,
115                            GVariant   *value,
116                            gpointer    data)
117 {
118   GimpImage   *image;
119   GimpVectors *vectors;
120   GimpTool    *active_tool;
121   return_if_no_vectors (image, vectors, data);
122 
123   active_tool = tool_manager_get_active (image->gimp);
124 
125   if (! GIMP_IS_VECTOR_TOOL (active_tool))
126     {
127       GimpToolInfo  *tool_info = gimp_get_tool_info (image->gimp,
128                                                      "gimp-vector-tool");
129 
130       if (GIMP_IS_TOOL_INFO (tool_info))
131         {
132           gimp_context_set_tool (action_data_get_context (data), tool_info);
133           active_tool = tool_manager_get_active (image->gimp);
134         }
135     }
136 
137   if (GIMP_IS_VECTOR_TOOL (active_tool))
138     gimp_vector_tool_set_vectors (GIMP_VECTOR_TOOL (active_tool), vectors);
139 }
140 
141 void
vectors_edit_attributes_cmd_callback(GimpAction * action,GVariant * value,gpointer data)142 vectors_edit_attributes_cmd_callback (GimpAction *action,
143                                       GVariant   *value,
144                                       gpointer    data)
145 {
146   GimpImage   *image;
147   GimpVectors *vectors;
148   GtkWidget   *widget;
149   GtkWidget   *dialog;
150   return_if_no_vectors (image, vectors, data);
151   return_if_no_widget (widget, data);
152 
153 #define EDIT_DIALOG_KEY "gimp-vectors-edit-attributes-dialog"
154 
155   dialog = dialogs_get_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY);
156 
157   if (! dialog)
158     {
159       GimpItem *item = GIMP_ITEM (vectors);
160 
161       dialog = vectors_options_dialog_new (image, vectors,
162                                            action_data_get_context (data),
163                                            widget,
164                                            _("Path Attributes"),
165                                            "gimp-vectors-edit",
166                                            GIMP_ICON_EDIT,
167                                            _("Edit Path Attributes"),
168                                            GIMP_HELP_PATH_EDIT,
169                                            gimp_object_get_name (vectors),
170                                            gimp_item_get_visible (item),
171                                            gimp_item_get_linked (item),
172                                            gimp_item_get_color_tag (item),
173                                            gimp_item_get_lock_content (item),
174                                            gimp_item_get_lock_position (item),
175                                            vectors_edit_attributes_callback,
176                                            NULL);
177 
178       dialogs_attach_dialog (G_OBJECT (vectors), EDIT_DIALOG_KEY, dialog);
179     }
180 
181   gtk_window_present (GTK_WINDOW (dialog));
182 }
183 
184 void
vectors_new_cmd_callback(GimpAction * action,GVariant * value,gpointer data)185 vectors_new_cmd_callback (GimpAction *action,
186                           GVariant   *value,
187                           gpointer    data)
188 {
189   GimpImage *image;
190   GtkWidget *widget;
191   GtkWidget *dialog;
192   return_if_no_image (image, data);
193   return_if_no_widget (widget, data);
194 
195 #define NEW_DIALOG_KEY "gimp-vectors-new-dialog"
196 
197   dialog = dialogs_get_dialog (G_OBJECT (image), NEW_DIALOG_KEY);
198 
199   if (! dialog)
200     {
201       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
202 
203       dialog = vectors_options_dialog_new (image, NULL,
204                                            action_data_get_context (data),
205                                            widget,
206                                            _("New Path"),
207                                            "gimp-vectors-new",
208                                            GIMP_ICON_PATH,
209                                            _("Create a New Path"),
210                                            GIMP_HELP_PATH_NEW,
211                                            config->vectors_new_name,
212                                            FALSE,
213                                            FALSE,
214                                            GIMP_COLOR_TAG_NONE,
215                                            FALSE,
216                                            FALSE,
217                                            vectors_new_callback,
218                                            NULL);
219 
220       dialogs_attach_dialog (G_OBJECT (image), NEW_DIALOG_KEY, dialog);
221     }
222 
223   gtk_window_present (GTK_WINDOW (dialog));
224 }
225 
226 void
vectors_new_last_vals_cmd_callback(GimpAction * action,GVariant * value,gpointer data)227 vectors_new_last_vals_cmd_callback (GimpAction *action,
228                                     GVariant   *value,
229                                     gpointer    data)
230 {
231   GimpImage        *image;
232   GimpVectors      *vectors;
233   GimpDialogConfig *config;
234   return_if_no_image (image, data);
235 
236   config = GIMP_DIALOG_CONFIG (image->gimp->config);
237 
238   vectors = gimp_vectors_new (image, config->vectors_new_name);
239   gimp_image_add_vectors (image, vectors,
240                           GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
241   gimp_image_flush (image);
242 }
243 
244 void
vectors_raise_cmd_callback(GimpAction * action,GVariant * value,gpointer data)245 vectors_raise_cmd_callback (GimpAction *action,
246                             GVariant   *value,
247                             gpointer    data)
248 {
249   GimpImage   *image;
250   GimpVectors *vectors;
251   return_if_no_vectors (image, vectors, data);
252 
253   gimp_image_raise_item (image, GIMP_ITEM (vectors), NULL);
254   gimp_image_flush (image);
255 }
256 
257 void
vectors_raise_to_top_cmd_callback(GimpAction * action,GVariant * value,gpointer data)258 vectors_raise_to_top_cmd_callback (GimpAction *action,
259                                    GVariant   *value,
260                                    gpointer    data)
261 {
262   GimpImage   *image;
263   GimpVectors *vectors;
264   return_if_no_vectors (image, vectors, data);
265 
266   gimp_image_raise_item_to_top (image, GIMP_ITEM (vectors));
267   gimp_image_flush (image);
268 }
269 
270 void
vectors_lower_cmd_callback(GimpAction * action,GVariant * value,gpointer data)271 vectors_lower_cmd_callback (GimpAction *action,
272                             GVariant   *value,
273                             gpointer    data)
274 {
275   GimpImage   *image;
276   GimpVectors *vectors;
277   return_if_no_vectors (image, vectors, data);
278 
279   gimp_image_lower_item (image, GIMP_ITEM (vectors), NULL);
280   gimp_image_flush (image);
281 }
282 
283 void
vectors_lower_to_bottom_cmd_callback(GimpAction * action,GVariant * value,gpointer data)284 vectors_lower_to_bottom_cmd_callback (GimpAction *action,
285                                       GVariant   *value,
286                                       gpointer    data)
287 {
288   GimpImage   *image;
289   GimpVectors *vectors;
290   return_if_no_vectors (image, vectors, data);
291 
292   gimp_image_lower_item_to_bottom (image, GIMP_ITEM (vectors));
293   gimp_image_flush (image);
294 }
295 
296 void
vectors_duplicate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)297 vectors_duplicate_cmd_callback (GimpAction *action,
298                                 GVariant   *value,
299                                 gpointer    data)
300 {
301   GimpImage   *image;
302   GimpVectors *vectors;
303   GimpVectors *new_vectors;
304   return_if_no_vectors (image, vectors, data);
305 
306   new_vectors = GIMP_VECTORS (gimp_item_duplicate (GIMP_ITEM (vectors),
307                                                    G_TYPE_FROM_INSTANCE (vectors)));
308   /*  use the actual parent here, not GIMP_IMAGE_ACTIVE_PARENT because
309    *  the latter would add a duplicated group inside itself instead of
310    *  above it
311    */
312   gimp_image_add_vectors (image, new_vectors,
313                           gimp_vectors_get_parent (vectors), -1,
314                           TRUE);
315   gimp_image_flush (image);
316 }
317 
318 void
vectors_delete_cmd_callback(GimpAction * action,GVariant * value,gpointer data)319 vectors_delete_cmd_callback (GimpAction *action,
320                              GVariant   *value,
321                              gpointer    data)
322 {
323   GimpImage   *image;
324   GimpVectors *vectors;
325   return_if_no_vectors (image, vectors, data);
326 
327   gimp_image_remove_vectors (image, vectors, TRUE, NULL);
328   gimp_image_flush (image);
329 }
330 
331 void
vectors_merge_visible_cmd_callback(GimpAction * action,GVariant * value,gpointer data)332 vectors_merge_visible_cmd_callback (GimpAction *action,
333                                     GVariant   *value,
334                                     gpointer    data)
335 {
336   GimpImage   *image;
337   GimpVectors *vectors;
338   GtkWidget   *widget;
339   GError      *error = NULL;
340   return_if_no_vectors (image, vectors, data);
341   return_if_no_widget (widget, data);
342 
343   if (! gimp_image_merge_visible_vectors (image, &error))
344     {
345       gimp_message_literal (image->gimp,
346                             G_OBJECT (widget), GIMP_MESSAGE_WARNING,
347                             error->message);
348       g_clear_error (&error);
349       return;
350     }
351 
352   gimp_image_flush (image);
353 }
354 
355 void
vectors_to_selection_cmd_callback(GimpAction * action,GVariant * value,gpointer data)356 vectors_to_selection_cmd_callback (GimpAction *action,
357                                    GVariant   *value,
358                                    gpointer    data)
359 {
360   GimpImage      *image;
361   GimpVectors    *vectors;
362   GimpChannelOps  operation;
363   return_if_no_vectors (image, vectors, data);
364 
365   operation = (GimpChannelOps) g_variant_get_int32 (value);
366 
367   gimp_item_to_selection (GIMP_ITEM (vectors), operation,
368                           TRUE, FALSE, 0, 0);
369   gimp_image_flush (image);
370 }
371 
372 void
vectors_selection_to_vectors_cmd_callback(GimpAction * action,GVariant * value,gpointer data)373 vectors_selection_to_vectors_cmd_callback (GimpAction *action,
374                                            GVariant   *value,
375                                            gpointer    data)
376 {
377   GimpImage      *image;
378   GtkWidget      *widget;
379   GimpProcedure  *procedure;
380   GimpValueArray *args;
381   GimpDisplay    *display;
382   gboolean        advanced;
383   GError         *error = NULL;
384   return_if_no_image (image, data);
385   return_if_no_widget (widget, data);
386 
387   advanced = (gboolean) g_variant_get_int32 (value);
388 
389   if (advanced)
390     procedure = gimp_pdb_lookup_procedure (image->gimp->pdb,
391                                            "plug-in-sel2path-advanced");
392   else
393     procedure = gimp_pdb_lookup_procedure (image->gimp->pdb,
394                                            "plug-in-sel2path");
395 
396   if (! procedure)
397     {
398       gimp_message_literal (image->gimp,
399                             G_OBJECT (widget), GIMP_MESSAGE_ERROR,
400                             "Selection to path procedure lookup failed.");
401       return;
402     }
403 
404   display = gimp_context_get_display (action_data_get_context (data));
405 
406   args = gimp_procedure_get_arguments (procedure);
407   gimp_value_array_truncate (args, 2);
408 
409   g_value_set_int      (gimp_value_array_index (args, 0),
410                         GIMP_RUN_INTERACTIVE);
411   gimp_value_set_image (gimp_value_array_index (args, 1),
412                         image);
413 
414   gimp_procedure_execute_async (procedure, image->gimp,
415                                 action_data_get_context (data),
416                                 GIMP_PROGRESS (display), args,
417                                 GIMP_OBJECT (display), &error);
418 
419   gimp_value_array_unref (args);
420 
421   if (error)
422     {
423       gimp_message_literal (image->gimp,
424                             G_OBJECT (widget), GIMP_MESSAGE_ERROR,
425                             error->message);
426       g_error_free (error);
427     }
428 }
429 
430 void
vectors_fill_cmd_callback(GimpAction * action,GVariant * value,gpointer data)431 vectors_fill_cmd_callback (GimpAction *action,
432                            GVariant   *value,
433                            gpointer    data)
434 {
435   GimpImage   *image;
436   GimpVectors *vectors;
437   return_if_no_vectors (image, vectors, data);
438 
439   items_fill_cmd_callback (action,
440                            image, GIMP_ITEM (vectors),
441                            "gimp-vectors-fill-dialog",
442                            _("Fill Path"),
443                            GIMP_ICON_TOOL_BUCKET_FILL,
444                            GIMP_HELP_PATH_FILL,
445                            data);
446 }
447 
448 void
vectors_fill_last_vals_cmd_callback(GimpAction * action,GVariant * value,gpointer data)449 vectors_fill_last_vals_cmd_callback (GimpAction *action,
450                                      GVariant   *value,
451                                      gpointer    data)
452 {
453   GimpImage   *image;
454   GimpVectors *vectors;
455   return_if_no_vectors (image, vectors, data);
456 
457   items_fill_last_vals_cmd_callback (action,
458                                      image, GIMP_ITEM (vectors),
459                                      data);
460 }
461 
462 void
vectors_stroke_cmd_callback(GimpAction * action,GVariant * value,gpointer data)463 vectors_stroke_cmd_callback (GimpAction *action,
464                              GVariant   *value,
465                              gpointer    data)
466 {
467   GimpImage   *image;
468   GimpVectors *vectors;
469   return_if_no_vectors (image, vectors, data);
470 
471   items_stroke_cmd_callback (action,
472                              image, GIMP_ITEM (vectors),
473                              "gimp-vectors-stroke-dialog",
474                              _("Stroke Path"),
475                              GIMP_ICON_PATH_STROKE,
476                              GIMP_HELP_PATH_STROKE,
477                              data);
478 }
479 
480 void
vectors_stroke_last_vals_cmd_callback(GimpAction * action,GVariant * value,gpointer data)481 vectors_stroke_last_vals_cmd_callback (GimpAction *action,
482                                        GVariant   *value,
483                                        gpointer    data)
484 {
485   GimpImage   *image;
486   GimpVectors *vectors;
487   return_if_no_vectors (image, vectors, data);
488 
489   items_stroke_last_vals_cmd_callback (action,
490                                        image, GIMP_ITEM (vectors),
491                                        data);
492 }
493 
494 void
vectors_copy_cmd_callback(GimpAction * action,GVariant * value,gpointer data)495 vectors_copy_cmd_callback (GimpAction *action,
496                            GVariant   *value,
497                            gpointer    data)
498 {
499   GimpImage   *image;
500   GimpVectors *vectors;
501   gchar       *svg;
502   return_if_no_vectors (image, vectors, data);
503 
504   svg = gimp_vectors_export_string (image, vectors);
505 
506   if (svg)
507     {
508       gimp_clipboard_set_svg (image->gimp, svg);
509       g_free (svg);
510     }
511 }
512 
513 void
vectors_paste_cmd_callback(GimpAction * action,GVariant * value,gpointer data)514 vectors_paste_cmd_callback (GimpAction *action,
515                             GVariant   *value,
516                             gpointer    data)
517 {
518   GimpImage *image;
519   GtkWidget *widget;
520   gchar     *svg;
521   gsize      svg_size;
522   return_if_no_image (image, data);
523   return_if_no_widget (widget, data);
524 
525   svg = gimp_clipboard_get_svg (image->gimp, &svg_size);
526 
527   if (svg)
528     {
529       GError *error = NULL;
530 
531       if (! gimp_vectors_import_buffer (image, svg, svg_size,
532                                         TRUE, FALSE,
533                                         GIMP_IMAGE_ACTIVE_PARENT, -1,
534                                         NULL, &error))
535         {
536           gimp_message (image->gimp, G_OBJECT (widget), GIMP_MESSAGE_ERROR,
537                         "%s", error->message);
538           g_clear_error (&error);
539         }
540       else
541         {
542           gimp_image_flush (image);
543         }
544 
545       g_free (svg);
546     }
547 }
548 
549 void
vectors_export_cmd_callback(GimpAction * action,GVariant * value,gpointer data)550 vectors_export_cmd_callback (GimpAction *action,
551                              GVariant   *value,
552                              gpointer    data)
553 {
554   GimpImage   *image;
555   GimpVectors *vectors;
556   GtkWidget   *widget;
557   GtkWidget   *dialog;
558   return_if_no_vectors (image, vectors, data);
559   return_if_no_widget (widget, data);
560 
561 #define EXPORT_DIALOG_KEY "gimp-vectors-export-dialog"
562 
563   dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
564 
565   if (! dialog)
566     {
567       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
568       GFile            *folder = NULL;
569 
570       if (config->vectors_export_path)
571         folder = gimp_file_new_for_config_path (config->vectors_export_path,
572                                                 NULL);
573 
574       dialog = vectors_export_dialog_new (image, widget,
575                                           folder,
576                                           config->vectors_export_active_only,
577                                           vectors_export_callback,
578                                           NULL);
579 
580       if (folder)
581         g_object_unref (folder);
582 
583       dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
584     }
585 
586   gtk_window_present (GTK_WINDOW (dialog));
587 }
588 
589 void
vectors_import_cmd_callback(GimpAction * action,GVariant * value,gpointer data)590 vectors_import_cmd_callback (GimpAction *action,
591                              GVariant   *value,
592                              gpointer    data)
593 {
594   GimpImage *image;
595   GtkWidget *widget;
596   GtkWidget *dialog;
597   return_if_no_image (image, data);
598   return_if_no_widget (widget, data);
599 
600 #define IMPORT_DIALOG_KEY "gimp-vectors-import-dialog"
601 
602   dialog = dialogs_get_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY);
603 
604   if (! dialog)
605     {
606       GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
607       GFile            *folder = NULL;
608 
609       if (config->vectors_import_path)
610         folder = gimp_file_new_for_config_path (config->vectors_import_path,
611                                                 NULL);
612 
613       dialog = vectors_import_dialog_new (image, widget,
614                                           folder,
615                                           config->vectors_import_merge,
616                                           config->vectors_import_scale,
617                                           vectors_import_callback,
618                                           NULL);
619 
620       dialogs_attach_dialog (G_OBJECT (image), IMPORT_DIALOG_KEY, dialog);
621     }
622 
623   gtk_window_present (GTK_WINDOW (dialog));
624 }
625 
626 void
vectors_visible_cmd_callback(GimpAction * action,GVariant * value,gpointer data)627 vectors_visible_cmd_callback (GimpAction *action,
628                               GVariant   *value,
629                               gpointer    data)
630 {
631   GimpImage   *image;
632   GimpVectors *vectors;
633   return_if_no_vectors (image, vectors, data);
634 
635   items_visible_cmd_callback (action, value, image, GIMP_ITEM (vectors));
636 }
637 
638 void
vectors_linked_cmd_callback(GimpAction * action,GVariant * value,gpointer data)639 vectors_linked_cmd_callback (GimpAction *action,
640                              GVariant   *value,
641                              gpointer    data)
642 {
643   GimpImage   *image;
644   GimpVectors *vectors;
645   return_if_no_vectors (image, vectors, data);
646 
647   items_linked_cmd_callback (action, value, image, GIMP_ITEM (vectors));
648 }
649 
650 void
vectors_lock_content_cmd_callback(GimpAction * action,GVariant * value,gpointer data)651 vectors_lock_content_cmd_callback (GimpAction *action,
652                                    GVariant   *value,
653                                    gpointer    data)
654 {
655   GimpImage   *image;
656   GimpVectors *vectors;
657   return_if_no_vectors (image, vectors, data);
658 
659   items_lock_content_cmd_callback (action, value, image, GIMP_ITEM (vectors));
660 }
661 
662 void
vectors_lock_position_cmd_callback(GimpAction * action,GVariant * value,gpointer data)663 vectors_lock_position_cmd_callback (GimpAction *action,
664                                     GVariant   *value,
665                                     gpointer    data)
666 {
667   GimpImage   *image;
668   GimpVectors *vectors;
669   return_if_no_vectors (image, vectors, data);
670 
671   items_lock_position_cmd_callback (action, value, image, GIMP_ITEM (vectors));
672 }
673 
674 void
vectors_color_tag_cmd_callback(GimpAction * action,GVariant * value,gpointer data)675 vectors_color_tag_cmd_callback (GimpAction *action,
676                                 GVariant   *value,
677                                 gpointer    data)
678 {
679   GimpImage    *image;
680   GimpVectors  *vectors;
681   GimpColorTag  color_tag;
682   return_if_no_vectors (image, vectors, data);
683 
684   color_tag = (GimpColorTag) g_variant_get_int32 (value);
685 
686   items_color_tag_cmd_callback (action, image, GIMP_ITEM (vectors),
687                                 color_tag);
688 }
689 
690 
691 /*  private functions  */
692 
693 static void
vectors_new_callback(GtkWidget * dialog,GimpImage * image,GimpVectors * vectors,GimpContext * context,const gchar * vectors_name,gboolean vectors_visible,gboolean vectors_linked,GimpColorTag vectors_color_tag,gboolean vectors_lock_content,gboolean vectors_lock_position,gpointer user_data)694 vectors_new_callback (GtkWidget    *dialog,
695                       GimpImage    *image,
696                       GimpVectors  *vectors,
697                       GimpContext  *context,
698                       const gchar  *vectors_name,
699                       gboolean      vectors_visible,
700                       gboolean      vectors_linked,
701                       GimpColorTag  vectors_color_tag,
702                       gboolean      vectors_lock_content,
703                       gboolean      vectors_lock_position,
704                       gpointer      user_data)
705 {
706   GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
707 
708   g_object_set (config,
709                 "path-new-name", vectors_name,
710                 NULL);
711 
712   vectors = gimp_vectors_new (image, config->vectors_new_name);
713   gimp_item_set_visible (GIMP_ITEM (vectors), vectors_visible, FALSE);
714   gimp_item_set_linked (GIMP_ITEM (vectors), vectors_linked, FALSE);
715   gimp_item_set_color_tag (GIMP_ITEM (vectors), vectors_color_tag, FALSE);
716   gimp_item_set_lock_content (GIMP_ITEM (vectors), vectors_lock_content, FALSE);
717   gimp_item_set_lock_position (GIMP_ITEM (vectors), vectors_lock_position, FALSE);
718 
719   gimp_image_add_vectors (image, vectors,
720                           GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
721   gimp_image_flush (image);
722 
723   gtk_widget_destroy (dialog);
724 }
725 
726 static void
vectors_edit_attributes_callback(GtkWidget * dialog,GimpImage * image,GimpVectors * vectors,GimpContext * context,const gchar * vectors_name,gboolean vectors_visible,gboolean vectors_linked,GimpColorTag vectors_color_tag,gboolean vectors_lock_content,gboolean vectors_lock_position,gpointer user_data)727 vectors_edit_attributes_callback (GtkWidget    *dialog,
728                                   GimpImage    *image,
729                                   GimpVectors  *vectors,
730                                   GimpContext  *context,
731                                   const gchar  *vectors_name,
732                                   gboolean      vectors_visible,
733                                   gboolean      vectors_linked,
734                                   GimpColorTag  vectors_color_tag,
735                                   gboolean      vectors_lock_content,
736                                   gboolean      vectors_lock_position,
737                                   gpointer      user_data)
738 {
739   GimpItem *item = GIMP_ITEM (vectors);
740 
741   if (strcmp (vectors_name, gimp_object_get_name (vectors))      ||
742       vectors_visible       != gimp_item_get_visible (item)      ||
743       vectors_linked        != gimp_item_get_linked (item)       ||
744       vectors_color_tag     != gimp_item_get_color_tag (item)    ||
745       vectors_lock_content  != gimp_item_get_lock_content (item) ||
746       vectors_lock_position != gimp_item_get_lock_position (item))
747     {
748       gimp_image_undo_group_start (image,
749                                    GIMP_UNDO_GROUP_ITEM_PROPERTIES,
750                                    _("Path Attributes"));
751 
752       if (strcmp (vectors_name, gimp_object_get_name (vectors)))
753         gimp_item_rename (GIMP_ITEM (vectors), vectors_name, NULL);
754 
755       if (vectors_visible != gimp_item_get_visible (item))
756         gimp_item_set_visible (item, vectors_visible, TRUE);
757 
758       if (vectors_linked != gimp_item_get_linked (item))
759         gimp_item_set_linked (item, vectors_linked, TRUE);
760 
761       if (vectors_color_tag != gimp_item_get_color_tag (item))
762         gimp_item_set_color_tag (item, vectors_color_tag, TRUE);
763 
764       if (vectors_lock_content != gimp_item_get_lock_content (item))
765         gimp_item_set_lock_content (item, vectors_lock_content, TRUE);
766 
767       if (vectors_lock_position != gimp_item_get_lock_position (item))
768         gimp_item_set_lock_position (item, vectors_lock_position, TRUE);
769 
770       gimp_image_undo_group_end (image);
771 
772       gimp_image_flush (image);
773     }
774 
775   gtk_widget_destroy (dialog);
776 }
777 
778 static void
vectors_import_callback(GtkWidget * dialog,GimpImage * image,GFile * file,GFile * import_folder,gboolean merge_vectors,gboolean scale_vectors,gpointer user_data)779 vectors_import_callback (GtkWidget *dialog,
780                          GimpImage *image,
781                          GFile     *file,
782                          GFile     *import_folder,
783                          gboolean   merge_vectors,
784                          gboolean   scale_vectors,
785                          gpointer   user_data)
786 {
787   GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config);
788   gchar            *path   = NULL;
789   GError           *error  = NULL;
790 
791   if (import_folder)
792     path = gimp_file_get_config_path (import_folder, NULL);
793 
794   g_object_set (config,
795                 "path-import-path",  path,
796                 "path-import-merge", merge_vectors,
797                 "path-import-scale", scale_vectors,
798                 NULL);
799 
800   if (path)
801     g_free (path);
802 
803   if (gimp_vectors_import_file (image, file,
804                                 config->vectors_import_merge,
805                                 config->vectors_import_scale,
806                                 GIMP_IMAGE_ACTIVE_PARENT, -1,
807                                 NULL, &error))
808     {
809       gimp_image_flush (image);
810     }
811   else
812     {
813       gimp_message (image->gimp, G_OBJECT (dialog),
814                     GIMP_MESSAGE_ERROR,
815                     "%s", error->message);
816       g_error_free (error);
817       return;
818     }
819 
820   gtk_widget_destroy (dialog);
821 }
822 
823 static void
vectors_export_callback(GtkWidget * dialog,GimpImage * image,GFile * file,GFile * export_folder,gboolean active_only,gpointer user_data)824 vectors_export_callback (GtkWidget *dialog,
825                          GimpImage *image,
826                          GFile     *file,
827                          GFile     *export_folder,
828                          gboolean   active_only,
829                          gpointer   user_data)
830 {
831   GimpDialogConfig *config  = GIMP_DIALOG_CONFIG (image->gimp->config);
832   GimpVectors      *vectors = NULL;
833   gchar            *path    = NULL;
834   GError           *error   = NULL;
835 
836   if (export_folder)
837     path = gimp_file_get_config_path (export_folder, NULL);
838 
839   g_object_set (config,
840                 "path-export-path",        path,
841                 "path-export-active-only", active_only,
842                 NULL);
843 
844   if (path)
845     g_free (path);
846 
847   if (config->vectors_export_active_only)
848     vectors = gimp_image_get_active_vectors (image);
849 
850   if (! gimp_vectors_export_file (image, vectors, file, &error))
851     {
852       gimp_message (image->gimp, G_OBJECT (dialog),
853                     GIMP_MESSAGE_ERROR,
854                     "%s", error->message);
855       g_clear_error (&error);
856       return;
857     }
858 
859   gtk_widget_destroy (dialog);
860 }
861 
862 void
vectors_select_cmd_callback(GimpAction * action,GVariant * value,gpointer data)863 vectors_select_cmd_callback (GimpAction *action,
864                              GVariant   *value,
865                              gpointer    data)
866 {
867   GimpImage            *image;
868   GimpVectors          *vectors;
869   GimpContainer        *container;
870   GimpVectors          *new_vectors;
871   GimpActionSelectType  select_type;
872   return_if_no_image (image, data);
873 
874   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
875 
876   vectors = gimp_image_get_active_vectors (image);
877 
878   if (vectors)
879     container = gimp_item_get_container (GIMP_ITEM (vectors));
880   else
881     container = gimp_image_get_vectors (image);
882 
883   new_vectors = (GimpVectors *) action_select_object (select_type,
884                                                       container,
885                                                       (GimpObject *) vectors);
886 
887   if (new_vectors && new_vectors != vectors)
888     {
889       gimp_image_set_active_vectors (image, new_vectors);
890       gimp_image_flush (image);
891     }
892 }
893