[gimp] app: add a concept of hidden items to a GimpImage.



commit e6722aa8b763618ba946b9b4c10e2e6d29437e90
Author: Jehan <jehan girinstud io>
Date:   Tue Mar 1 16:09:47 2022 +0100

    app: add a concept of hidden items to a GimpImage.
    
    Many features can only be run on items belonging to an image, and in
    particular attached. It makes sense, but in the same time, there are
    often some types of processing you'd like to do in background on
    temporary items, not visible in GUI, and without any undo steps.
    
    You could work on buffers directly, but sometimes it's also nice to
    attach the semantics of the various items, and reuse logics (in
    particular class method implementations) already existing. So I am
    adding a concept of "hidden items" which is where you'd put items in
    some temporary processing state when you don't want them to go anywhere
    visible publicly.

 app/core/gimpimage-private.h |  2 ++
 app/core/gimpimage.c         | 73 ++++++++++++++++++++++++++++++++++++++++++++
 app/core/gimpimage.h         |  7 +++++
 app/core/gimpitem.c          |  7 ++++-
 4 files changed, 88 insertions(+), 1 deletion(-)
---
diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h
index 6f8e617d78..0f7db76754 100644
--- a/app/core/gimpimage-private.h
+++ b/app/core/gimpimage-private.h
@@ -111,6 +111,8 @@ struct _GimpImagePrivate
   GimpItemTree      *vectors;               /*  the tree of vectors          */
   GSList            *layer_stack;           /*  the layers in MRU order      */
 
+  GList             *hidden_items;          /*  internal process-only items  */
+
   GList             *stored_layer_sets;
   GList             *stored_channel_sets;
   GList             *stored_vectors_sets;
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index a9126ab31f..38a0e9d9a5 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -1189,6 +1189,17 @@ gimp_image_finalize (GObject *object)
   g_clear_pointer (&private->display_path, g_free);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
+
+  /* Don't just free the list silently. It is supposed to be empty.
+   * Instead just assert this fact to warn on improper management of
+   * hidden items.
+   */
+  if (private->hidden_items != NULL)
+    {
+      g_warning ("%s: the hidden items list should be empty (%d items remaining).",
+                 G_STRFUNC, g_list_length (private->hidden_items));
+      g_list_free (private->hidden_items);
+    }
 }
 
 static void
@@ -6022,6 +6033,68 @@ gimp_image_remove_vectors (GimpImage   *image,
     gimp_image_undo_group_end (image);
 }
 
+/*  hidden items  */
+
+/* Sometimes you want to create a channel or other types of drawables to
+ * work on them without adding them to the public trees and to be
+ * visible in the GUI. This is when you create hidden items. No undo
+ * steps will ever be created either for any processing on these items.
+ *
+ * Note that you are expected to manage the hidden items properly. In
+ * particular, once you are done with them, remove them with
+ * gimp_image_remove_hidden_item() and free them.
+ * @image is not assuming ownership of @item.
+ */
+gboolean
+gimp_image_add_hidden_item (GimpImage *image,
+                            GimpItem  *item)
+{
+  GimpImagePrivate *private;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
+  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
+  g_return_val_if_fail (! gimp_item_is_attached (item), FALSE);
+  g_return_val_if_fail (gimp_item_get_image (item) == image, FALSE);
+
+  private = GIMP_IMAGE_GET_PRIVATE (image);
+
+  private->hidden_items = g_list_prepend (private->hidden_items, item);
+
+  return TRUE;
+}
+
+void
+gimp_image_remove_hidden_item (GimpImage *image,
+                               GimpItem  *item)
+{
+  GimpImagePrivate *private;
+
+  g_return_if_fail (GIMP_IS_IMAGE (image));
+  g_return_if_fail (GIMP_IS_ITEM (item));
+  g_return_if_fail (gimp_item_get_image (item) == image);
+
+  private = GIMP_IMAGE_GET_PRIVATE (image);
+
+  g_return_if_fail (g_list_find (private->hidden_items, item) != NULL);
+
+  private->hidden_items = g_list_remove (private->hidden_items, item);
+}
+
+gboolean
+gimp_image_is_hidden_item (GimpImage *image,
+                           GimpItem  *item)
+{
+  GimpImagePrivate *private;
+
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
+  g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
+  g_return_val_if_fail (gimp_item_get_image (item) == image, FALSE);
+
+  private = GIMP_IMAGE_GET_PRIVATE (image);
+
+  return (g_list_find (private->hidden_items, item) != NULL);
+}
+
 gboolean
 gimp_image_coords_in_active_pickable (GimpImage        *image,
                                       const GimpCoords *coords,
diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h
index 0c2e161191..1e132942d9 100644
--- a/app/core/gimpimage.h
+++ b/app/core/gimpimage.h
@@ -488,6 +488,13 @@ void            gimp_image_remove_vectors        (GimpImage          *image,
                                                   gboolean            push_undo,
                                                   GList              *new_selected);
 
+gboolean        gimp_image_add_hidden_item       (GimpImage          *image,
+                                                  GimpItem           *item);
+void            gimp_image_remove_hidden_item    (GimpImage          *image,
+                                                  GimpItem           *item);
+gboolean        gimp_image_is_hidden_item        (GimpImage          *image,
+                                                  GimpItem           *item);
+
 gboolean    gimp_image_coords_in_active_pickable (GimpImage          *image,
                                                   const GimpCoords   *coords,
                                                   gboolean            show_all,
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index d2f4f016be..5efeac3d16 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -855,10 +855,15 @@ gimp_item_unset_removed (GimpItem *item)
 gboolean
 gimp_item_is_attached (GimpItem *item)
 {
-  GimpItem *parent;
+  GimpImage *image;
+  GimpItem  *parent;
 
   g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
 
+  image = gimp_item_get_image (item);
+  if (image != NULL && gimp_image_is_hidden_item (image, item))
+    return TRUE;
+
   parent = gimp_item_get_parent (item);
 
   if (parent)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]