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 "libgimpmath/gimpmath.h"
26 
27 #include "actions-types.h"
28 
29 #include "core/gimp.h"
30 #include "core/gimpcontainer.h"
31 #include "core/gimpcontext.h"
32 #include "core/gimptoolinfo.h"
33 
34 #include "paint/gimpinkoptions.h"
35 #include "paint/gimpairbrushoptions.h"
36 #include "paint/gimpmybrushoptions.h"
37 
38 #include "widgets/gimpaction.h"
39 #include "widgets/gimpenumaction.h"
40 #include "widgets/gimpuimanager.h"
41 
42 #include "display/gimpdisplay.h"
43 
44 #include "tools/gimp-tools.h"
45 #include "tools/gimpcoloroptions.h"
46 #include "tools/gimpforegroundselectoptions.h"
47 #include "tools/gimprectangleoptions.h"
48 #include "tools/gimptool.h"
49 #include "tools/gimptoolcontrol.h"
50 #include "tools/gimptransformoptions.h"
51 #include "tools/gimptransformtool.h"
52 #include "tools/gimpwarpoptions.h"
53 #include "tools/tool_manager.h"
54 
55 #include "actions.h"
56 #include "tools-commands.h"
57 
58 
59 /*  local function prototypes  */
60 
61 static void   tools_activate_enum_action (const gchar *action_desc,
62                                           GVariant    *value);
63 
64 
65 /*  local variables  */
66 
67 /* this is a hack to allow GimpToolButton to activate a tool-selection action
68  * without initializing the tool
69  */
70 static gint tools_select_cmd_initialize_blocked = 0;
71 
72 
73 /*  public functions  */
74 
75 void
tools_select_cmd_callback(GimpAction * action,GVariant * value,gpointer data)76 tools_select_cmd_callback (GimpAction *action,
77                            GVariant   *value,
78                            gpointer    data)
79 {
80   Gimp              *gimp;
81   GimpToolInfo      *tool_info;
82   GimpContext       *context;
83   GimpDisplay       *display;
84   const gchar       *tool_name;
85   gboolean           set_transform_type = FALSE;
86   GimpTransformType  transform_type;
87   return_if_no_gimp (gimp, data);
88 
89   tool_name = g_variant_get_string (value, NULL);
90 
91   /*  special case gimp-rotate-tool being called from the Image or Layer
92    *  menus
93    */
94   if (strcmp (tool_name, "gimp-rotate-layer") == 0)
95     {
96       tool_name          = "gimp-rotate-tool";
97       set_transform_type = TRUE;
98       transform_type     = GIMP_TRANSFORM_TYPE_LAYER;
99     }
100   else if (strcmp (tool_name, "gimp-rotate-image") == 0)
101     {
102       tool_name          = "gimp-rotate-tool";
103       set_transform_type = TRUE;
104       transform_type     = GIMP_TRANSFORM_TYPE_IMAGE;
105     }
106 
107   tool_info = gimp_get_tool_info (gimp, tool_name);
108 
109   context = gimp_get_user_context (gimp);
110 
111   /*  always allocate a new tool when selected from the image menu
112    */
113   if (gimp_context_get_tool (context) != tool_info ||
114       tools_select_cmd_initialize_blocked)
115     {
116       gimp_context_set_tool (context, tool_info);
117     }
118   else
119     {
120       gimp_context_tool_changed (context);
121     }
122 
123   if (set_transform_type)
124     {
125       GimpTool *tool = tool_manager_get_active (gimp);
126 
127       gimp_transform_tool_set_type (GIMP_TRANSFORM_TOOL (tool),
128                                     transform_type);
129     }
130 
131   if (! tools_select_cmd_initialize_blocked)
132     {
133       display = gimp_context_get_display (context);
134 
135       if (display && gimp_display_get_image (display))
136         tool_manager_initialize_active (gimp, display);
137     }
138 }
139 
140 void
tools_select_cmd_block_initialize(void)141 tools_select_cmd_block_initialize (void)
142 {
143   tools_select_cmd_initialize_blocked++;
144 }
145 
146 void
tools_select_cmd_unblock_initialize(void)147 tools_select_cmd_unblock_initialize (void)
148 {
149   g_return_if_fail (tools_select_cmd_initialize_blocked > 0);
150 
151   tools_select_cmd_initialize_blocked--;
152 }
153 
154 void
tools_color_average_radius_cmd_callback(GimpAction * action,GVariant * value,gpointer data)155 tools_color_average_radius_cmd_callback (GimpAction *action,
156                                          GVariant   *value,
157                                          gpointer    data)
158 {
159   GimpContext          *context;
160   GimpToolInfo         *tool_info;
161   GimpActionSelectType  select_type;
162   return_if_no_context (context, data);
163 
164   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
165 
166   tool_info = gimp_context_get_tool (context);
167 
168   if (tool_info && GIMP_IS_COLOR_OPTIONS (tool_info->tool_options))
169     {
170       action_select_property (select_type,
171                               action_data_get_display (data),
172                               G_OBJECT (tool_info->tool_options),
173                               "average-radius",
174                               1.0, 1.0, 10.0, 0.1, FALSE);
175     }
176 }
177 
178 void
tools_paintbrush_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)179 tools_paintbrush_size_cmd_callback (GimpAction *action,
180                                     GVariant   *value,
181                                     gpointer    data)
182 {
183   GimpContext          *context;
184   GimpToolInfo         *tool_info;
185   GimpActionSelectType  select_type;
186   return_if_no_context (context, data);
187 
188   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
189 
190   tool_info = gimp_context_get_tool (context);
191 
192   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
193     {
194       action_select_property (select_type,
195                               action_data_get_display (data),
196                               G_OBJECT (tool_info->tool_options),
197                               "brush-size",
198                               0.1, 1.0, 10.0, 1.0, FALSE);
199     }
200 }
201 
202 void
tools_paintbrush_angle_cmd_callback(GimpAction * action,GVariant * value,gpointer data)203 tools_paintbrush_angle_cmd_callback (GimpAction *action,
204                                      GVariant   *value,
205                                      gpointer    data)
206 {
207   GimpContext          *context;
208   GimpToolInfo         *tool_info;
209   GimpActionSelectType  select_type;
210   return_if_no_context (context, data);
211 
212   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
213 
214   tool_info = gimp_context_get_tool (context);
215 
216   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
217     {
218       action_select_property (select_type,
219                               action_data_get_display (data),
220                               G_OBJECT (tool_info->tool_options),
221                               "brush-angle",
222                               0.1, 1.0, 15.0, 0.1, TRUE);
223     }
224 }
225 
226 void
tools_paintbrush_aspect_ratio_cmd_callback(GimpAction * action,GVariant * value,gpointer data)227 tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action,
228                                             GVariant   *value,
229                                             gpointer    data)
230 {
231   GimpContext          *context;
232   GimpToolInfo         *tool_info;
233   GimpActionSelectType  select_type;
234   return_if_no_context (context, data);
235 
236   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
237 
238   tool_info = gimp_context_get_tool (context);
239 
240   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
241     {
242       action_select_property (select_type,
243                               action_data_get_display (data),
244                               G_OBJECT (tool_info->tool_options),
245                               "brush-aspect-ratio",
246                               0.01, 0.1, 1.0, 0.1, TRUE);
247     }
248 }
249 
250 void
tools_paintbrush_spacing_cmd_callback(GimpAction * action,GVariant * value,gpointer data)251 tools_paintbrush_spacing_cmd_callback (GimpAction *action,
252                                        GVariant   *value,
253                                        gpointer    data)
254 {
255   GimpContext          *context;
256   GimpToolInfo         *tool_info;
257   GimpActionSelectType  select_type;
258   return_if_no_context (context, data);
259 
260   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
261 
262   tool_info = gimp_context_get_tool (context);
263 
264   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
265     {
266       action_select_property (select_type,
267                               action_data_get_display (data),
268                               G_OBJECT (tool_info->tool_options),
269                               "brush-spacing",
270                               0.001, 0.01, 0.1, 0.1, FALSE);
271     }
272 }
273 
274 void
tools_paintbrush_hardness_cmd_callback(GimpAction * action,GVariant * value,gpointer data)275 tools_paintbrush_hardness_cmd_callback (GimpAction *action,
276                                         GVariant   *value,
277                                         gpointer    data)
278 {
279   GimpContext          *context;
280   GimpToolInfo         *tool_info;
281   GimpActionSelectType  select_type;
282   return_if_no_context (context, data);
283 
284   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
285 
286   tool_info = gimp_context_get_tool (context);
287 
288   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
289     {
290       action_select_property (select_type,
291                               action_data_get_display (data),
292                               G_OBJECT (tool_info->tool_options),
293                               "brush-hardness",
294                               0.001, 0.01, 0.1, 0.1, FALSE);
295     }
296 }
297 
298 void
tools_paintbrush_force_cmd_callback(GimpAction * action,GVariant * value,gpointer data)299 tools_paintbrush_force_cmd_callback (GimpAction *action,
300                                      GVariant   *value,
301                                      gpointer    data)
302 {
303   GimpContext          *context;
304   GimpToolInfo         *tool_info;
305   GimpActionSelectType  select_type;
306   return_if_no_context (context, data);
307 
308   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
309 
310   tool_info = gimp_context_get_tool (context);
311 
312   if (tool_info && GIMP_IS_PAINT_OPTIONS (tool_info->tool_options))
313     {
314       action_select_property (select_type,
315                               action_data_get_display (data),
316                               G_OBJECT (tool_info->tool_options),
317                               "brush-force",
318                               0.001, 0.01, 0.1, 0.1, FALSE);
319     }
320 }
321 
322 void
tools_ink_blob_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)323 tools_ink_blob_size_cmd_callback (GimpAction *action,
324                                   GVariant   *value,
325                                   gpointer    data)
326 {
327   GimpContext          *context;
328   GimpToolInfo         *tool_info;
329   GimpActionSelectType  select_type;
330   return_if_no_context (context, data);
331 
332   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
333 
334   tool_info = gimp_context_get_tool (context);
335 
336   if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
337     {
338       action_select_property (select_type,
339                               action_data_get_display (data),
340                               G_OBJECT (tool_info->tool_options),
341                               "size",
342                               0.1, 1.0, 10.0, 0.1, FALSE);
343     }
344 }
345 
346 void
tools_ink_blob_aspect_cmd_callback(GimpAction * action,GVariant * value,gpointer data)347 tools_ink_blob_aspect_cmd_callback (GimpAction *action,
348                                     GVariant   *value,
349                                     gpointer    data)
350 {
351   GimpContext          *context;
352   GimpToolInfo         *tool_info;
353   GimpActionSelectType  select_type;
354   return_if_no_context (context, data);
355 
356   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
357 
358   tool_info = gimp_context_get_tool (context);
359 
360   if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
361     {
362       action_select_property (select_type,
363                               action_data_get_display (data),
364                               G_OBJECT (tool_info->tool_options),
365                               "blob-aspect",
366                               1.0, 0.1, 1.0, 0.1, FALSE);
367     }
368 }
369 
370 void
tools_ink_blob_angle_cmd_callback(GimpAction * action,GVariant * value,gpointer data)371 tools_ink_blob_angle_cmd_callback (GimpAction *action,
372                                    GVariant   *value,
373                                    gpointer    data)
374 {
375   GimpContext          *context;
376   GimpToolInfo         *tool_info;
377   GimpActionSelectType  select_type;
378   return_if_no_context (context, data);
379 
380   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
381 
382   tool_info = gimp_context_get_tool (context);
383 
384   if (tool_info && GIMP_IS_INK_OPTIONS (tool_info->tool_options))
385     {
386       action_select_property (select_type,
387                               action_data_get_display (data),
388                               G_OBJECT (tool_info->tool_options),
389                               "blob-angle",
390                               gimp_deg_to_rad (0.1),
391                               gimp_deg_to_rad (1.0),
392                               gimp_deg_to_rad (15.0),
393                               0.1, TRUE);
394     }
395 }
396 
397 void
tools_airbrush_rate_cmd_callback(GimpAction * action,GVariant * value,gpointer data)398 tools_airbrush_rate_cmd_callback (GimpAction *action,
399                                   GVariant   *value,
400                                   gpointer    data)
401 {
402   GimpContext          *context;
403   GimpToolInfo         *tool_info;
404   GimpActionSelectType  select_type;
405   return_if_no_context (context, data);
406 
407   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
408 
409   tool_info = gimp_context_get_tool (context);
410 
411   if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options))
412     {
413       action_select_property (select_type,
414                               action_data_get_display (data),
415                               G_OBJECT (tool_info->tool_options),
416                               "rate",
417                               0.1, 1.0, 10.0, 0.1, FALSE);
418     }
419 }
420 
421 void
tools_airbrush_flow_cmd_callback(GimpAction * action,GVariant * value,gpointer data)422 tools_airbrush_flow_cmd_callback (GimpAction *action,
423                                   GVariant   *value,
424                                   gpointer    data)
425 {
426   GimpContext          *context;
427   GimpToolInfo         *tool_info;
428   GimpActionSelectType  select_type;
429   return_if_no_context (context, data);
430 
431   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
432 
433   tool_info = gimp_context_get_tool (context);
434 
435   if (tool_info && GIMP_IS_AIRBRUSH_OPTIONS (tool_info->tool_options))
436     {
437       action_select_property (select_type,
438                               action_data_get_display (data),
439                               G_OBJECT (tool_info->tool_options),
440                               "flow",
441                               0.1, 1.0, 10.0, 0.1, FALSE);
442     }
443 }
444 
445 void
tools_mybrush_radius_cmd_callback(GimpAction * action,GVariant * value,gpointer data)446 tools_mybrush_radius_cmd_callback (GimpAction *action,
447                                    GVariant   *value,
448                                    gpointer    data)
449 {
450   GimpContext          *context;
451   GimpToolInfo         *tool_info;
452   GimpActionSelectType  select_type;
453   return_if_no_context (context, data);
454 
455   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
456 
457   tool_info = gimp_context_get_tool (context);
458 
459   if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options))
460     {
461       action_select_property (select_type,
462                               action_data_get_display (data),
463                               G_OBJECT (tool_info->tool_options),
464                               "radius",
465                               0.1, 0.1, 0.5, 1.0, FALSE);
466     }
467 }
468 
469 void
tools_mybrush_hardness_cmd_callback(GimpAction * action,GVariant * value,gpointer data)470 tools_mybrush_hardness_cmd_callback (GimpAction *action,
471                                      GVariant   *value,
472                                      gpointer    data)
473 {
474   GimpContext          *context;
475   GimpToolInfo         *tool_info;
476   GimpActionSelectType  select_type;
477   return_if_no_context (context, data);
478 
479   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
480 
481   tool_info = gimp_context_get_tool (context);
482 
483   if (tool_info && GIMP_IS_MYBRUSH_OPTIONS (tool_info->tool_options))
484     {
485       action_select_property (select_type,
486                               action_data_get_display (data),
487                               G_OBJECT (tool_info->tool_options),
488                               "hardness",
489                               0.001, 0.01, 0.1, 1.0, FALSE);
490     }
491 }
492 
493 void
tools_fg_select_brush_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)494 tools_fg_select_brush_size_cmd_callback (GimpAction *action,
495                                          GVariant   *value,
496                                          gpointer    data)
497 {
498   GimpContext          *context;
499   GimpToolInfo         *tool_info;
500   GimpActionSelectType  select_type;
501   return_if_no_context (context, data);
502 
503   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
504 
505   tool_info = gimp_context_get_tool (context);
506 
507   if (tool_info && GIMP_IS_FOREGROUND_SELECT_OPTIONS (tool_info->tool_options))
508     {
509       action_select_property (select_type,
510                               action_data_get_display (data),
511                               G_OBJECT (tool_info->tool_options),
512                               "stroke-width",
513                               1.0, 4.0, 16.0, 0.1, FALSE);
514     }
515 }
516 
517 void
tools_transform_preview_opacity_cmd_callback(GimpAction * action,GVariant * value,gpointer data)518 tools_transform_preview_opacity_cmd_callback (GimpAction *action,
519                                               GVariant   *value,
520                                               gpointer    data)
521 {
522   GimpContext          *context;
523   GimpToolInfo         *tool_info;
524   GimpActionSelectType  select_type;
525   return_if_no_context (context, data);
526 
527   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
528 
529   tool_info = gimp_context_get_tool (context);
530 
531   if (tool_info && GIMP_IS_TRANSFORM_OPTIONS (tool_info->tool_options))
532     {
533       action_select_property (select_type,
534                               action_data_get_display (data),
535                               G_OBJECT (tool_info->tool_options),
536                               "preview-opacity",
537                               0.01, 0.1, 0.5, 0.1, FALSE);
538     }
539 }
540 
541 void
tools_warp_effect_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)542 tools_warp_effect_size_cmd_callback (GimpAction *action,
543                                      GVariant   *value,
544                                      gpointer    data)
545 {
546   GimpContext          *context;
547   GimpToolInfo         *tool_info;
548   GimpActionSelectType  select_type;
549   return_if_no_context (context, data);
550 
551   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
552 
553   tool_info = gimp_context_get_tool (context);
554 
555   if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options))
556     {
557       action_select_property (select_type,
558                               action_data_get_display (data),
559                               G_OBJECT (tool_info->tool_options),
560                               "effect-size",
561                               1.0, 4.0, 16.0, 0.1, FALSE);
562     }
563 }
564 
565 void
tools_warp_effect_hardness_cmd_callback(GimpAction * action,GVariant * value,gpointer data)566 tools_warp_effect_hardness_cmd_callback (GimpAction *action,
567                                          GVariant   *value,
568                                          gpointer    data)
569 {
570   GimpContext          *context;
571   GimpToolInfo         *tool_info;
572   GimpActionSelectType  select_type;
573   return_if_no_context (context, data);
574 
575   select_type = (GimpActionSelectType) g_variant_get_int32 (value);
576 
577   tool_info = gimp_context_get_tool (context);
578 
579   if (tool_info && GIMP_IS_WARP_OPTIONS (tool_info->tool_options))
580     {
581       action_select_property (select_type,
582                               action_data_get_display (data),
583                               G_OBJECT (tool_info->tool_options),
584                               "effect-hardness",
585                               0.001, 0.01, 0.1, 0.1, FALSE);
586     }
587 }
588 
589 void
tools_opacity_cmd_callback(GimpAction * action,GVariant * value,gpointer data)590 tools_opacity_cmd_callback (GimpAction *action,
591                             GVariant   *value,
592                             gpointer    data)
593 {
594   GimpContext *context;
595   GimpTool    *tool;
596   return_if_no_context (context, data);
597 
598   tool = tool_manager_get_active (context->gimp);
599 
600   if (tool)
601     {
602       const gchar *action_desc;
603 
604       action_desc = gimp_tool_control_get_action_opacity (tool->control);
605 
606       if (action_desc)
607         tools_activate_enum_action (action_desc, value);
608     }
609 }
610 
611 void
tools_size_cmd_callback(GimpAction * action,GVariant * value,gpointer data)612 tools_size_cmd_callback (GimpAction *action,
613                          GVariant   *value,
614                          gpointer    data)
615 {
616   GimpContext *context;
617   GimpTool    *tool;
618   return_if_no_context (context, data);
619 
620   tool = tool_manager_get_active (context->gimp);
621 
622   if (tool)
623     {
624       const gchar *action_desc;
625 
626       action_desc = gimp_tool_control_get_action_size (tool->control);
627 
628       if (action_desc)
629         tools_activate_enum_action (action_desc, value);
630     }
631 }
632 
633 void
tools_aspect_cmd_callback(GimpAction * action,GVariant * value,gpointer data)634 tools_aspect_cmd_callback (GimpAction *action,
635                            GVariant   *value,
636                            gpointer    data)
637 {
638   GimpContext *context;
639   GimpTool    *tool;
640   return_if_no_context (context, data);
641 
642   tool = tool_manager_get_active (context->gimp);
643 
644   if (tool)
645     {
646       const gchar *action_desc;
647 
648       action_desc = gimp_tool_control_get_action_aspect (tool->control);
649 
650       if (action_desc)
651         tools_activate_enum_action (action_desc, value);
652     }
653 }
654 
655 void
tools_angle_cmd_callback(GimpAction * action,GVariant * value,gpointer data)656 tools_angle_cmd_callback (GimpAction *action,
657                           GVariant   *value,
658                           gpointer    data)
659 {
660   GimpContext *context;
661   GimpTool    *tool;
662   return_if_no_context (context, data);
663 
664   tool = tool_manager_get_active (context->gimp);
665 
666   if (tool)
667     {
668       const gchar *action_desc;
669 
670       action_desc = gimp_tool_control_get_action_angle (tool->control);
671 
672       if (action_desc)
673         tools_activate_enum_action (action_desc, value);
674     }
675 }
676 
677 void
tools_spacing_cmd_callback(GimpAction * action,GVariant * value,gpointer data)678 tools_spacing_cmd_callback (GimpAction *action,
679                             GVariant   *value,
680                             gpointer    data)
681 {
682   GimpContext *context;
683   GimpTool    *tool;
684   return_if_no_context (context, data);
685 
686   tool = tool_manager_get_active (context->gimp);
687 
688   if (tool)
689     {
690       const gchar *action_desc;
691 
692       action_desc = gimp_tool_control_get_action_spacing (tool->control);
693 
694       if (action_desc)
695         tools_activate_enum_action (action_desc, value);
696     }
697 }
698 
699 void
tools_hardness_cmd_callback(GimpAction * action,GVariant * value,gpointer data)700 tools_hardness_cmd_callback (GimpAction *action,
701                              GVariant   *value,
702                              gpointer    data)
703 {
704   GimpContext *context;
705   GimpTool    *tool;
706   return_if_no_context (context, data);
707 
708   tool = tool_manager_get_active (context->gimp);
709 
710   if (tool)
711     {
712       const gchar *action_desc;
713 
714       action_desc = gimp_tool_control_get_action_hardness (tool->control);
715 
716       if (action_desc)
717         tools_activate_enum_action (action_desc, value);
718     }
719 }
720 
721 void
tools_force_cmd_callback(GimpAction * action,GVariant * value,gpointer data)722 tools_force_cmd_callback (GimpAction *action,
723                           GVariant   *value,
724                           gpointer    data)
725 {
726   GimpContext *context;
727   GimpTool    *tool;
728   return_if_no_context (context, data);
729 
730   tool = tool_manager_get_active (context->gimp);
731 
732   if (tool)
733     {
734       const gchar *action_desc;
735 
736       action_desc = gimp_tool_control_get_action_force (tool->control);
737 
738       if (action_desc)
739         tools_activate_enum_action (action_desc, value);
740     }
741 }
742 
743 void
tools_object_1_cmd_callback(GimpAction * action,GVariant * value,gpointer data)744 tools_object_1_cmd_callback (GimpAction *action,
745                              GVariant   *value,
746                              gpointer    data)
747 {
748   GimpContext *context;
749   GimpTool    *tool;
750   return_if_no_context (context, data);
751 
752   tool = tool_manager_get_active (context->gimp);
753 
754   if (tool)
755     {
756       const gchar *action_desc;
757 
758       action_desc = gimp_tool_control_get_action_object_1 (tool->control);
759 
760       if (action_desc)
761         tools_activate_enum_action (action_desc, value);
762     }
763 }
764 
765 void
tools_object_2_cmd_callback(GimpAction * action,GVariant * value,gpointer data)766 tools_object_2_cmd_callback (GimpAction *action,
767                              GVariant   *value,
768                              gpointer    data)
769 {
770   GimpContext *context;
771   GimpTool    *tool;
772   return_if_no_context (context, data);
773 
774   tool = tool_manager_get_active (context->gimp);
775 
776   if (tool)
777     {
778       const gchar *action_desc;
779 
780       action_desc = gimp_tool_control_get_action_object_2 (tool->control);
781 
782       if (action_desc)
783         tools_activate_enum_action (action_desc, value);
784     }
785 }
786 
787 
788 /*  private functions  */
789 
790 static void
tools_activate_enum_action(const gchar * action_desc,GVariant * value)791 tools_activate_enum_action (const gchar *action_desc,
792                             GVariant    *value)
793 {
794   gchar *group_name;
795   gchar *action_name;
796 
797   group_name  = g_strdup (action_desc);
798   action_name = strchr (group_name, '/');
799 
800   if (action_name)
801     {
802       GList      *managers;
803       GimpAction *action;
804 
805       *action_name++ = '\0';
806 
807       managers = gimp_ui_managers_from_name ("<Image>");
808 
809       action = gimp_ui_manager_find_action (managers->data,
810                                             group_name, action_name);
811 
812       if (GIMP_IS_ENUM_ACTION (action) &&
813           GIMP_ENUM_ACTION (action)->value_variable)
814         {
815           gimp_action_emit_activate (GIMP_ACTION (action), value);
816         }
817     }
818 
819   g_free (group_name);
820 }
821