[gimp] app: add GimpLayerStack



commit 07ac78ef8dfe5e0936016a88d2baff514eadfd54
Author: Ell <ell_se yahoo com>
Date:   Mon May 8 16:02:37 2017 -0400

    app: add GimpLayerStack
    
    A subclass of GimpDrawableStack, for layer stacks.  Invalidates the
    layers' backdrop as/when necessary, according to the value of their
    excludes_backdrop property.
    
    Make gimp_drawable_stack_update() protected, instead of private, so
    that we can use it in GimpLayerStack.

 app/core/Makefile.am         |    2 +
 app/core/core-types.h        |    1 +
 app/core/gimpdrawablestack.c |   14 ++--
 app/core/gimpdrawablestack.h |   11 ++-
 app/core/gimpgrouplayer.c    |    4 +-
 app/core/gimpimage.c         |    3 +-
 app/core/gimplayerstack.c    |  233 ++++++++++++++++++++++++++++++++++++++++++
 app/core/gimplayerstack.h    |   51 +++++++++
 8 files changed, 308 insertions(+), 11 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index 8e0aec0..9e99352 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -308,6 +308,8 @@ libappcore_a_sources = \
        gimplayermaskundo.h                     \
        gimplayerpropundo.c                     \
        gimplayerpropundo.h                     \
+       gimplayerstack.c                        \
+       gimplayerstack.h                        \
        gimplayerundo.c                         \
        gimplayerundo.h                         \
        gimplist.c                              \
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 11eaa62..9ba95a4 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -98,6 +98,7 @@ typedef struct _GimpDrawableStack     GimpDrawableStack;
 typedef struct _GimpFilteredContainer GimpFilteredContainer;
 typedef struct _GimpFilterStack       GimpFilterStack;
 typedef struct _GimpItemStack         GimpItemStack;
+typedef struct _GimpLayerStack        GimpLayerStack;
 typedef struct _GimpTaggedContainer   GimpTaggedContainer;
 
 
diff --git a/app/core/gimpdrawablestack.c b/app/core/gimpdrawablestack.c
index 521f99c..a98b315 100644
--- a/app/core/gimpdrawablestack.c
+++ b/app/core/gimpdrawablestack.c
@@ -49,11 +49,6 @@ static void   gimp_drawable_stack_reorder          (GimpContainer     *container
                                                     GimpObject        *object,
                                                     gint               new_index);
 
-static void   gimp_drawable_stack_update           (GimpDrawableStack *stack,
-                                                    gint               x,
-                                                    gint               y,
-                                                    gint               width,
-                                                    gint               height);
 static void   gimp_drawable_stack_drawable_update  (GimpItem          *item,
                                                     gint               x,
                                                     gint               y,
@@ -173,19 +168,24 @@ gimp_drawable_stack_new (GType drawable_type)
 }
 
 
-/*  private functions  */
+/*  protected functions  */
 
-static void
+void
 gimp_drawable_stack_update (GimpDrawableStack *stack,
                             gint               x,
                             gint               y,
                             gint               width,
                             gint               height)
 {
+  g_return_if_fail (GIMP_IS_DRAWABLE_STACK (stack));
+
   g_signal_emit (stack, stack_signals[UPDATE], 0,
                  x, y, width, height);
 }
 
