1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
3  *
4  * gimpitemstack.c
5  * Copyright (C) 2008 Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include <cairo.h>
26 #include <gdk-pixbuf/gdk-pixbuf.h>
27 #include <gegl.h>
28 
29 #include "libgimpcolor/gimpcolor.h"
30 
31 #include "core-types.h"
32 
33 #include "gimpitem.h"
34 #include "gimpitemstack.h"
35 
36 
37 /*  local function prototypes  */
38 
39 static void   gimp_item_stack_constructed (GObject       *object);
40 
41 static void   gimp_item_stack_add         (GimpContainer *container,
42                                            GimpObject    *object);
43 static void   gimp_item_stack_remove      (GimpContainer *container,
44                                            GimpObject    *object);
45 
46 
G_DEFINE_TYPE(GimpItemStack,gimp_item_stack,GIMP_TYPE_FILTER_STACK)47 G_DEFINE_TYPE (GimpItemStack, gimp_item_stack, GIMP_TYPE_FILTER_STACK)
48 
49 #define parent_class gimp_item_stack_parent_class
50 
51 
52 static void
53 gimp_item_stack_class_init (GimpItemStackClass *klass)
54 {
55   GObjectClass       *object_class    = G_OBJECT_CLASS (klass);
56   GimpContainerClass *container_class = GIMP_CONTAINER_CLASS (klass);
57 
58   object_class->constructed = gimp_item_stack_constructed;
59 
60   container_class->add      = gimp_item_stack_add;
61   container_class->remove   = gimp_item_stack_remove;
62 }
63 
64 static void
gimp_item_stack_init(GimpItemStack * stack)65 gimp_item_stack_init (GimpItemStack *stack)
66 {
67 }
68 
69 static void
gimp_item_stack_constructed(GObject * object)70 gimp_item_stack_constructed (GObject *object)
71 {
72   GimpContainer *container = GIMP_CONTAINER (object);
73 
74   G_OBJECT_CLASS (parent_class)->constructed (object);
75 
76   gimp_assert (g_type_is_a (gimp_container_get_children_type (container),
77                          GIMP_TYPE_ITEM));
78 }
79 
80 static void
gimp_item_stack_add(GimpContainer * container,GimpObject * object)81 gimp_item_stack_add (GimpContainer *container,
82                      GimpObject    *object)
83 {
84   g_object_ref_sink (object);
85 
86   GIMP_CONTAINER_CLASS (parent_class)->add (container, object);
87 
88   g_object_unref (object);
89 }
90 
91 static void
gimp_item_stack_remove(GimpContainer * container,GimpObject * object)92 gimp_item_stack_remove (GimpContainer *container,
93                         GimpObject    *object)
94 {
95   GIMP_CONTAINER_CLASS (parent_class)->remove (container, object);
96 }
97 
98 
99 /*  public functions  */
100 
101 GimpContainer *
gimp_item_stack_new(GType item_type)102 gimp_item_stack_new (GType item_type)
103 {
104   g_return_val_if_fail (g_type_is_a (item_type, GIMP_TYPE_ITEM), NULL);
105 
106   return g_object_new (GIMP_TYPE_ITEM_STACK,
107                        "name",          g_type_name (item_type),
108                        "children-type", item_type,
109                        "policy",        GIMP_CONTAINER_POLICY_STRONG,
110                        NULL);
111 }
112 
113 gint
gimp_item_stack_get_n_items(GimpItemStack * stack)114 gimp_item_stack_get_n_items (GimpItemStack *stack)
115 {
116   GList *list;
117   gint   n_items = 0;
118 
119   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), 0);
120 
121   for (list = GIMP_LIST (stack)->queue->head; list; list = g_list_next (list))
122     {
123       GimpItem      *item = list->data;
124       GimpContainer *children;
125 
126       n_items++;
127 
128       children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
129 
130       if (children)
131         n_items += gimp_item_stack_get_n_items (GIMP_ITEM_STACK (children));
132     }
133 
134   return n_items;
135 }
136 
137 gboolean
gimp_item_stack_is_flat(GimpItemStack * stack)138 gimp_item_stack_is_flat (GimpItemStack *stack)
139 {
140   GList *list;
141 
142   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), TRUE);
143 
144   for (list = GIMP_LIST (stack)->queue->head; list; list = g_list_next (list))
145     {
146       GimpViewable *viewable = list->data;
147 
148       if (gimp_viewable_get_children (viewable))
149         return FALSE;
150     }
151 
152   return TRUE;
153 }
154 
155 GList *
gimp_item_stack_get_item_iter(GimpItemStack * stack)156 gimp_item_stack_get_item_iter (GimpItemStack *stack)
157 {
158   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), NULL);
159 
160   return GIMP_LIST (stack)->queue->head;
161 }
162 
163 GList *
gimp_item_stack_get_item_list(GimpItemStack * stack)164 gimp_item_stack_get_item_list (GimpItemStack *stack)
165 {
166   GList *list;
167   GList *result = NULL;
168 
169   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), NULL);
170 
171   for (list = GIMP_LIST (stack)->queue->head;
172        list;
173        list = g_list_next (list))
174     {
175       GimpViewable  *viewable = list->data;
176       GimpContainer *children;
177 
178       result = g_list_prepend (result, viewable);
179 
180       children = gimp_viewable_get_children (viewable);
181 
182       if (children)
183         {
184           GList *child_list;
185 
186           child_list = gimp_item_stack_get_item_list (GIMP_ITEM_STACK (children));
187 
188           while (child_list)
189             {
190               result = g_list_prepend (result, child_list->data);
191 
192               child_list = g_list_remove (child_list, child_list->data);
193             }
194         }
195     }
196 
197   return g_list_reverse (result);
198 }
199 
200 GimpItem *
gimp_item_stack_get_item_by_tattoo(GimpItemStack * stack,GimpTattoo tattoo)201 gimp_item_stack_get_item_by_tattoo (GimpItemStack *stack,
202                                     GimpTattoo     tattoo)
203 {
204   GList *list;
205 
206   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), NULL);
207 
208   for (list = GIMP_LIST (stack)->queue->head; list; list = g_list_next (list))
209     {
210       GimpItem      *item = list->data;
211       GimpContainer *children;
212 
213       if (gimp_item_get_tattoo (item) == tattoo)
214         return item;
215 
216       children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
217 
218       if (children)
219         {
220           item = gimp_item_stack_get_item_by_tattoo (GIMP_ITEM_STACK (children),
221                                                      tattoo);
222 
223           if (item)
224             return item;
225         }
226     }
227 
228   return NULL;
229 }
230 
231 GimpItem *
gimp_item_stack_get_item_by_path(GimpItemStack * stack,GList * path)232 gimp_item_stack_get_item_by_path (GimpItemStack *stack,
233                                   GList         *path)
234 {
235   GimpContainer *container;
236   GimpItem      *item = NULL;
237 
238   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), NULL);
239   g_return_val_if_fail (path != NULL, NULL);
240 
241   container = GIMP_CONTAINER (stack);
242 
243   while (path)
244     {
245       guint32 i = GPOINTER_TO_UINT (path->data);
246 
247       item = GIMP_ITEM (gimp_container_get_child_by_index (container, i));
248 
249       g_return_val_if_fail (GIMP_IS_ITEM (item), item);
250 
251       if (path->next)
252         {
253           container = gimp_viewable_get_children (GIMP_VIEWABLE (item));
254 
255           g_return_val_if_fail (GIMP_IS_ITEM_STACK (container), item);
256         }
257 
258       path = path->next;
259     }
260 
261   return item;
262 }
263 
264 GimpItem *
gimp_item_stack_get_parent_by_path(GimpItemStack * stack,GList * path,gint * index)265 gimp_item_stack_get_parent_by_path (GimpItemStack *stack,
266                                     GList         *path,
267                                     gint          *index)
268 {
269   GimpItem *parent = NULL;
270   guint32   i;
271 
272   g_return_val_if_fail (GIMP_IS_ITEM_STACK (stack), NULL);
273   g_return_val_if_fail (path != NULL, NULL);
274 
275   i = GPOINTER_TO_UINT (path->data);
276 
277   if (index)
278     *index = i;
279 
280   while (path->next)
281     {
282       GimpObject    *child;
283       GimpContainer *children;
284 
285       child = gimp_container_get_child_by_index (GIMP_CONTAINER (stack), i);
286 
287       g_return_val_if_fail (GIMP_IS_ITEM (child), parent);
288 
289       children = gimp_viewable_get_children (GIMP_VIEWABLE (child));
290 
291       g_return_val_if_fail (GIMP_IS_ITEM_STACK (children), parent);
292 
293       parent = GIMP_ITEM (child);
294       stack  = GIMP_ITEM_STACK (children);
295 
296       path = path->next;
297 
298       i = GPOINTER_TO_UINT (path->data);
299 
300       if (index)
301         *index = i;
302     }
303 
304   return parent;
305 }
306 
307 static void
gimp_item_stack_viewable_invalidate_previews(GimpViewable * viewable)308 gimp_item_stack_viewable_invalidate_previews (GimpViewable *viewable)
309 {
310   GimpContainer *children = gimp_viewable_get_children (viewable);
311 
312   if (children)
313     gimp_item_stack_invalidate_previews (GIMP_ITEM_STACK (children));
314 
315   gimp_viewable_invalidate_preview (viewable);
316 }
317 
318 void
gimp_item_stack_invalidate_previews(GimpItemStack * stack)319 gimp_item_stack_invalidate_previews (GimpItemStack *stack)
320 {
321   g_return_if_fail (GIMP_IS_ITEM_STACK (stack));
322 
323   gimp_container_foreach (GIMP_CONTAINER (stack),
324                           (GFunc) gimp_item_stack_viewable_invalidate_previews,
325                           NULL);
326 }
327 
328 static void
gimp_item_stack_viewable_profile_changed(GimpViewable * viewable)329 gimp_item_stack_viewable_profile_changed (GimpViewable *viewable)
330 {
331   GimpContainer *children = gimp_viewable_get_children (viewable);
332 
333   if (children)
334     gimp_item_stack_profile_changed (GIMP_ITEM_STACK (children));
335 
336   if (GIMP_IS_COLOR_MANAGED (viewable))
337     gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (viewable));
338 }
339 
340 void
gimp_item_stack_profile_changed(GimpItemStack * stack)341 gimp_item_stack_profile_changed (GimpItemStack *stack)
342 {
343   g_return_if_fail (GIMP_IS_ITEM_STACK (stack));
344 
345   gimp_container_foreach (GIMP_CONTAINER (stack),
346                           (GFunc) gimp_item_stack_viewable_profile_changed,
347                           NULL);
348 }
349