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 "libgimpwidgets/gimpwidgets.h"
24
25 #include "actions-types.h"
26
27 #include "core/gimp.h"
28 #include "core/gimpcontainer.h"
29 #include "core/gimpcontext.h"
30 #include "core/gimpimage.h"
31 #include "core/gimptooloptions.h"
32 #include "core/gimptoolinfo.h"
33
34 #include "widgets/gimpactionfactory.h"
35 #include "widgets/gimpactiongroup.h"
36 #include "widgets/gimpcontainereditor.h"
37 #include "widgets/gimpcontainerview.h"
38 #include "widgets/gimpdock.h"
39 #include "widgets/gimpdockable.h"
40 #include "widgets/gimpdockwindow.h"
41 #include "widgets/gimpimageeditor.h"
42 #include "widgets/gimpitemtreeview.h"
43
44 #include "display/gimpdisplay.h"
45 #include "display/gimpdisplayshell.h"
46 #include "display/gimpimagewindow.h"
47 #include "display/gimpnavigationeditor.h"
48 #include "display/gimpstatusbar.h"
49
50 #include "dialogs/dialogs.h"
51
52 #include "actions.h"
53 #include "brush-editor-actions.h"
54 #include "brushes-actions.h"
55 #include "buffers-actions.h"
56 #include "channels-actions.h"
57 #include "colormap-actions.h"
58 #include "context-actions.h"
59 #include "cursor-info-actions.h"
60 #include "dashboard-actions.h"
61 #include "debug-actions.h"
62 #include "dialogs-actions.h"
63 #include "dock-actions.h"
64 #include "dockable-actions.h"
65 #include "documents-actions.h"
66 #include "drawable-actions.h"
67 #include "dynamics-actions.h"
68 #include "dynamics-editor-actions.h"
69 #include "edit-actions.h"
70 #include "error-console-actions.h"
71 #include "file-actions.h"
72 #include "filters-actions.h"
73 #include "fonts-actions.h"
74 #include "gradient-editor-actions.h"
75 #include "gradients-actions.h"
76 #include "help-actions.h"
77 #include "image-actions.h"
78 #include "images-actions.h"
79 #include "layers-actions.h"
80 #include "mypaint-brushes-actions.h"
81 #include "palette-editor-actions.h"
82 #include "palettes-actions.h"
83 #include "patterns-actions.h"
84 #include "plug-in-actions.h"
85 #include "quick-mask-actions.h"
86 #include "sample-points-actions.h"
87 #include "select-actions.h"
88 #include "templates-actions.h"
89 #include "text-editor-actions.h"
90 #include "text-tool-actions.h"
91 #include "tool-options-actions.h"
92 #include "tool-presets-actions.h"
93 #include "tool-preset-editor-actions.h"
94 #include "tools-actions.h"
95 #include "vectors-actions.h"
96 #include "view-actions.h"
97 #include "windows-actions.h"
98
99 #include "gimp-intl.h"
100
101
102 /* global variables */
103
104 GimpActionFactory *global_action_factory = NULL;
105
106
107 /* private variables */
108
109 static const GimpActionFactoryEntry action_groups[] =
110 {
111 { "brush-editor", N_("Brush Editor"), GIMP_ICON_BRUSH,
112 brush_editor_actions_setup,
113 brush_editor_actions_update },
114 { "brushes", N_("Brushes"), GIMP_ICON_BRUSH,
115 brushes_actions_setup,
116 brushes_actions_update },
117 { "buffers", N_("Buffers"), GIMP_ICON_BUFFER,
118 buffers_actions_setup,
119 buffers_actions_update },
120 { "channels", N_("Channels"), GIMP_ICON_CHANNEL,
121 channels_actions_setup,
122 channels_actions_update },
123 { "colormap", N_("Colormap"), GIMP_ICON_COLORMAP,
124 colormap_actions_setup,
125 colormap_actions_update },
126 { "context", N_("Context"), GIMP_ICON_DIALOG_TOOL_OPTIONS /* well... */,
127 context_actions_setup,
128 context_actions_update },
129 { "cursor-info", N_("Pointer Information"), NULL,
130 cursor_info_actions_setup,
131 cursor_info_actions_update },
132 { "dashboard", N_("Dashboard"), GIMP_ICON_DIALOG_DASHBOARD,
133 dashboard_actions_setup,
134 dashboard_actions_update },
135 { "debug", N_("Debug"), NULL,
136 debug_actions_setup,
137 debug_actions_update },
138 { "dialogs", N_("Dialogs"), NULL,
139 dialogs_actions_setup,
140 dialogs_actions_update },
141 { "dock", N_("Dock"), NULL,
142 dock_actions_setup,
143 dock_actions_update },
144 { "dockable", N_("Dockable"), NULL,
145 dockable_actions_setup,
146 dockable_actions_update },
147 { "documents", N_("Document History"), NULL,
148 documents_actions_setup,
149 documents_actions_update },
150 { "drawable", N_("Drawable"), GIMP_ICON_LAYER,
151 drawable_actions_setup,
152 drawable_actions_update },
153 { "dynamics", N_("Paint Dynamics"), GIMP_ICON_DYNAMICS,
154 dynamics_actions_setup,
155 dynamics_actions_update },
156 { "dynamics-editor", N_("Paint Dynamics Editor"), GIMP_ICON_DYNAMICS,
157 dynamics_editor_actions_setup,
158 dynamics_editor_actions_update },
159 { "edit", N_("Edit"), GIMP_ICON_EDIT,
160 edit_actions_setup,
161 edit_actions_update },
162 { "error-console", N_("Error Console"), GIMP_ICON_DIALOG_WARNING,
163 error_console_actions_setup,
164 error_console_actions_update },
165 { "file", N_("File"), "text-x-generic",
166 file_actions_setup,
167 file_actions_update },
168 { "filters", N_("Filters"), GIMP_ICON_GEGL,
169 filters_actions_setup,
170 filters_actions_update },
171 { "fonts", N_("Fonts"), GIMP_ICON_FONT,
172 fonts_actions_setup,
173 fonts_actions_update },
174 { "gradient-editor", N_("Gradient Editor"), GIMP_ICON_GRADIENT,
175 gradient_editor_actions_setup,
176 gradient_editor_actions_update },
177 { "gradients", N_("Gradients"), GIMP_ICON_GRADIENT,
178 gradients_actions_setup,
179 gradients_actions_update },
180 { "tool-presets", N_("Tool Presets"), GIMP_ICON_TOOL_PRESET,
181 tool_presets_actions_setup,
182 tool_presets_actions_update },
183 { "tool-preset-editor", N_("Tool Preset Editor"), GIMP_ICON_TOOL_PRESET,
184 tool_preset_editor_actions_setup,
185 tool_preset_editor_actions_update },
186 { "help", N_("Help"), "help-browser",
187 help_actions_setup,
188 help_actions_update },
189 { "image", N_("Image"), GIMP_ICON_IMAGE,
190 image_actions_setup,
191 image_actions_update },
192 { "images", N_("Images"), GIMP_ICON_IMAGE,
193 images_actions_setup,
194 images_actions_update },
195 { "layers", N_("Layers"), GIMP_ICON_LAYER,
196 layers_actions_setup,
197 layers_actions_update },
198 { "mypaint-brushes", N_("MyPaint Brushes"), GIMP_ICON_MYPAINT_BRUSH,
199 mypaint_brushes_actions_setup,
200 mypaint_brushes_actions_update },
201 { "palette-editor", N_("Palette Editor"), GIMP_ICON_PALETTE,
202 palette_editor_actions_setup,
203 palette_editor_actions_update },
204 { "palettes", N_("Palettes"), GIMP_ICON_PALETTE,
205 palettes_actions_setup,
206 palettes_actions_update },
207 { "patterns", N_("Patterns"), GIMP_ICON_PATTERN,
208 patterns_actions_setup,
209 patterns_actions_update },
210 { "plug-in", N_("Plug-ins"), GIMP_ICON_PLUGIN,
211 plug_in_actions_setup,
212 plug_in_actions_update },
213 { "quick-mask", N_("Quick Mask"), GIMP_ICON_QUICK_MASK_ON,
214 quick_mask_actions_setup,
215 quick_mask_actions_update },
216 { "sample-points", N_("Sample Points"), GIMP_ICON_SAMPLE_POINT,
217 sample_points_actions_setup,
218 sample_points_actions_update },
219 { "select", N_("Select"), GIMP_ICON_SELECTION,
220 select_actions_setup,
221 select_actions_update },
222 { "templates", N_("Templates"), GIMP_ICON_TEMPLATE,
223 templates_actions_setup,
224 templates_actions_update },
225 { "text-tool", N_("Text Tool"), GIMP_ICON_EDIT,
226 text_tool_actions_setup,
227 text_tool_actions_update },
228 { "text-editor", N_("Text Editor"), GIMP_ICON_EDIT,
229 text_editor_actions_setup,
230 text_editor_actions_update },
231 { "tool-options", N_("Tool Options"), GIMP_ICON_DIALOG_TOOL_OPTIONS,
232 tool_options_actions_setup,
233 tool_options_actions_update },
234 { "tools", N_("Tools"), GIMP_ICON_DIALOG_TOOLS,
235 tools_actions_setup,
236 tools_actions_update },
237 { "vectors", N_("Paths"), GIMP_ICON_PATH,
238 vectors_actions_setup,
239 vectors_actions_update },
240 { "view", N_("View"), GIMP_ICON_VISIBLE,
241 view_actions_setup,
242 view_actions_update },
243 { "windows", N_("Windows"), NULL,
244 windows_actions_setup,
245 windows_actions_update }
246 };
247
248
249 /* public functions */
250
251 void
actions_init(Gimp * gimp)252 actions_init (Gimp *gimp)
253 {
254 gint i;
255
256 g_return_if_fail (GIMP_IS_GIMP (gimp));
257 g_return_if_fail (global_action_factory == NULL);
258
259 global_action_factory = gimp_action_factory_new (gimp);
260
261 for (i = 0; i < G_N_ELEMENTS (action_groups); i++)
262 gimp_action_factory_group_register (global_action_factory,
263 action_groups[i].identifier,
264 gettext (action_groups[i].label),
265 action_groups[i].icon_name,
266 action_groups[i].setup_func,
267 action_groups[i].update_func);
268 }
269
270 void
actions_exit(Gimp * gimp)271 actions_exit (Gimp *gimp)
272 {
273 g_return_if_fail (GIMP_IS_GIMP (gimp));
274 g_return_if_fail (global_action_factory != NULL);
275 g_return_if_fail (global_action_factory->gimp == gimp);
276
277 g_clear_object (&global_action_factory);
278 }
279
280 Gimp *
action_data_get_gimp(gpointer data)281 action_data_get_gimp (gpointer data)
282 {
283 Gimp *result = NULL;
284 static gboolean recursion = FALSE;
285
286 if (! data || recursion)
287 return NULL;
288
289 recursion = TRUE;
290
291 if (GIMP_IS_GIMP (data))
292 result = data;
293
294 if (! result)
295 {
296 GimpDisplay *display = action_data_get_display (data);
297
298 if (display)
299 result = display->gimp;
300 }
301
302 if (! result)
303 {
304 GimpContext *context = action_data_get_context (data);
305
306 if (context)
307 result = context->gimp;
308 }
309
310 recursion = FALSE;
311
312 return result;
313 }
314
315 GimpContext *
action_data_get_context(gpointer data)316 action_data_get_context (gpointer data)
317 {
318 GimpContext *result = NULL;
319 static gboolean recursion = FALSE;
320
321 if (! data || recursion)
322 return NULL;
323
324 recursion = TRUE;
325
326 if (GIMP_IS_DOCK (data))
327 result = gimp_dock_get_context ((GimpDock *) data);
328 else if (GIMP_IS_DOCK_WINDOW (data))
329 result = gimp_dock_window_get_context (((GimpDockWindow *) data));
330 else if (GIMP_IS_CONTAINER_VIEW (data))
331 result = gimp_container_view_get_context ((GimpContainerView *) data);
332 else if (GIMP_IS_CONTAINER_EDITOR (data))
333 result = gimp_container_view_get_context (((GimpContainerEditor *) data)->view);
334 else if (GIMP_IS_IMAGE_EDITOR (data))
335 result = ((GimpImageEditor *) data)->context;
336 else if (GIMP_IS_NAVIGATION_EDITOR (data))
337 result = ((GimpNavigationEditor *) data)->context;
338
339 if (! result)
340 {
341 Gimp *gimp = action_data_get_gimp (data);
342
343 if (gimp)
344 result = gimp_get_user_context (gimp);
345 }
346
347 recursion = FALSE;
348
349 return result;
350 }
351
352 GimpImage *
action_data_get_image(gpointer data)353 action_data_get_image (gpointer data)
354 {
355 GimpImage *result = NULL;
356 static gboolean recursion = FALSE;
357
358 if (! data || recursion)
359 return NULL;
360
361 recursion = TRUE;
362
363 if (GIMP_IS_ITEM_TREE_VIEW (data))
364 result = gimp_item_tree_view_get_image ((GimpItemTreeView *) data);
365 else if (GIMP_IS_IMAGE_EDITOR (data))
366 result = ((GimpImageEditor *) data)->image;
367
368 if (! result)
369 {
370 GimpDisplay *display = action_data_get_display (data);
371
372 if (display)
373 result = gimp_display_get_image (display);
374 }
375
376 if (! result)
377 {
378 GimpContext *context = action_data_get_context (data);
379
380 if (context)
381 result = gimp_context_get_image (context);
382 }
383
384 recursion = FALSE;
385
386 return result;
387 }
388
389 GimpDisplay *
action_data_get_display(gpointer data)390 action_data_get_display (gpointer data)
391 {
392 GimpDisplay *result = NULL;
393 static gboolean recursion = FALSE;
394
395 if (! data || recursion)
396 return NULL;
397
398 recursion = TRUE;
399
400 if (GIMP_IS_DISPLAY (data))
401 result = data;
402 else if (GIMP_IS_IMAGE_WINDOW (data))
403 {
404 GimpDisplayShell *shell = gimp_image_window_get_active_shell (data);
405 result = shell ? shell->display : NULL;
406 }
407
408 if (! result)
409 {
410 GimpContext *context = action_data_get_context (data);
411
412 if (context)
413 result = gimp_context_get_display (context);
414 }
415
416 recursion = FALSE;
417
418 return result;
419 }
420
421 GimpDisplayShell *
action_data_get_shell(gpointer data)422 action_data_get_shell (gpointer data)
423 {
424 GimpDisplayShell *result = NULL;
425 static gboolean recursion = FALSE;
426
427 if (! data || recursion)
428 return NULL;
429
430 recursion = TRUE;
431
432 if (! result)
433 {
434 GimpDisplay *display = action_data_get_display (data);
435
436 if (display)
437 result = gimp_display_get_shell (display);
438 }
439
440 recursion = FALSE;
441
442 return result;
443 }
444
445 GtkWidget *
action_data_get_widget(gpointer data)446 action_data_get_widget (gpointer data)
447 {
448 GtkWidget *result = NULL;
449 static gboolean recursion = FALSE;
450
451 if (! data || recursion)
452 return NULL;
453
454 recursion = TRUE;
455
456 if (GTK_IS_WIDGET (data))
457 result = data;
458
459 if (! result)
460 {
461 GimpDisplay *display = action_data_get_display (data);
462
463 if (display)
464 result = GTK_WIDGET (gimp_display_get_shell (display));
465 }
466
467 if (! result)
468 result = dialogs_get_toolbox ();
469
470 recursion = FALSE;
471
472 return result;
473 }
474
475 gint
action_data_sel_count(gpointer data)476 action_data_sel_count (gpointer data)
477 {
478 if (GIMP_IS_CONTAINER_EDITOR (data))
479 {
480 GimpContainerEditor *editor;
481
482 editor = GIMP_CONTAINER_EDITOR (data);
483 return gimp_container_view_get_selected (editor->view, NULL);
484 }
485 else
486 {
487 return 0;
488 }
489 }
490
491 gdouble
action_select_value(GimpActionSelectType select_type,gdouble value,gdouble min,gdouble max,gdouble def,gdouble small_inc,gdouble inc,gdouble skip_inc,gdouble delta_factor,gboolean wrap)492 action_select_value (GimpActionSelectType select_type,
493 gdouble value,
494 gdouble min,
495 gdouble max,
496 gdouble def,
497 gdouble small_inc,
498 gdouble inc,
499 gdouble skip_inc,
500 gdouble delta_factor,
501 gboolean wrap)
502 {
503 switch (select_type)
504 {
505 case GIMP_ACTION_SELECT_SET_TO_DEFAULT:
506 value = def;
507 break;
508
509 case GIMP_ACTION_SELECT_FIRST:
510 value = min;
511 break;
512
513 case GIMP_ACTION_SELECT_LAST:
514 value = max;
515 break;
516
517 case GIMP_ACTION_SELECT_SMALL_PREVIOUS:
518 value -= small_inc;
519 break;
520
521 case GIMP_ACTION_SELECT_SMALL_NEXT:
522 value += small_inc;
523 break;
524
525 case GIMP_ACTION_SELECT_PREVIOUS:
526 value -= inc;
527 break;
528
529 case GIMP_ACTION_SELECT_NEXT:
530 value += inc;
531 break;
532
533 case GIMP_ACTION_SELECT_SKIP_PREVIOUS:
534 value -= skip_inc;
535 break;
536
537 case GIMP_ACTION_SELECT_SKIP_NEXT:
538 value += skip_inc;
539 break;
540
541 case GIMP_ACTION_SELECT_PERCENT_PREVIOUS:
542 g_return_val_if_fail (delta_factor >= 0.0, value);
543 value /= (1.0 + delta_factor);
544 break;
545
546 case GIMP_ACTION_SELECT_PERCENT_NEXT:
547 g_return_val_if_fail (delta_factor >= 0.0, value);
548 value *= (1.0 + delta_factor);
549 break;
550
551 default:
552 if ((gint) select_type >= 0)
553 value = (gdouble) select_type * (max - min) / 1000.0 + min;
554 else
555 g_return_val_if_reached (value);
556 break;
557 }
558
559 if (wrap)
560 {
561 while (value < min)
562 value = max - (min - value);
563
564 while (value > max)
565 value = min + (value - max);
566 }
567 else
568 {
569 value = CLAMP (value, min, max);
570 }
571
572 return value;
573 }
574
575 void
action_select_property(GimpActionSelectType select_type,GimpDisplay * display,GObject * object,const gchar * property_name,gdouble small_inc,gdouble inc,gdouble skip_inc,gdouble delta_factor,gboolean wrap)576 action_select_property (GimpActionSelectType select_type,
577 GimpDisplay *display,
578 GObject *object,
579 const gchar *property_name,
580 gdouble small_inc,
581 gdouble inc,
582 gdouble skip_inc,
583 gdouble delta_factor,
584 gboolean wrap)
585 {
586 GParamSpec *pspec;
587
588 g_return_if_fail (display == NULL || GIMP_IS_DISPLAY (display));
589 g_return_if_fail (G_IS_OBJECT (object));
590 g_return_if_fail (property_name != NULL);
591
592 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
593 property_name);
594
595 if (G_IS_PARAM_SPEC_DOUBLE (pspec))
596 {
597 gdouble value;
598
599 g_object_get (object, property_name, &value, NULL);
600
601 value = action_select_value (select_type,
602 value,
603 G_PARAM_SPEC_DOUBLE (pspec)->minimum,
604 G_PARAM_SPEC_DOUBLE (pspec)->maximum,
605 G_PARAM_SPEC_DOUBLE (pspec)->default_value,
606 small_inc, inc, skip_inc, delta_factor, wrap);
607
608 g_object_set (object, property_name, value, NULL);
609
610 if (display)
611 {
612 const gchar *blurb = g_param_spec_get_blurb (pspec);
613
614 if (blurb)
615 {
616 /* value description and new value shown in the status bar */
617 action_message (display, object, _("%s: %.2f"), blurb, value);
618 }
619 }
620 }
621 else if (G_IS_PARAM_SPEC_INT (pspec))
622 {
623 gint value;
624
625 g_object_get (object, property_name, &value, NULL);
626
627 value = action_select_value (select_type,
628 value,
629 G_PARAM_SPEC_INT (pspec)->minimum,
630 G_PARAM_SPEC_INT (pspec)->maximum,
631 G_PARAM_SPEC_INT (pspec)->default_value,
632 small_inc, inc, skip_inc, delta_factor, wrap);
633
634 g_object_set (object, property_name, value, NULL);
635
636 if (display)
637 {
638 const gchar *blurb = g_param_spec_get_blurb (pspec);
639
640 if (blurb)
641 {
642 /* value description and new value shown in the status bar */
643 action_message (display, object, _("%s: %d"), blurb, value);
644 }
645 }
646 }
647 else
648 {
649 g_return_if_reached ();
650 }
651 }
652
653 GimpObject *
action_select_object(GimpActionSelectType select_type,GimpContainer * container,GimpObject * current)654 action_select_object (GimpActionSelectType select_type,
655 GimpContainer *container,
656 GimpObject *current)
657 {
658 gint select_index;
659 gint n_children;
660
661 g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
662 g_return_val_if_fail (current == NULL || GIMP_IS_OBJECT (current), NULL);
663
664 if (! current)
665 return NULL;
666
667 n_children = gimp_container_get_n_children (container);
668
669 if (n_children == 0)
670 return NULL;
671
672 switch (select_type)
673 {
674 case GIMP_ACTION_SELECT_FIRST:
675 select_index = 0;
676 break;
677
678 case GIMP_ACTION_SELECT_LAST:
679 select_index = n_children - 1;
680 break;
681
682 case GIMP_ACTION_SELECT_PREVIOUS:
683 select_index = gimp_container_get_child_index (container, current) - 1;
684 break;
685
686 case GIMP_ACTION_SELECT_NEXT:
687 select_index = gimp_container_get_child_index (container, current) + 1;
688 break;
689
690 case GIMP_ACTION_SELECT_SKIP_PREVIOUS:
691 select_index = gimp_container_get_child_index (container, current) - 10;
692 break;
693
694 case GIMP_ACTION_SELECT_SKIP_NEXT:
695 select_index = gimp_container_get_child_index (container, current) + 10;
696 break;
697
698 default:
699 if ((gint) select_type >= 0)
700 select_index = (gint) select_type;
701 else
702 g_return_val_if_reached (current);
703 break;
704 }
705
706 select_index = CLAMP (select_index, 0, n_children - 1);
707
708 return gimp_container_get_child_by_index (container, select_index);
709 }
710
711 void
action_message(GimpDisplay * display,GObject * object,const gchar * format,...)712 action_message (GimpDisplay *display,
713 GObject *object,
714 const gchar *format,
715 ...)
716 {
717 GimpDisplayShell *shell = gimp_display_get_shell (display);
718 GimpStatusbar *statusbar = gimp_display_shell_get_statusbar (shell);
719 const gchar *icon_name = NULL;
720 va_list args;
721
722 if (GIMP_IS_TOOL_OPTIONS (object))
723 {
724 GimpToolInfo *tool_info = GIMP_TOOL_OPTIONS (object)->tool_info;
725
726 icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (tool_info));
727 }
728 else if (GIMP_IS_VIEWABLE (object))
729 {
730 icon_name = gimp_viewable_get_icon_name (GIMP_VIEWABLE (object));
731 }
732
733 va_start (args, format);
734 gimp_statusbar_push_temp_valist (statusbar, GIMP_MESSAGE_INFO,
735 icon_name, format, args);
736 va_end (args);
737 }
738