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 "libgimpconfig/gimpconfig.h"
26 
27 #include "tools-types.h"
28 
29 #include "core/gimp.h"
30 #include "core/gimpcontext.h"
31 #include "core/gimplist.h"
32 #include "core/gimpimage.h"
33 #include "core/gimptoolgroup.h"
34 #include "core/gimptoolinfo.h"
35 #include "core/gimptooloptions.h"
36 #include "core/gimptoolpreset.h"
37 
38 #include "display/gimpdisplay.h"
39 
40 #include "widgets/gimpcairo-wilber.h"
41 
42 #include "gimptool.h"
43 #include "gimptoolcontrol.h"
44 #include "tool_manager.h"
45 
46 
47 typedef struct _GimpToolManager GimpToolManager;
48 
49 struct _GimpToolManager
50 {
51   Gimp          *gimp;
52 
53   GimpTool      *active_tool;
54   GSList        *tool_stack;
55 
56   GimpToolGroup *active_tool_group;
57 
58   GQuark         image_clean_handler_id;
59   GQuark         image_dirty_handler_id;
60   GQuark         image_saving_handler_id;
61 };
62 
63 
64 /*  local function prototypes  */
65 
66 static void              tool_manager_set                       (Gimp            *gimp,
67                                                                  GimpToolManager *tool_manager);
68 static GimpToolManager * tool_manager_get                       (Gimp            *gimp);
69 
70 static void              tool_manager_select_tool               (GimpToolManager *tool_manager,
71                                                                  GimpTool        *tool);
72 
73 static void              tool_manager_set_active_tool_group     (GimpToolManager *tool_manager,
74                                                                  GimpToolGroup   *tool_group);
75 
76 static void              tool_manager_tool_changed              (GimpContext     *user_context,
77                                                                  GimpToolInfo    *tool_info,
78                                                                  GimpToolManager *tool_manager);
79 static void              tool_manager_preset_changed            (GimpContext     *user_context,
80                                                                  GimpToolPreset  *preset,
81                                                                  GimpToolManager *tool_manager);
82 static void              tool_manager_image_clean_dirty         (GimpImage       *image,
83                                                                  GimpDirtyMask    dirty_mask,
84                                                                  GimpToolManager *tool_manager);
85 static void              tool_manager_image_saving              (GimpImage       *image,
86                                                                  GimpToolManager *tool_manager);
87 static void              tool_manager_tool_ancestry_changed     (GimpToolInfo    *tool_info,
88                                                                  GimpToolManager *tool_manager);
89 static void              tool_manager_group_active_tool_changed (GimpToolGroup   *tool_group,
90                                                                  GimpToolManager *tool_manager);
91 
92 static void              tool_manager_cast_spell                (GimpToolInfo    *tool_info);
93 
94 
95 /*  public functions  */
96 
97 void
tool_manager_init(Gimp * gimp)98 tool_manager_init (Gimp *gimp)
99 {
100   GimpToolManager *tool_manager;
101   GimpContext     *user_context;
102 
103   g_return_if_fail (GIMP_IS_GIMP (gimp));
104 
105   tool_manager = g_slice_new0 (GimpToolManager);
106 
107   tool_manager->gimp                    = gimp;
108   tool_manager->active_tool             = NULL;
109   tool_manager->tool_stack              = NULL;
110   tool_manager->active_tool_group       = NULL;
111   tool_manager->image_clean_handler_id  = 0;
112   tool_manager->image_dirty_handler_id  = 0;
113   tool_manager->image_saving_handler_id = 0;
114 
115   tool_manager_set (gimp, tool_manager);
116 
117   tool_manager->image_clean_handler_id =
118     gimp_container_add_handler (gimp->images, "clean",
119                                 G_CALLBACK (tool_manager_image_clean_dirty),
120                                 tool_manager);
121 
122   tool_manager->image_dirty_handler_id =
123     gimp_container_add_handler (gimp->images, "dirty",
124                                 G_CALLBACK (tool_manager_image_clean_dirty),
125                                 tool_manager);
126 
127   tool_manager->image_saving_handler_id =
128     gimp_container_add_handler (gimp->images, "saving",
129                                 G_CALLBACK (tool_manager_image_saving),
130                                 tool_manager);
131 
132   user_context = gimp_get_user_context (gimp);
133 
134   g_signal_connect (user_context, "tool-changed",
135                     G_CALLBACK (tool_manager_tool_changed),
136                     tool_manager);
137   g_signal_connect (user_context, "tool-preset-changed",
138                     G_CALLBACK (tool_manager_preset_changed),
139                     tool_manager);
140 
141   tool_manager_tool_changed (user_context,
142                              gimp_context_get_tool (user_context),
143                              tool_manager);
144 }
145 
146 void
tool_manager_exit(Gimp * gimp)147 tool_manager_exit (Gimp *gimp)
148 {
149   GimpToolManager *tool_manager;
150   GimpContext     *user_context;
151 
152   g_return_if_fail (GIMP_IS_GIMP (gimp));
153 
154   tool_manager = tool_manager_get (gimp);
155   tool_manager_set (gimp, NULL);
156 
157   user_context = gimp_get_user_context (gimp);
158 
159   g_signal_handlers_disconnect_by_func (user_context,
160                                         tool_manager_tool_changed,
161                                         tool_manager);
162   g_signal_handlers_disconnect_by_func (user_context,
163                                         tool_manager_preset_changed,
164                                         tool_manager);
165 
166   gimp_container_remove_handler (gimp->images,
167                                  tool_manager->image_clean_handler_id);
168   gimp_container_remove_handler (gimp->images,
169                                  tool_manager->image_dirty_handler_id);
170   gimp_container_remove_handler (gimp->images,
171                                  tool_manager->image_saving_handler_id);
172 
173   if (tool_manager->active_tool)
174     {
175       g_signal_handlers_disconnect_by_func (
176         tool_manager->active_tool->tool_info,
177         tool_manager_tool_ancestry_changed,
178         tool_manager);
179 
180       g_clear_object (&tool_manager->active_tool);
181     }
182 
183   tool_manager_set_active_tool_group (tool_manager, NULL);
184 
185   g_slice_free (GimpToolManager, tool_manager);
186 }
187 
188 GimpTool *
tool_manager_get_active(Gimp * gimp)189 tool_manager_get_active (Gimp *gimp)
190 {
191   GimpToolManager *tool_manager;
192 
193   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
194 
195   tool_manager = tool_manager_get (gimp);
196 
197   return tool_manager->active_tool;
198 }
199 
200 void
tool_manager_push_tool(Gimp * gimp,GimpTool * tool)201 tool_manager_push_tool (Gimp     *gimp,
202                         GimpTool *tool)
203 {
204   GimpToolManager *tool_manager;
205   GimpDisplay     *focus_display = NULL;
206 
207   g_return_if_fail (GIMP_IS_GIMP (gimp));
208   g_return_if_fail (GIMP_IS_TOOL (tool));
209 
210   tool_manager = tool_manager_get (gimp);
211 
212   if (tool_manager->active_tool)
213     {
214       focus_display = tool_manager->active_tool->focus_display;
215 
216       tool_manager->tool_stack = g_slist_prepend (tool_manager->tool_stack,
217                                                   tool_manager->active_tool);
218 
219       g_object_ref (tool_manager->tool_stack->data);
220     }
221 
222   tool_manager_select_tool (tool_manager, tool);
223 
224   if (focus_display)
225     tool_manager_focus_display_active (gimp, focus_display);
226 }
227 
228 void
tool_manager_pop_tool(Gimp * gimp)229 tool_manager_pop_tool (Gimp *gimp)
230 {
231   GimpToolManager *tool_manager;
232 
233   g_return_if_fail (GIMP_IS_GIMP (gimp));
234 
235   tool_manager = tool_manager_get (gimp);
236 
237   if (tool_manager->tool_stack)
238     {
239       GimpTool *tool = tool_manager->tool_stack->data;
240 
241       tool_manager->tool_stack = g_slist_remove (tool_manager->tool_stack,
242                                                  tool);
243 
244       tool_manager_select_tool (tool_manager, tool);
245 
246       g_object_unref (tool);
247     }
248 }
249 
250 gboolean
tool_manager_initialize_active(Gimp * gimp,GimpDisplay * display)251 tool_manager_initialize_active (Gimp        *gimp,
252                                 GimpDisplay *display)
253 {
254   GimpToolManager *tool_manager;
255 
256   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
257   g_return_val_if_fail (GIMP_IS_DISPLAY (display), FALSE);
258 
259   tool_manager = tool_manager_get (gimp);
260 
261   if (tool_manager->active_tool)
262     {
263       GimpTool *tool = tool_manager->active_tool;
264 
265       if (gimp_tool_initialize (tool, display))
266         {
267           GimpImage *image = gimp_display_get_image (display);
268 
269           tool->drawable = gimp_image_get_active_drawable (image);
270 
271           return TRUE;
272         }
273     }
274 
275   return FALSE;
276 }
277 
278 void
tool_manager_control_active(Gimp * gimp,GimpToolAction action,GimpDisplay * display)279 tool_manager_control_active (Gimp           *gimp,
280                              GimpToolAction  action,
281                              GimpDisplay    *display)
282 {
283   GimpToolManager *tool_manager;
284 
285   g_return_if_fail (GIMP_IS_GIMP (gimp));
286 
287   tool_manager = tool_manager_get (gimp);
288 
289   if (tool_manager->active_tool)
290     {
291       GimpTool *tool = tool_manager->active_tool;
292 
293       if (display && gimp_tool_has_display (tool, display))
294         {
295           gimp_tool_control (tool, action, display);
296         }
297       else if (action == GIMP_TOOL_ACTION_HALT)
298         {
299           if (gimp_tool_control_is_active (tool->control))
300             gimp_tool_control_halt (tool->control);
301         }
302     }
303 }
304 
305 void
tool_manager_button_press_active(Gimp * gimp,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpButtonPressType press_type,GimpDisplay * display)306 tool_manager_button_press_active (Gimp                *gimp,
307                                   const GimpCoords    *coords,
308                                   guint32              time,
309                                   GdkModifierType      state,
310                                   GimpButtonPressType  press_type,
311                                   GimpDisplay         *display)
312 {
313   GimpToolManager *tool_manager;
314 
315   g_return_if_fail (GIMP_IS_GIMP (gimp));
316 
317   tool_manager = tool_manager_get (gimp);
318 
319   if (tool_manager->active_tool)
320     {
321       gimp_tool_button_press (tool_manager->active_tool,
322                               coords, time, state, press_type,
323                               display);
324     }
325 }
326 
327 void
tool_manager_button_release_active(Gimp * gimp,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpDisplay * display)328 tool_manager_button_release_active (Gimp             *gimp,
329                                     const GimpCoords *coords,
330                                     guint32           time,
331                                     GdkModifierType   state,
332                                     GimpDisplay      *display)
333 {
334   GimpToolManager *tool_manager;
335 
336   g_return_if_fail (GIMP_IS_GIMP (gimp));
337 
338   tool_manager = tool_manager_get (gimp);
339 
340   if (tool_manager->active_tool)
341     {
342       gimp_tool_button_release (tool_manager->active_tool,
343                                 coords, time, state,
344                                 display);
345     }
346 }
347 
348 void
tool_manager_motion_active(Gimp * gimp,const GimpCoords * coords,guint32 time,GdkModifierType state,GimpDisplay * display)349 tool_manager_motion_active (Gimp             *gimp,
350                             const GimpCoords *coords,
351                             guint32           time,
352                             GdkModifierType   state,
353                             GimpDisplay      *display)
354 {
355   GimpToolManager *tool_manager;
356 
357   g_return_if_fail (GIMP_IS_GIMP (gimp));
358 
359   tool_manager = tool_manager_get (gimp);
360 
361   if (tool_manager->active_tool)
362     {
363       gimp_tool_motion (tool_manager->active_tool,
364                         coords, time, state,
365                         display);
366     }
367 }
368 
369 gboolean
tool_manager_key_press_active(Gimp * gimp,GdkEventKey * kevent,GimpDisplay * display)370 tool_manager_key_press_active (Gimp        *gimp,
371                                GdkEventKey *kevent,
372                                GimpDisplay *display)
373 {
374   GimpToolManager *tool_manager;
375 
376   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
377 
378   tool_manager = tool_manager_get (gimp);
379 
380   if (tool_manager->active_tool)
381     {
382       return gimp_tool_key_press (tool_manager->active_tool,
383                                   kevent,
384                                   display);
385     }
386 
387   return FALSE;
388 }
389 
390 gboolean
tool_manager_key_release_active(Gimp * gimp,GdkEventKey * kevent,GimpDisplay * display)391 tool_manager_key_release_active (Gimp        *gimp,
392                                  GdkEventKey *kevent,
393                                  GimpDisplay *display)
394 {
395   GimpToolManager *tool_manager;
396 
397   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
398 
399   tool_manager = tool_manager_get (gimp);
400 
401   if (tool_manager->active_tool)
402     {
403       return gimp_tool_key_release (tool_manager->active_tool,
404                                     kevent,
405                                     display);
406     }
407 
408   return FALSE;
409 }
410 
411 void
tool_manager_focus_display_active(Gimp * gimp,GimpDisplay * display)412 tool_manager_focus_display_active (Gimp        *gimp,
413                                    GimpDisplay *display)
414 {
415   GimpToolManager *tool_manager;
416 
417   g_return_if_fail (GIMP_IS_GIMP (gimp));
418 
419   tool_manager = tool_manager_get (gimp);
420 
421   if (tool_manager->active_tool &&
422       ! gimp_tool_control_is_active (tool_manager->active_tool->control))
423     {
424       gimp_tool_set_focus_display (tool_manager->active_tool,
425                                    display);
426     }
427 }
428 
429 void
tool_manager_modifier_state_active(Gimp * gimp,GdkModifierType state,GimpDisplay * display)430 tool_manager_modifier_state_active (Gimp            *gimp,
431                                     GdkModifierType  state,
432                                     GimpDisplay     *display)
433 {
434   GimpToolManager *tool_manager;
435 
436   g_return_if_fail (GIMP_IS_GIMP (gimp));
437 
438   tool_manager = tool_manager_get (gimp);
439 
440   if (tool_manager->active_tool &&
441       ! gimp_tool_control_is_active (tool_manager->active_tool->control))
442     {
443       gimp_tool_set_modifier_state (tool_manager->active_tool,
444                                     state,
445                                     display);
446     }
447 }
448 
449 void
tool_manager_active_modifier_state_active(Gimp * gimp,GdkModifierType state,GimpDisplay * display)450 tool_manager_active_modifier_state_active (Gimp            *gimp,
451                                            GdkModifierType  state,
452                                            GimpDisplay     *display)
453 {
454   GimpToolManager *tool_manager;
455 
456   g_return_if_fail (GIMP_IS_GIMP (gimp));
457 
458   tool_manager = tool_manager_get (gimp);
459 
460   if (tool_manager->active_tool)
461     {
462       gimp_tool_set_active_modifier_state (tool_manager->active_tool,
463                                            state,
464                                            display);
465     }
466 }
467 
468 void
tool_manager_oper_update_active(Gimp * gimp,const GimpCoords * coords,GdkModifierType state,gboolean proximity,GimpDisplay * display)469 tool_manager_oper_update_active (Gimp             *gimp,
470                                  const GimpCoords *coords,
471                                  GdkModifierType   state,
472                                  gboolean          proximity,
473                                  GimpDisplay      *display)
474 {
475   GimpToolManager *tool_manager;
476 
477   g_return_if_fail (GIMP_IS_GIMP (gimp));
478 
479   tool_manager = tool_manager_get (gimp);
480 
481   if (tool_manager->active_tool &&
482       ! gimp_tool_control_is_active (tool_manager->active_tool->control))
483     {
484       gimp_tool_oper_update (tool_manager->active_tool,
485                              coords, state, proximity,
486                              display);
487     }
488 }
489 
490 void
tool_manager_cursor_update_active(Gimp * gimp,const GimpCoords * coords,GdkModifierType state,GimpDisplay * display)491 tool_manager_cursor_update_active (Gimp             *gimp,
492                                    const GimpCoords *coords,
493                                    GdkModifierType   state,
494                                    GimpDisplay      *display)
495 {
496   GimpToolManager *tool_manager;
497 
498   g_return_if_fail (GIMP_IS_GIMP (gimp));
499 
500   tool_manager = tool_manager_get (gimp);
501 
502   if (tool_manager->active_tool &&
503       ! gimp_tool_control_is_active (tool_manager->active_tool->control))
504     {
505       gimp_tool_cursor_update (tool_manager->active_tool,
506                                coords, state,
507                                display);
508     }
509 }
510 
511 const gchar *
tool_manager_can_undo_active(Gimp * gimp,GimpDisplay * display)512 tool_manager_can_undo_active (Gimp        *gimp,
513                               GimpDisplay *display)
514 {
515   GimpToolManager *tool_manager;
516 
517   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
518 
519   tool_manager = tool_manager_get (gimp);
520 
521   if (tool_manager->active_tool)
522     {
523       return gimp_tool_can_undo (tool_manager->active_tool,
524                                  display);
525     }
526 
527   return NULL;
528 }
529 
530 const gchar *
tool_manager_can_redo_active(Gimp * gimp,GimpDisplay * display)531 tool_manager_can_redo_active (Gimp        *gimp,
532                               GimpDisplay *display)
533 {
534   GimpToolManager *tool_manager;
535 
536   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
537 
538   tool_manager = tool_manager_get (gimp);
539 
540   if (tool_manager->active_tool)
541     {
542       return gimp_tool_can_redo (tool_manager->active_tool,
543                                  display);
544     }
545 
546   return NULL;
547 }
548 
549 gboolean
tool_manager_undo_active(Gimp * gimp,GimpDisplay * display)550 tool_manager_undo_active (Gimp        *gimp,
551                           GimpDisplay *display)
552 {
553   GimpToolManager *tool_manager;
554 
555   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
556 
557   tool_manager = tool_manager_get (gimp);
558 
559   if (tool_manager->active_tool)
560     {
561       return gimp_tool_undo (tool_manager->active_tool,
562                              display);
563     }
564 
565   return FALSE;
566 }
567 
568 gboolean
tool_manager_redo_active(Gimp * gimp,GimpDisplay * display)569 tool_manager_redo_active (Gimp        *gimp,
570                           GimpDisplay *display)
571 {
572   GimpToolManager *tool_manager;
573 
574   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
575 
576   tool_manager = tool_manager_get (gimp);
577 
578   if (tool_manager->active_tool)
579     {
580       return gimp_tool_redo (tool_manager->active_tool,
581                              display);
582     }
583 
584   return FALSE;
585 }
586 
587 GimpUIManager *
tool_manager_get_popup_active(Gimp * gimp,const GimpCoords * coords,GdkModifierType state,GimpDisplay * display,const gchar ** ui_path)588 tool_manager_get_popup_active (Gimp             *gimp,
589                                const GimpCoords *coords,
590                                GdkModifierType   state,
591                                GimpDisplay      *display,
592                                const gchar     **ui_path)
593 {
594   GimpToolManager *tool_manager;
595 
596   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
597 
598   tool_manager = tool_manager_get (gimp);
599 
600   if (tool_manager->active_tool)
601     {
602       return gimp_tool_get_popup (tool_manager->active_tool,
603                                   coords, state,
604                                   display,
605                                   ui_path);
606     }
607 
608   return NULL;
609 }
610 
611 
612 /*  private functions  */
613 
614 static GQuark tool_manager_quark = 0;
615 
616 static void
tool_manager_set(Gimp * gimp,GimpToolManager * tool_manager)617 tool_manager_set (Gimp            *gimp,
618                   GimpToolManager *tool_manager)
619 {
620   if (! tool_manager_quark)
621     tool_manager_quark = g_quark_from_static_string ("gimp-tool-manager");
622 
623   g_object_set_qdata (G_OBJECT (gimp), tool_manager_quark, tool_manager);
624 }
625 
626 static GimpToolManager *
tool_manager_get(Gimp * gimp)627 tool_manager_get (Gimp *gimp)
628 {
629   if (! tool_manager_quark)
630     tool_manager_quark = g_quark_from_static_string ("gimp-tool-manager");
631 
632   return g_object_get_qdata (G_OBJECT (gimp), tool_manager_quark);
633 }
634 
635 static void
tool_manager_select_tool(GimpToolManager * tool_manager,GimpTool * tool)636 tool_manager_select_tool (GimpToolManager *tool_manager,
637                           GimpTool        *tool)
638 {
639   Gimp *gimp = tool_manager->gimp;
640 
641   /*  reset the previously selected tool, but only if it is not only
642    *  temporarily pushed to the tool stack
643    */
644   if (tool_manager->active_tool)
645     {
646       if (! tool_manager->tool_stack ||
647           tool_manager->active_tool != tool_manager->tool_stack->data)
648         {
649           GimpTool    *active_tool = tool_manager->active_tool;
650           GimpDisplay *display;
651 
652           /*  NULL image returns any display (if there is any)  */
653           display = gimp_tool_has_image (active_tool, NULL);
654 
655           tool_manager_control_active (gimp, GIMP_TOOL_ACTION_HALT, display);
656           tool_manager_focus_display_active (gimp, NULL);
657         }
658     }
659 
660   g_set_object (&tool_manager->active_tool, tool);
661 }
662 
663 static void
tool_manager_set_active_tool_group(GimpToolManager * tool_manager,GimpToolGroup * tool_group)664 tool_manager_set_active_tool_group (GimpToolManager *tool_manager,
665                                     GimpToolGroup   *tool_group)
666 {
667   if (tool_group != tool_manager->active_tool_group)
668     {
669       if (tool_manager->active_tool_group)
670         {
671           g_signal_handlers_disconnect_by_func (
672             tool_manager->active_tool_group,
673             tool_manager_group_active_tool_changed,
674             tool_manager);
675         }
676 
677       g_set_weak_pointer (&tool_manager->active_tool_group, tool_group);
678 
679       if (tool_manager->active_tool_group)
680         {
681           g_signal_connect (
682             tool_manager->active_tool_group, "active-tool-changed",
683             G_CALLBACK (tool_manager_group_active_tool_changed),
684             tool_manager);
685         }
686     }
687 }
688 
689 static void
tool_manager_tool_changed(GimpContext * user_context,GimpToolInfo * tool_info,GimpToolManager * tool_manager)690 tool_manager_tool_changed (GimpContext     *user_context,
691                            GimpToolInfo    *tool_info,
692                            GimpToolManager *tool_manager)
693 {
694   GimpTool *new_tool = NULL;
695 
696   if (! tool_info)
697     return;
698 
699   if (! g_type_is_a (tool_info->tool_type, GIMP_TYPE_TOOL))
700     {
701       g_warning ("%s: tool_info->tool_type is no GimpTool subclass",
702                  G_STRFUNC);
703       return;
704     }
705 
706   /* FIXME: gimp_busy HACK */
707   if (user_context->gimp->busy)
708     {
709       /*  there may be contexts waiting for the user_context's "tool-changed"
710        *  signal, so stop emitting it.
711        */
712       g_signal_stop_emission_by_name (user_context, "tool-changed");
713 
714       if (G_TYPE_FROM_INSTANCE (tool_manager->active_tool) !=
715           tool_info->tool_type)
716         {
717           g_signal_handlers_block_by_func (user_context,
718                                            tool_manager_tool_changed,
719                                            tool_manager);
720 
721           /*  explicitly set the current tool  */
722           gimp_context_set_tool (user_context,
723                                  tool_manager->active_tool->tool_info);
724 
725           g_signal_handlers_unblock_by_func (user_context,
726                                              tool_manager_tool_changed,
727                                              tool_manager);
728         }
729 
730       return;
731     }
732 
733   g_return_if_fail (tool_manager->tool_stack == NULL);
734 
735   if (tool_manager->active_tool)
736     {
737       GimpTool    *active_tool = tool_manager->active_tool;
738       GimpDisplay *display;
739 
740       /*  NULL image returns any display (if there is any)  */
741       display = gimp_tool_has_image (active_tool, NULL);
742 
743       /*  commit the old tool's operation before creating the new tool
744        *  because creating a tool might mess with the old tool's
745        *  options (old and new tool might be the same)
746        */
747       if (display)
748         tool_manager_control_active (user_context->gimp, GIMP_TOOL_ACTION_COMMIT,
749                                      display);
750 
751       g_signal_handlers_disconnect_by_func (active_tool->tool_info,
752                                             tool_manager_tool_ancestry_changed,
753                                             tool_manager);
754     }
755 
756   g_signal_connect (tool_info, "ancestry-changed",
757                     G_CALLBACK (tool_manager_tool_ancestry_changed),
758                     tool_manager);
759 
760   tool_manager_tool_ancestry_changed (tool_info, tool_manager);
761 
762   new_tool = g_object_new (tool_info->tool_type,
763                            "tool-info", tool_info,
764                            NULL);
765 
766   tool_manager_select_tool (tool_manager, new_tool);
767 
768   g_object_unref (new_tool);
769 
770   /* ??? */
771   tool_manager_cast_spell (tool_info);
772 }
773 
774 static void
tool_manager_copy_tool_options(GObject * src,GObject * dest)775 tool_manager_copy_tool_options (GObject *src,
776                                 GObject *dest)
777 {
778   GList *diff;
779 
780   diff = gimp_config_diff (src, dest, G_PARAM_READWRITE);
781 
782   if (diff)
783     {
784       GList *list;
785 
786       g_object_freeze_notify (dest);
787 
788       for (list = diff; list; list = list->next)
789         {
790           GParamSpec *prop_spec = list->data;
791 
792           if (g_type_is_a (prop_spec->owner_type, GIMP_TYPE_TOOL_OPTIONS) &&
793               ! (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY))
794             {
795               GValue value = G_VALUE_INIT;
796 
797               g_value_init (&value, prop_spec->value_type);
798 
799               g_object_get_property (src,  prop_spec->name, &value);
800               g_object_set_property (dest, prop_spec->name, &value);
801 
802               g_value_unset (&value);
803             }
804         }
805 
806       g_object_thaw_notify (dest);
807 
808       g_list_free (diff);
809     }
810 }
811 
812 static void
tool_manager_preset_changed(GimpContext * user_context,GimpToolPreset * preset,GimpToolManager * tool_manager)813 tool_manager_preset_changed (GimpContext     *user_context,
814                              GimpToolPreset  *preset,
815                              GimpToolManager *tool_manager)
816 {
817   GimpToolInfo *preset_tool;
818 
819   if (! preset || user_context->gimp->busy)
820     return;
821 
822   preset_tool = gimp_context_get_tool (GIMP_CONTEXT (preset->tool_options));
823 
824   /* first, select the preset's tool, even if it's already the active
825    * tool
826    */
827   gimp_context_set_tool (user_context, preset_tool);
828 
829   /* then, copy the context properties the preset remembers, possibly
830    * changing some tool options due to the "link brush stuff to brush
831    * defaults" settings in gimptooloptions.c
832    */
833   gimp_context_copy_properties (GIMP_CONTEXT (preset->tool_options),
834                                 user_context,
835                                 gimp_tool_preset_get_prop_mask (preset));
836 
837   /* finally, copy all tool options properties, overwriting any
838    * changes resulting from setting the context properties above, we
839    * really want exactly what is in the preset and nothing else
840    */
841   tool_manager_copy_tool_options (G_OBJECT (preset->tool_options),
842                                   G_OBJECT (preset_tool->tool_options));
843 }
844 
845 static void
tool_manager_image_clean_dirty(GimpImage * image,GimpDirtyMask dirty_mask,GimpToolManager * tool_manager)846 tool_manager_image_clean_dirty (GimpImage       *image,
847                                 GimpDirtyMask    dirty_mask,
848                                 GimpToolManager *tool_manager)
849 {
850   GimpTool *tool = tool_manager->active_tool;
851 
852   if (tool &&
853       ! gimp_tool_control_get_preserve (tool->control) &&
854       (gimp_tool_control_get_dirty_mask (tool->control) & dirty_mask))
855     {
856       GimpDisplay *display = gimp_tool_has_image (tool, image);
857 
858       if (display)
859         {
860           tool_manager_control_active (
861             image->gimp,
862             gimp_tool_control_get_dirty_action (tool->control),
863             display);
864         }
865     }
866 }
867 
868 static void
tool_manager_image_saving(GimpImage * image,GimpToolManager * tool_manager)869 tool_manager_image_saving (GimpImage       *image,
870                            GimpToolManager *tool_manager)
871 {
872   GimpTool *tool = tool_manager->active_tool;
873 
874   if (tool &&
875       ! gimp_tool_control_get_preserve (tool->control))
876     {
877       GimpDisplay *display = gimp_tool_has_image (tool, image);
878 
879       if (display)
880         tool_manager_control_active (image->gimp, GIMP_TOOL_ACTION_COMMIT,
881                                      display);
882     }
883 }
884 
885 static void
tool_manager_tool_ancestry_changed(GimpToolInfo * tool_info,GimpToolManager * tool_manager)886 tool_manager_tool_ancestry_changed (GimpToolInfo    *tool_info,
887                                     GimpToolManager *tool_manager)
888 {
889   GimpViewable *parent;
890 
891   parent = gimp_viewable_get_parent (GIMP_VIEWABLE (tool_info));
892 
893   if (parent)
894     {
895       gimp_tool_group_set_active_tool_info (GIMP_TOOL_GROUP (parent),
896                                             tool_info);
897     }
898 
899   tool_manager_set_active_tool_group (tool_manager, GIMP_TOOL_GROUP (parent));
900 }
901 
902 static void
tool_manager_group_active_tool_changed(GimpToolGroup * tool_group,GimpToolManager * tool_manager)903 tool_manager_group_active_tool_changed (GimpToolGroup   *tool_group,
904                                         GimpToolManager *tool_manager)
905 {
906   gimp_context_set_tool (tool_manager->gimp->user_context,
907                          gimp_tool_group_get_active_tool_info (tool_group));
908 }
909 
910 static void
tool_manager_cast_spell(GimpToolInfo * tool_info)911 tool_manager_cast_spell (GimpToolInfo *tool_info)
912 {
913   typedef struct
914   {
915     const gchar *sequence;
916     GCallback    func;
917   } Spell;
918 
919   static const Spell spells[] =
920   {
921     { .sequence = "gimp-warp-tool\0"
922                   "gimp-iscissors-tool\0"
923                   "gimp-gradient-tool\0"
924                   "gimp-vector-tool\0"
925                   "gimp-ellipse-select-tool\0"
926                   "gimp-rect-select-tool\0",
927       .func     = gimp_cairo_wilber_toggle_pointer_eyes
928     }
929   };
930 
931   static const gchar *spell_progress[G_N_ELEMENTS (spells)];
932   const gchar        *tool_name;
933   gint                i;
934 
935   tool_name = gimp_object_get_name (GIMP_OBJECT (tool_info));
936 
937   for (i = 0; i < G_N_ELEMENTS (spells); i++)
938     {
939       if (! spell_progress[i])
940         spell_progress[i] = spells[i].sequence;
941 
942       while (spell_progress[i])
943         {
944           if (! strcmp (tool_name, spell_progress[i]))
945             {
946               spell_progress[i] += strlen (spell_progress[i]) + 1;
947 
948               if (! *spell_progress[i])
949                 {
950                   spell_progress[i] = NULL;
951 
952                   spells[i].func ();
953                 }
954 
955               break;
956             }
957           else
958             {
959               if (spell_progress[i] == spells[i].sequence)
960                 spell_progress[i] = NULL;
961               else
962                 spell_progress[i] = spells[i].sequence;
963             }
964         }
965     }
966 }
967