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