+
+/*  private functions  */
+
 static void
 gimp_drawable_stack_drawable_update (GimpItem          *item,
                                      gint               x,
diff --git a/app/core/gimpdrawablestack.h b/app/core/gimpdrawablestack.h
index 5197d13..eec4609 100644
--- a/app/core/gimpdrawablestack.h
+++ b/app/core/gimpdrawablestack.h
@@ -51,7 +51,16 @@ struct _GimpDrawableStackClass
 
 
 GType           gimp_drawable_stack_get_type  (void) G_GNUC_CONST;
-GimpContainer * gimp_drawable_stack_new       (GType drawable_type);
+GimpContainer * gimp_drawable_stack_new       (GType              drawable_type);
+
+
+/*  protected  */
+
+void            gimp_drawable_stack_update    (GimpDrawableStack *stack,
+                                               gint               x,
+                                               gint               y,
+                                               gint               width,
+                                               gint               height);
 
 
 #endif  /*  __GIMP_DRAWABLE_STACK_H__  */
diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c
index 3ac678b..2be8de7 100644
--- a/app/core/gimpgrouplayer.c
+++ b/app/core/gimpgrouplayer.c
@@ -35,7 +35,7 @@
 #include "gimpgrouplayer.h"
 #include "gimpimage.h"
 #include "gimpimage-undo-push.h"
-#include "gimpdrawablestack.h"
+#include "gimplayerstack.h"
 #include "gimppickable.h"
 #include "gimpprojectable.h"
 #include "gimpprojection.h"
@@ -261,7 +261,7 @@ gimp_group_layer_init (GimpGroupLayer *group)
 {
   GimpGroupLayerPrivate *private = GET_PRIVATE (group);
 
-  private->children = gimp_drawable_stack_new (GIMP_TYPE_LAYER);
+  private->children = gimp_layer_stack_new (GIMP_TYPE_LAYER);
   private->expanded = TRUE;
 
   g_signal_connect (private->children, "add",
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 8531253..58749c9 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -64,6 +64,7 @@
 #include "gimplayer.h"
 #include "gimplayer-floating-selection.h"
 #include "gimplayermask.h"
+#include "gimplayerstack.h"
 #include "gimpmarshal.h"
 #include "gimpparasitelist.h"
 #include "gimppickable.h"
@@ -728,7 +729,7 @@ gimp_image_init (GimpImage *image)
   private->sample_points       = NULL;
 
   private->layers              = gimp_item_tree_new (image,
-                                                     GIMP_TYPE_DRAWABLE_STACK,
+                                                     GIMP_TYPE_LAYER_STACK,
                                                      GIMP_TYPE_LAYER);
   private->channels            = gimp_item_tree_new (image,
                                                      GIMP_TYPE_DRAWABLE_STACK,
diff --git a/app/core/gimplayerstack.c b/app/core/gimplayerstack.c
new file mode 100644
index 0000000..7011bc7
--- /dev/null
+++ b/app/core/gimplayerstack.c
@@ -0,0 +1,233 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimplayerstack.c
+ * Copyright (C) 2017 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gegl.h>
+
+#include "core-types.h"
+
+#include "gimplayer.h"
+#include "gimplayerstack.h"
+
+
+/*  local function prototypes  */
+
+static void   gimp_layer_stack_constructed             (GObject       *object);
+
+static void   gimp_layer_stack_add                     (GimpContainer *container,
+                                                        GimpObject    *object);
+static void   gimp_layer_stack_remove                  (GimpContainer *container,
+                                                        GimpObject    *object);
+static void   gimp_layer_stack_reorder                 (GimpContainer *container,
+                                                        GimpObject    *object,
+                                                        gint           new_index);
+
+static void   gimp_layer_stack_layer_visible           (GimpLayer      *layer,
+                                                        GimpLayerStack *stack);
+static void   gimp_layer_stack_layer_excludes_backdrop (GimpLayer      *layer,
+                                                        GimpLayerStack *stack);
+
+static void   gimp_layer_stack_update_backdrop         (GimpLayerStack *stack,
+                                                        GimpLayer      *layer,
+                                                        gboolean        ignore_visible,
+                                                        gboolean        ignore_excludes_backdrop);
+static void   gimp_layer_stack_update_range            (GimpLayerStack *stack,
+                                                        gint            first,
+                                                        gint            last);
+
+
+G_DEFINE_TYPE (GimpLayerStack, gimp_layer_stack, GIMP_TYPE_DRAWABLE_STACK)
+
+#define parent_class gimp_layer_stack_parent_class
+
+
+static void
+gimp_layer_stack_class_init (GimpLayerStackClass *klass)
+{
+  GObjectClass       *object_class    = G_OBJECT_CLASS (klass);
+  GimpContainerClass *container_class = GIMP_CONTAINER_CLASS (klass);
+
+  object_class->constructed = gimp_layer_stack_constructed;
+
+  container_class->add      = gimp_layer_stack_add;
+  container_class->remove   = gimp_layer_stack_remove;
+  container_class->reorder  = gimp_layer_stack_reorder;
+}
+
+static void
+gimp_layer_stack_init (GimpLayerStack *stack)
+{
+}
+
+static void
+gimp_layer_stack_constructed (GObject *object)
+{
+  GimpContainer *container = GIMP_CONTAINER (object);
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  g_assert (g_type_is_a (gimp_container_get_children_type (container),
+                         GIMP_TYPE_LAYER));
+
+  gimp_container_add_handler (container, "visibility-changed",
+                              G_CALLBACK (gimp_layer_stack_layer_visible),
+                              container);
+  gimp_container_add_handler (container, "excludes-backdrop-changed",
+                              G_CALLBACK (gimp_layer_stack_layer_excludes_backdrop),
+                              container);
+}
+
+static void
+gimp_layer_stack_add (GimpContainer *container,
+                      GimpObject    *object)
+{
+  GimpLayerStack *stack = GIMP_LAYER_STACK (container);
+
+  GIMP_CONTAINER_CLASS (parent_class)->add (container, object);
+
+  gimp_layer_stack_update_backdrop (stack, GIMP_LAYER (object), FALSE, FALSE);
+}
+
+static void
+gimp_layer_stack_remove (GimpContainer *container,
+                         GimpObject    *object)
+{
+  GimpLayerStack *stack = GIMP_LAYER_STACK (container);
+
+  gimp_layer_stack_update_backdrop (stack, GIMP_LAYER (object), FALSE, FALSE);
+
+  GIMP_CONTAINER_CLASS (parent_class)->remove (container, object);
+}
+
+static void
+gimp_layer_stack_reorder (GimpContainer *container,
+                          GimpObject    *object,
+                          gint           new_index)
+{
+  GimpLayerStack *stack = GIMP_LAYER_STACK (container);
+  gboolean        excludes_backdrop;
+  gint            index;
+
+  excludes_backdrop = gimp_item_get_visible (GIMP_ITEM (object)) &&
+                      gimp_layer_get_excludes_backdrop (GIMP_LAYER (object));
+
+  if (excludes_backdrop)
+    index = gimp_container_get_child_index (container, object);
+
+  GIMP_CONTAINER_CLASS (parent_class)->reorder (container, object, new_index);
+
+  if (excludes_backdrop)
+    gimp_layer_stack_update_range (stack, index, new_index);
+}
+
+
+/*  public functions  */
+
+GimpContainer *
+gimp_layer_stack_new (GType layer_type)
+{
+  g_return_val_if_fail (g_type_is_a (layer_type, GIMP_TYPE_LAYER), NULL);
+
+  return g_object_new (GIMP_TYPE_LAYER_STACK,
+                       "name",          g_type_name (layer_type),
+                       "children-type", layer_type,
+                       "policy",        GIMP_CONTAINER_POLICY_STRONG,
+                       NULL);
+}
+
+
+/*  private functions  */
+
+static void
+gimp_layer_stack_layer_visible (GimpLayer      *layer,
+                                GimpLayerStack *stack)
+{
+  gimp_layer_stack_update_backdrop (stack, layer, TRUE, FALSE);
+}
+
+static void
+gimp_layer_stack_layer_excludes_backdrop (GimpLayer      *layer,
+                                          GimpLayerStack *stack)
+{
+  gimp_layer_stack_update_backdrop (stack, layer, FALSE, TRUE);
+}
+
+static void
+gimp_layer_stack_update_backdrop (GimpLayerStack *stack,
+                                  GimpLayer      *layer,
+                                  gboolean        ignore_visible,
+                                  gboolean        ignore_excludes_backdrop)
+{
+  if ((ignore_visible           || gimp_item_get_visible (GIMP_ITEM (layer))) &&
+      (ignore_excludes_backdrop || gimp_layer_get_excludes_backdrop (layer)))
+    {
+      gint index;
+
+      index = gimp_container_get_child_index (GIMP_CONTAINER (stack),
+                                              GIMP_OBJECT (layer));
+
+      gimp_layer_stack_update_range (stack, index, -1);
+    }
+}
+
+static void
+gimp_layer_stack_update_range (GimpLayerStack *stack,
+                               gint            first,
+                               gint            last)
+{
+  GList *iter;
+
+  g_assert (first >= 0 && last >= -1);
+
+  /* if the range is reversed, flip first and last; note that last == -1 is
+   * used to update all layers from first onward.
+   */
+  if (last >= 0 && last < first)
+    {
+      gint temp = first;
+
+      first = last + 1;
+      last  = temp + 1;
+    }
+
+  iter = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (stack));
+
+  for (iter = g_list_nth (iter, first);
+       iter && first != last;
+       iter = g_list_next (iter), first++)
+    {
+      GimpItem *item = iter->data;
+
+      if (gimp_item_get_visible (item))
+        {
+          gint offset_x;
+          gint offset_y;
+
+          gimp_item_get_offset (item, &offset_x, &offset_y);
+
+          gimp_drawable_stack_update (GIMP_DRAWABLE_STACK (stack),
+                                      offset_x, offset_y,
+                                      gimp_item_get_width  (item),
+                                      gimp_item_get_height (item));
+        }
+    }
+}
diff --git a/app/core/gimplayerstack.h b/app/core/gimplayerstack.h
new file mode 100644
index 0000000..00e8fcb
--- /dev/null
+++ b/app/core/gimplayerstack.h
@@ -0,0 +1,51 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * gimplayerstack.h
+ * Copyright (C) 2017 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_LAYER_STACK_H__
+#define __GIMP_LAYER_STACK_H__
+
+#include "gimpdrawablestack.h"
+
+
+#define GIMP_TYPE_LAYER_STACK            (gimp_layer_stack_get_type ())
+#define GIMP_LAYER_STACK(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_LAYER_STACK, 
GimpLayerStack))
+#define GIMP_LAYER_STACK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_LAYER_STACK, 
GimpLayerStackClass))
+#define GIMP_IS_LAYER_STACK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_LAYER_STACK))
+#define GIMP_IS_LAYER_STACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_LAYER_STACK))
+
+
+typedef struct _GimpLayerStackClass GimpLayerStackClass;
+
+struct _GimpLayerStack
+{
+  GimpDrawableStack  parent_instance;
+};
+
+struct _GimpLayerStackClass
+{
+  GimpDrawableStackClass  parent_class;
+};
+
+
+GType           gimp_layer_stack_get_type  (void) G_GNUC_CONST;
+GimpContainer * gimp_layer_stack_new       (GType layer_type);
+
+
+#endif  /*  __GIMP_LAYER_STACK_H__  */


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