1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimptooleditor.c
5 * Copyright (C) 2001-2009 Michael Natterer <mitch@gimp.org>
6 * Stephen Griffiths <scgmk5@gmail.com>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <gegl.h>
25 #include <gtk/gtk.h>
26
27 #include "libgimpconfig/gimpconfig.h"
28 #include "libgimpwidgets/gimpwidgets.h"
29
30 #include "widgets-types.h"
31
32 #include "core/gimp.h"
33 #include "core/gimpcontainer.h"
34 #include "core/gimpcontext.h"
35 #include "core/gimptoolgroup.h"
36 #include "core/gimptreehandler.h"
37
38 #include "tools/gimp-tools.h"
39
40 #include "gimpcontainertreestore.h"
41 #include "gimpcontainerview.h"
42 #include "gimpdnd.h"
43 #include "gimpviewrenderer.h"
44 #include "gimptooleditor.h"
45 #include "gimphelp-ids.h"
46 #include "gimpwidgets-utils.h"
47
48 #include "gimp-intl.h"
49
50
51 struct _GimpToolEditorPrivate
52 {
53 GimpContainer *container;
54 GimpContext *context;
55
56 GtkWidget *scrolled;
57
58 GtkWidget *new_group_button;
59 GtkWidget *raise_button;
60 GtkWidget *lower_button;
61 GtkWidget *delete_button;
62 GtkWidget *reset_button;
63
64 GimpTreeHandler *tool_item_notify_handler;
65
66 /* State of tools at creation of the editor, stored to support
67 * reverting changes
68 */
69 gchar *initial_tool_state;
70 };
71
72
73 /* local function prototypes */
74
75 static void gimp_tool_editor_view_iface_init (GimpContainerViewInterface *iface);
76
77 static void gimp_tool_editor_constructed (GObject *object);
78
79 static gboolean gimp_tool_editor_select_item (GimpContainerView *view,
80 GimpViewable *viewable,
81 gpointer insert_data);
82 static void gimp_tool_editor_set_container (GimpContainerView *container_view,
83 GimpContainer *container);
84 static void gimp_tool_editor_set_context (GimpContainerView *container_view,
85 GimpContext *context);
86
87 static gboolean gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
88 GimpDndType src_type,
89 GimpViewable *src_viewable,
90 GimpViewable *dest_viewable,
91 GtkTreePath *drop_path,
92 GtkTreeViewDropPosition drop_pos,
93 GtkTreeViewDropPosition *return_drop_pos,
94 GdkDragAction *return_drag_action);
95 static void gimp_tool_editor_drop_viewable (GimpContainerTreeView *tree_view,
96 GimpViewable *src_viewable,
97 GimpViewable *dest_viewable,
98 GtkTreeViewDropPosition drop_pos);
99
100 static void gimp_tool_editor_tool_item_notify (GimpToolItem *tool_item,
101 GParamSpec *pspec,
102 GimpToolEditor *tool_editor);
103
104 static void gimp_tool_editor_eye_data_func (GtkTreeViewColumn *tree_column,
105 GtkCellRenderer *cell,
106 GtkTreeModel *tree_model,
107 GtkTreeIter *iter,
108 gpointer data);
109 static void gimp_tool_editor_eye_clicked (GtkCellRendererToggle *toggle,
110 gchar *path_str,
111 GdkModifierType state,
112 GimpToolEditor *tool_editor);
113
114 static void gimp_tool_editor_new_group_clicked (GtkButton *button,
115 GimpToolEditor *tool_editor);
116 static void gimp_tool_editor_raise_clicked (GtkButton *button,
117 GimpToolEditor *tool_editor);
118 static void gimp_tool_editor_raise_extend_clicked (GtkButton *button,
119 GdkModifierType mask,
120 GimpToolEditor *tool_editor);
121 static void gimp_tool_editor_lower_clicked (GtkButton *button,
122 GimpToolEditor *tool_editor);
123 static void gimp_tool_editor_lower_extend_clicked (GtkButton *button,
124 GdkModifierType mask,
125 GimpToolEditor *tool_editor);
126 static void gimp_tool_editor_delete_clicked (GtkButton *button,
127 GimpToolEditor *tool_editor);
128 static void gimp_tool_editor_reset_clicked (GtkButton *button,
129 GimpToolEditor *tool_editor);
130
131 static GimpToolItem * gimp_tool_editor_get_selected_tool_item (GimpToolEditor *tool_editor);
132 static GimpContainer * gimp_tool_editor_get_tool_item_container (GimpToolEditor *tool_editor,
133 GimpToolItem *tool_item);
134
135 static void gimp_tool_editor_update_container (GimpToolEditor *tool_editor);
136 static void gimp_tool_editor_update_sensitivity (GimpToolEditor *tool_editor);
137
138
139 G_DEFINE_TYPE_WITH_CODE (GimpToolEditor, gimp_tool_editor,
140 GIMP_TYPE_CONTAINER_TREE_VIEW,
141 G_ADD_PRIVATE (GimpToolEditor)
142 G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONTAINER_VIEW,
143 gimp_tool_editor_view_iface_init))
144
145 #define parent_class gimp_tool_editor_parent_class
146
147 static GimpContainerViewInterface *parent_view_iface = NULL;
148
149
150 /* private functions */
151
152 static void
gimp_tool_editor_class_init(GimpToolEditorClass * klass)153 gimp_tool_editor_class_init (GimpToolEditorClass *klass)
154 {
155 GObjectClass *object_class = G_OBJECT_CLASS (klass);
156 GimpContainerTreeViewClass *tree_view_class = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
157
158 object_class->constructed = gimp_tool_editor_constructed;
159
160 tree_view_class->drop_possible = gimp_tool_editor_drop_possible;
161 tree_view_class->drop_viewable = gimp_tool_editor_drop_viewable;
162 }
163
164 static void
gimp_tool_editor_view_iface_init(GimpContainerViewInterface * iface)165 gimp_tool_editor_view_iface_init (GimpContainerViewInterface *iface)
166 {
167 parent_view_iface = g_type_interface_peek_parent (iface);
168
169 if (! parent_view_iface)
170 parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW);
171
172 iface->select_item = gimp_tool_editor_select_item;
173 iface->set_container = gimp_tool_editor_set_container;
174 iface->set_context = gimp_tool_editor_set_context;
175 }
176
177 static void
gimp_tool_editor_init(GimpToolEditor * tool_editor)178 gimp_tool_editor_init (GimpToolEditor *tool_editor)
179 {
180 tool_editor->priv = gimp_tool_editor_get_instance_private (tool_editor);
181 }
182
183 static void
gimp_tool_editor_constructed(GObject * object)184 gimp_tool_editor_constructed (GObject *object)
185 {
186 GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (object);
187 GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (object);
188 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (object);
189 gint view_size;
190 gint border_width;
191
192 G_OBJECT_CLASS (parent_class)->constructed (object);
193
194 view_size = gimp_container_view_get_view_size (container_view,
195 &border_width);
196
197 gimp_editor_set_show_name (GIMP_EDITOR (tool_editor), FALSE);
198
199 gtk_tree_view_set_level_indentation (tree_view->view,
200 0.8 * (view_size + 2 * border_width));
201
202 gimp_dnd_viewable_dest_add (GTK_WIDGET (tree_view->view),
203 GIMP_TYPE_TOOL_ITEM,
204 NULL, NULL);
205
206 /* construct tree view */
207 {
208 GtkTreeViewColumn *column;
209 GtkCellRenderer *eye_cell;
210 GtkStyle *tree_style;
211 GtkIconSize icon_size;
212
213 tree_style = gtk_widget_get_style (GTK_WIDGET (tool_editor));
214
215 icon_size = gimp_get_icon_size (GTK_WIDGET (tool_editor),
216 GIMP_ICON_VISIBLE,
217 GTK_ICON_SIZE_BUTTON,
218 view_size -
219 2 * tree_style->xthickness,
220 view_size -
221 2 * tree_style->ythickness);
222
223 column = gtk_tree_view_column_new ();
224 gtk_tree_view_insert_column (tree_view->view, column, 0);
225
226 eye_cell = gimp_cell_renderer_toggle_new (GIMP_ICON_VISIBLE);
227 g_object_set (eye_cell, "stock-size", icon_size, NULL);
228 gtk_tree_view_column_pack_start (column, eye_cell, FALSE);
229 gtk_tree_view_column_set_cell_data_func (column, eye_cell,
230 gimp_tool_editor_eye_data_func,
231 tree_view, NULL);
232
233 gimp_container_tree_view_add_toggle_cell (tree_view, eye_cell);
234
235 g_signal_connect (eye_cell, "clicked",
236 G_CALLBACK (gimp_tool_editor_eye_clicked),
237 tool_editor);
238 }
239
240 /* buttons */
241 tool_editor->priv->new_group_button =
242 gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_FOLDER_NEW,
243 _("Create a new tool group"), NULL,
244 G_CALLBACK (gimp_tool_editor_new_group_clicked),
245 NULL,
246 tool_editor);
247
248 tool_editor->priv->raise_button =
249 gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_UP,
250 _("Raise this item"),
251 _("Raise this item to the top"),
252 G_CALLBACK (gimp_tool_editor_raise_clicked),
253 G_CALLBACK (gimp_tool_editor_raise_extend_clicked),
254 tool_editor);
255
256 tool_editor->priv->lower_button =
257 gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_DOWN,
258 _("Lower this item"),
259 _("Lower this item to the bottom"),
260 G_CALLBACK (gimp_tool_editor_lower_clicked),
261 G_CALLBACK (gimp_tool_editor_lower_extend_clicked),
262 tool_editor);
263
264 tool_editor->priv->delete_button =
265 gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_EDIT_DELETE,
266 _("Delete this tool group"), NULL,
267 G_CALLBACK (gimp_tool_editor_delete_clicked),
268 NULL,
269 tool_editor);
270
271 tool_editor->priv->reset_button =
272 gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_RESET,
273 _("Reset tool order and visibility"), NULL,
274 G_CALLBACK (gimp_tool_editor_reset_clicked),
275 NULL,
276 tool_editor);
277
278 gimp_tool_editor_update_sensitivity (tool_editor);
279 }
280
281 static gboolean
gimp_tool_editor_select_item(GimpContainerView * container_view,GimpViewable * viewable,gpointer insert_data)282 gimp_tool_editor_select_item (GimpContainerView *container_view,
283 GimpViewable *viewable,
284 gpointer insert_data)
285 {
286 GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
287 gboolean result;
288
289 result = parent_view_iface->select_item (container_view,
290 viewable, insert_data);
291
292 gimp_tool_editor_update_sensitivity (tool_editor);
293
294 return result;
295 }
296
297 static void
gimp_tool_editor_set_container(GimpContainerView * container_view,GimpContainer * container)298 gimp_tool_editor_set_container (GimpContainerView *container_view,
299 GimpContainer *container)
300 {
301 GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
302
303 parent_view_iface->set_container (container_view, container);
304
305 gimp_tool_editor_update_container (tool_editor);
306 }
307
308 static void
gimp_tool_editor_set_context(GimpContainerView * container_view,GimpContext * context)309 gimp_tool_editor_set_context (GimpContainerView *container_view,
310 GimpContext *context)
311 {
312 GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
313
314 parent_view_iface->set_context (container_view, context);
315
316 gimp_tool_editor_update_container (tool_editor);
317 }
318
319 static gboolean
gimp_tool_editor_drop_possible(GimpContainerTreeView * tree_view,GimpDndType src_type,GimpViewable * src_viewable,GimpViewable * dest_viewable,GtkTreePath * drop_path,GtkTreeViewDropPosition drop_pos,GtkTreeViewDropPosition * return_drop_pos,GdkDragAction * return_drag_action)320 gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
321 GimpDndType src_type,
322 GimpViewable *src_viewable,
323 GimpViewable *dest_viewable,
324 GtkTreePath *drop_path,
325 GtkTreeViewDropPosition drop_pos,
326 GtkTreeViewDropPosition *return_drop_pos,
327 GdkDragAction *return_drag_action)
328 {
329 if (GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (
330 tree_view,
331 src_type, src_viewable, dest_viewable, drop_path, drop_pos,
332 return_drop_pos, return_drag_action))
333 {
334 if (gimp_viewable_get_parent (dest_viewable) ||
335 (gimp_viewable_get_children (dest_viewable) &&
336 (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
337 drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
338 {
339 return ! gimp_viewable_get_children (src_viewable);
340 }
341
342 return TRUE;
343 }
344
345 return FALSE;
346 }
347
348 static void
gimp_tool_editor_drop_viewable(GimpContainerTreeView * tree_view,GimpViewable * src_viewable,GimpViewable * dest_viewable,GtkTreeViewDropPosition drop_pos)349 gimp_tool_editor_drop_viewable (GimpContainerTreeView *tree_view,
350 GimpViewable *src_viewable,
351 GimpViewable *dest_viewable,
352 GtkTreeViewDropPosition drop_pos)
353 {
354 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tree_view);
355
356 GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (tree_view,
357 src_viewable,
358 dest_viewable,
359 drop_pos);
360
361 gimp_container_view_select_item (container_view, src_viewable);
362 }
363
364 static void
gimp_tool_editor_new_group_clicked(GtkButton * button,GimpToolEditor * tool_editor)365 gimp_tool_editor_new_group_clicked (GtkButton *button,
366 GimpToolEditor *tool_editor)
367 {
368 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
369 GimpContainer *container;
370 GimpToolItem *tool_item;
371 GimpToolGroup *group;
372 gint index = 0;
373
374 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
375
376 if (tool_item)
377 {
378 if (gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item)) != NULL)
379 return;
380
381 container = gimp_tool_editor_get_tool_item_container (tool_editor,
382 tool_item);
383
384 index = gimp_container_get_child_index (container,
385 GIMP_OBJECT (tool_item));
386 }
387 else
388 {
389 container = tool_editor->priv->container;
390 }
391
392 if (container)
393 {
394 group = gimp_tool_group_new ();
395
396 gimp_container_insert (container, GIMP_OBJECT (group), index);
397
398 g_object_unref (group);
399
400 gimp_container_view_select_item (container_view, GIMP_VIEWABLE (group));
401 }
402 }
403
404 static void
gimp_tool_editor_raise_clicked(GtkButton * button,GimpToolEditor * tool_editor)405 gimp_tool_editor_raise_clicked (GtkButton *button,
406 GimpToolEditor *tool_editor)
407 {
408 GimpToolItem *tool_item;
409
410 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
411
412 if (tool_item)
413 {
414 GimpContainer *container;
415 gint index;
416
417 container = gimp_tool_editor_get_tool_item_container (tool_editor,
418 tool_item);
419
420 index = gimp_container_get_child_index (container,
421 GIMP_OBJECT (tool_item));
422
423 if (index > 0)
424 {
425 gimp_container_reorder (container,
426 GIMP_OBJECT (tool_item), index - 1);
427 }
428 }
429 }
430
431 static void
gimp_tool_editor_raise_extend_clicked(GtkButton * button,GdkModifierType mask,GimpToolEditor * tool_editor)432 gimp_tool_editor_raise_extend_clicked (GtkButton *button,
433 GdkModifierType mask,
434 GimpToolEditor *tool_editor)
435 {
436 GimpToolItem *tool_item;
437
438 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
439
440 if (tool_item && (mask & GDK_SHIFT_MASK))
441 {
442 GimpContainer *container;
443 gint index;
444
445 container = gimp_tool_editor_get_tool_item_container (tool_editor,
446 tool_item);
447
448 index = gimp_container_get_child_index (container,
449 GIMP_OBJECT (tool_item));
450
451 if (index > 0)
452 {
453 gimp_container_reorder (container,
454 GIMP_OBJECT (tool_item), 0);
455 }
456 }
457 }
458
459 static void
gimp_tool_editor_lower_clicked(GtkButton * button,GimpToolEditor * tool_editor)460 gimp_tool_editor_lower_clicked (GtkButton *button,
461 GimpToolEditor *tool_editor)
462 {
463 GimpToolItem *tool_item;
464
465 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
466
467 if (tool_item)
468 {
469 GimpContainer *container;
470 gint index;
471
472 container = gimp_tool_editor_get_tool_item_container (tool_editor,
473 tool_item);
474
475 index = gimp_container_get_child_index (container,
476 GIMP_OBJECT (tool_item));
477
478 if (index + 1 < gimp_container_get_n_children (container))
479 {
480 gimp_container_reorder (container,
481 GIMP_OBJECT (tool_item), index + 1);
482 }
483 }
484 }
485
486 static void
gimp_tool_editor_lower_extend_clicked(GtkButton * button,GdkModifierType mask,GimpToolEditor * tool_editor)487 gimp_tool_editor_lower_extend_clicked (GtkButton *button,
488 GdkModifierType mask,
489 GimpToolEditor *tool_editor)
490 {
491 GimpToolItem *tool_item;
492
493 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
494
495 if (tool_item && (mask & GDK_SHIFT_MASK))
496 {
497 GimpContainer *container;
498 gint index;
499
500 container = gimp_tool_editor_get_tool_item_container (tool_editor,
501 tool_item);
502
503 index = gimp_container_get_n_children (container) - 1;
504 index = MAX (index, 0);
505
506 gimp_container_reorder (container,
507 GIMP_OBJECT (tool_item), index);
508 }
509 }
510
511 static void
gimp_tool_editor_delete_clicked(GtkButton * button,GimpToolEditor * tool_editor)512 gimp_tool_editor_delete_clicked (GtkButton *button,
513 GimpToolEditor *tool_editor)
514 {
515 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
516 GimpToolItem *tool_item;
517
518 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
519
520 if (tool_item)
521 {
522 GimpContainer *src_container;
523 GimpContainer *dest_container;
524 gint index;
525 gint dest_index;
526
527 src_container = gimp_viewable_get_children (GIMP_VIEWABLE (tool_item));
528 dest_container = gimp_tool_editor_get_tool_item_container (tool_editor,
529 tool_item);
530
531 if (! src_container)
532 return;
533
534 index = gimp_container_get_child_index (dest_container,
535 GIMP_OBJECT (tool_item));
536 dest_index = index;
537
538 g_object_ref (tool_item);
539
540 gimp_container_freeze (src_container);
541 gimp_container_freeze (dest_container);
542
543 gimp_container_remove (dest_container, GIMP_OBJECT (tool_item));
544
545 while (! gimp_container_is_empty (src_container))
546 {
547 GimpObject *object = gimp_container_get_first_child (src_container);
548
549 g_object_ref (object);
550
551 gimp_container_remove (src_container, object);
552 gimp_container_insert (dest_container, object, dest_index++);
553
554 g_object_unref (object);
555 }
556
557 gimp_container_thaw (dest_container);
558 gimp_container_thaw (src_container);
559
560 gimp_container_view_select_item (
561 container_view,
562 GIMP_VIEWABLE (gimp_container_get_child_by_index (dest_container,
563 index)));
564
565 g_object_unref (tool_item);
566 }
567 }
568
569 static void
gimp_tool_editor_reset_clicked(GtkButton * button,GimpToolEditor * tool_editor)570 gimp_tool_editor_reset_clicked (GtkButton *button,
571 GimpToolEditor *tool_editor)
572 {
573 gimp_tools_reset (tool_editor->priv->context->gimp,
574 tool_editor->priv->container,
575 FALSE);
576 }
577
578 static void
gimp_tool_editor_tool_item_notify(GimpToolItem * tool_item,GParamSpec * pspec,GimpToolEditor * tool_editor)579 gimp_tool_editor_tool_item_notify (GimpToolItem *tool_item,
580 GParamSpec *pspec,
581 GimpToolEditor *tool_editor)
582 {
583 GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (tool_editor);
584 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
585 GtkTreeIter *iter;
586
587 iter = gimp_container_view_lookup (container_view,
588 GIMP_VIEWABLE (tool_item));
589
590 if (iter)
591 {
592 GtkTreePath *path;
593
594 path = gtk_tree_model_get_path (tree_view->model, iter);
595
596 gtk_tree_model_row_changed (tree_view->model, path, iter);
597
598 gtk_tree_path_free (path);
599 }
600 }
601
602 static void
gimp_tool_editor_eye_data_func(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)603 gimp_tool_editor_eye_data_func (GtkTreeViewColumn *tree_column,
604 GtkCellRenderer *cell,
605 GtkTreeModel *tree_model,
606 GtkTreeIter *iter,
607 gpointer data)
608 {
609 GimpViewRenderer *renderer;
610 GimpToolItem *tool_item;
611
612 gtk_tree_model_get (tree_model, iter,
613 GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
614 -1);
615
616 tool_item = GIMP_TOOL_ITEM (renderer->viewable);
617
618 g_object_set (cell,
619 "active", gimp_tool_item_get_visible (tool_item),
620 "inconsistent", gimp_tool_item_get_visible (tool_item) &&
621 ! gimp_tool_item_get_shown (tool_item),
622 NULL);
623
624 g_object_unref (renderer);
625 }
626
627 static void
gimp_tool_editor_eye_clicked(GtkCellRendererToggle * toggle,gchar * path_str,GdkModifierType state,GimpToolEditor * tool_editor)628 gimp_tool_editor_eye_clicked (GtkCellRendererToggle *toggle,
629 gchar *path_str,
630 GdkModifierType state,
631 GimpToolEditor *tool_editor)
632 {
633 GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (tool_editor);
634 GtkTreePath *path;
635 GtkTreeIter iter;
636
637 path = gtk_tree_path_new_from_string (path_str);
638
639 if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
640 {
641 GimpViewRenderer *renderer;
642 GimpToolItem *tool_item;
643 gboolean active;
644
645 gtk_tree_model_get (tree_view->model, &iter,
646 GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
647 -1);
648
649 tool_item = GIMP_TOOL_ITEM (renderer->viewable);
650
651 g_object_get (toggle,
652 "active", &active,
653 NULL);
654
655 gimp_tool_item_set_visible (tool_item, ! active);
656
657 g_object_unref (renderer);
658 }
659
660 gtk_tree_path_free (path);
661 }
662
663 static GimpToolItem *
gimp_tool_editor_get_selected_tool_item(GimpToolEditor * tool_editor)664 gimp_tool_editor_get_selected_tool_item (GimpToolEditor *tool_editor)
665 {
666 GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (tool_editor);
667
668 if (tool_editor->priv->container)
669 {
670 GimpViewRenderer *renderer;
671 GimpToolItem *tool_item;
672 GtkTreeSelection *selection;
673 GtkTreeModel *model;
674 GtkTreeIter iter;
675
676 selection = gtk_tree_view_get_selection (tree_view->view);
677
678 if (! gtk_tree_selection_get_selected (selection, &model, &iter))
679 return NULL;
680
681 gtk_tree_model_get (model, &iter,
682 GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
683 -1);
684
685 tool_item = GIMP_TOOL_ITEM (renderer->viewable);
686
687 g_object_unref (renderer);
688
689 return tool_item;
690 }
691
692 return NULL;
693 }
694
695 static GimpContainer *
gimp_tool_editor_get_tool_item_container(GimpToolEditor * tool_editor,GimpToolItem * tool_item)696 gimp_tool_editor_get_tool_item_container (GimpToolEditor *tool_editor,
697 GimpToolItem *tool_item)
698 {
699 GimpViewable *parent;
700
701 parent = gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item));
702
703 if (parent)
704 {
705 return gimp_viewable_get_children (parent);
706 }
707 else
708 {
709 return tool_editor->priv->container;
710 }
711 }
712
713 static void
gimp_tool_editor_update_container(GimpToolEditor * tool_editor)714 gimp_tool_editor_update_container (GimpToolEditor *tool_editor)
715 {
716 GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
717 GimpContainer *container;
718 GimpContext *context;
719
720 g_clear_pointer (&tool_editor->priv->tool_item_notify_handler,
721 gimp_tree_handler_disconnect);
722
723 g_clear_pointer (&tool_editor->priv->initial_tool_state, g_free);
724
725 container = gimp_container_view_get_container (container_view);
726 context = gimp_container_view_get_context (container_view);
727
728 if (container && context)
729 {
730 GString *string;
731 GimpConfigWriter *writer;
732
733 tool_editor->priv->container = container;
734 tool_editor->priv->context = context;
735
736 tool_editor->priv->tool_item_notify_handler = gimp_tree_handler_connect (
737 container, "notify",
738 G_CALLBACK (gimp_tool_editor_tool_item_notify),
739 tool_editor);
740
741 /* save initial tool order */
742 string = g_string_new (NULL);
743
744 writer = gimp_config_writer_new_string (string);
745
746 gimp_tools_serialize (context->gimp, container, writer);
747
748 gimp_config_writer_finish (writer, NULL, NULL);
749
750 tool_editor->priv->initial_tool_state = g_string_free (string, FALSE);
751 }
752 }
753
754 static void
gimp_tool_editor_update_sensitivity(GimpToolEditor * tool_editor)755 gimp_tool_editor_update_sensitivity (GimpToolEditor *tool_editor)
756 {
757 GimpToolItem *tool_item;
758
759 tool_item = gimp_tool_editor_get_selected_tool_item (tool_editor);
760
761 if (tool_item)
762 {
763 GimpContainer *container;
764 gint index;
765
766 container = gimp_tool_editor_get_tool_item_container (tool_editor,
767 tool_item);
768
769 index = gimp_container_get_child_index (container,
770 GIMP_OBJECT (tool_item));
771
772 gtk_widget_set_sensitive (
773 tool_editor->priv->new_group_button,
774 gimp_viewable_get_parent (GIMP_VIEWABLE (tool_item)) == NULL);
775
776 gtk_widget_set_sensitive (
777 tool_editor->priv->raise_button,
778 index > 0);
779
780 gtk_widget_set_sensitive (
781 tool_editor->priv->lower_button,
782 index < gimp_container_get_n_children (container) - 1);
783
784 gtk_widget_set_sensitive (
785 tool_editor->priv->delete_button,
786 gimp_viewable_get_children (GIMP_VIEWABLE (tool_item)) != NULL);
787 }
788 else
789 {
790 gtk_widget_set_sensitive (tool_editor->priv->new_group_button, TRUE);
791 gtk_widget_set_sensitive (tool_editor->priv->raise_button, FALSE);
792 gtk_widget_set_sensitive (tool_editor->priv->lower_button, FALSE);
793 gtk_widget_set_sensitive (tool_editor->priv->delete_button, FALSE);
794 }
795 }
796
797
798 /* public functions */
799
800 GtkWidget *
gimp_tool_editor_new(GimpContainer * container,GimpContext * context,gint view_size,gint view_border_width)801 gimp_tool_editor_new (GimpContainer *container,
802 GimpContext *context,
803 gint view_size,
804 gint view_border_width)
805 {
806 GimpContainerView *container_view;
807
808 g_return_val_if_fail (GIMP_IS_CONTAINER (container), NULL);
809 g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
810
811 container_view = g_object_new (GIMP_TYPE_TOOL_EDITOR,
812 "view-size", view_size,
813 "view-border-width", view_border_width,
814 NULL);
815
816 gimp_container_view_set_context (container_view, context);
817 gimp_container_view_set_container (container_view, container);
818 gimp_container_view_set_reorderable (container_view, TRUE);
819
820 return GTK_WIDGET (container_view);
821 }
822
823 /**
824 * gimp_tool_editor_revert_changes:
825 * @tool_editor:
826 *
827 * Reverts the tool order and visibility to the state at creation.
828 **/
829 void
gimp_tool_editor_revert_changes(GimpToolEditor * tool_editor)830 gimp_tool_editor_revert_changes (GimpToolEditor *tool_editor)
831 {
832 GScanner *scanner;
833
834 g_return_if_fail (GIMP_IS_TOOL_EDITOR (tool_editor));
835
836 scanner = gimp_scanner_new_string (tool_editor->priv->initial_tool_state, -1,
837 NULL);
838
839 gimp_tools_deserialize (tool_editor->priv->context->gimp,
840 tool_editor->priv->container,
841 scanner);
842
843 gimp_scanner_destroy (scanner);
844 }
845