[gimp] app: respond to viewable expanded state changes in container views



commit d027a059ef1c4b46370177b0a72a19a5b98561d9
Author: Ell <ell_se yahoo com>
Date:   Sun Oct 22 11:50:37 2017 -0400

    app: respond to viewable expanded state changes in container views
    
    Add an "expanded-changed" signal to GimpViewable, which should be
    emitted by subclasses when the viewable's expanded state changes.
    Emit this signal when the expanded state of group layers changes.
    Respond to this signal in GimpContainerView, by calling a new
    expand_item() virtual function.  Implement expand_item() in
    GimpContainerTreeView, expanding or collapsing the item as
    necessary.

 app/core/gimpgrouplayer.c           |    9 ++++++-
 app/core/gimpviewable.c             |   27 ++++++++++++++++++++++++
 app/core/gimpviewable.h             |    2 +
 app/widgets/gimpcontainertreeview.c |   39 +++++++++++++++++++++++++++++++++++
 app/widgets/gimpcontainerview.c     |   36 ++++++++++++++++++++++++++++++-
 app/widgets/gimpcontainerview.h     |    3 ++
 6 files changed, 112 insertions(+), 4 deletions(-)
---
diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c
index 5aac2bd..c4a80bd 100644
--- a/app/core/gimpgrouplayer.c
+++ b/app/core/gimpgrouplayer.c
@@ -438,9 +438,14 @@ static void
 gimp_group_layer_set_expanded (GimpViewable *viewable,
                                gboolean      expanded)
 {
-  GimpGroupLayer *group = GIMP_GROUP_LAYER (viewable);
+  GimpGroupLayerPrivate *private = GET_PRIVATE (viewable);
 
-  GET_PRIVATE (group)->expanded = expanded;
+  if (private->expanded != expanded)
+    {
+      private->expanded = expanded;
+
+      gimp_viewable_expanded_changed (viewable);
+    }
 }
 
 static gboolean
diff --git a/app/core/gimpviewable.c b/app/core/gimpviewable.c
index d3be5d5..bd521a1 100644
--- a/app/core/gimpviewable.c
+++ b/app/core/gimpviewable.c
@@ -54,6 +54,7 @@ enum
 {
   INVALIDATE_PREVIEW,
   SIZE_CHANGED,
+  EXPANDED_CHANGED,
   LAST_SIGNAL
 };
 
@@ -160,6 +161,15 @@ gimp_viewable_class_init (GimpViewableClass *klass)
                   gimp_marshal_VOID__VOID,
                   G_TYPE_NONE, 0);
 
+  viewable_signals[EXPANDED_CHANGED] =
+    g_signal_new ("expanded-changed",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GimpViewableClass, expanded_changed),
+                  NULL, NULL,
+                  gimp_marshal_VOID__VOID,
+                  G_TYPE_NONE, 0);
+
   object_class->finalize         = gimp_viewable_finalize;
   object_class->get_property     = gimp_viewable_get_property;
   object_class->set_property     = gimp_viewable_set_property;
@@ -172,6 +182,7 @@ gimp_viewable_class_init (GimpViewableClass *klass)
 
   klass->invalidate_preview      = gimp_viewable_real_invalidate_preview;
   klass->size_changed            = NULL;
+  klass->expanded_changed        = NULL;
 
   klass->get_size                = NULL;
   klass->get_preview_size        = gimp_viewable_real_get_preview_size;
@@ -557,6 +568,22 @@ gimp_viewable_size_changed (GimpViewable *viewable)
 }
 
 /**
+ * gimp_viewable_expanded_changed:
+ * @viewable: a viewable object
+ *
+ * This function sends a signal that is handled at a lower level in the
+ * object hierarchy, and provides a mechanism by which objects derived
+ * from #GimpViewable can respond to expanded state changes.
+ **/
+void
+gimp_viewable_expanded_changed (GimpViewable *viewable)
+{
+  g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
+
+  g_signal_emit (viewable, viewable_signals[EXPANDED_CHANGED], 0);
+}
+
+/**
  * gimp_viewable_calc_preview_size:
  * @aspect_width:   unscaled width of the preview for an item.
  * @aspect_height:  unscaled height of the preview for an item.
diff --git a/app/core/gimpviewable.h b/app/core/gimpviewable.h
index 2d42ec8..a3b310c 100644
--- a/app/core/gimpviewable.h
+++ b/app/core/gimpviewable.h
@@ -57,6 +57,7 @@ struct _GimpViewableClass
   /*  signals  */
   void            (* invalidate_preview) (GimpViewable  *viewable);
   void            (* size_changed)       (GimpViewable  *viewable);
+  void            (* expanded_changed)   (GimpViewable  *viewable);
 
   /*  virtual functions  */
   gboolean        (* get_size)           (GimpViewable  *viewable,
@@ -107,6 +108,7 @@ GType           gimp_viewable_get_type           (void) G_GNUC_CONST;
 
 void            gimp_viewable_invalidate_preview (GimpViewable  *viewable);
 void            gimp_viewable_size_changed       (GimpViewable  *viewable);
+void            gimp_viewable_expanded_changed   (GimpViewable  *viewable);
 
 void            gimp_viewable_calc_preview_size  (gint           aspect_width,
                                                   gint           aspect_height,
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index 12c3667..f91162c 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -86,6 +86,9 @@ static void          gimp_container_tree_view_reorder_item      (GimpContainerVi
 static void          gimp_container_tree_view_rename_item       (GimpContainerView           *view,
                                                                  GimpViewable                *viewable,
                                                                  gpointer                     insert_data);
+static void          gimp_container_tree_view_expand_item       (GimpContainerView           *view,
+                                                                 GimpViewable                *viewable,
+                                                                 gpointer                     insert_data);
 static gboolean      gimp_container_tree_view_select_item       (GimpContainerView           *view,
                                                                  GimpViewable                *viewable,
                                                                  gpointer                     insert_data);
@@ -203,6 +206,7 @@ gimp_container_tree_view_view_iface_init (GimpContainerViewInterface *iface)
   iface->remove_item        = gimp_container_tree_view_remove_item;
   iface->reorder_item       = gimp_container_tree_view_reorder_item;
   iface->rename_item        = gimp_container_tree_view_rename_item;
+  iface->expand_item        = gimp_container_tree_view_expand_item;
   iface->select_item        = gimp_container_tree_view_select_item;
   iface->clear_items        = gimp_container_tree_view_clear_items;
   iface->set_view_size      = gimp_container_tree_view_set_view_size;
@@ -767,6 +771,41 @@ gimp_container_tree_view_rename_item (GimpContainerView *view,
     }
 }
 
+static void
+gimp_container_tree_view_expand_item (GimpContainerView *view,
+                                      GimpViewable      *viewable,
+                                      gpointer           insert_data)
+{
+  GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
+  GtkTreeIter           *iter      = (GtkTreeIter *) insert_data;
+  GimpViewRenderer      *renderer;
+
+  gtk_tree_model_get (tree_view->model, iter,
+                      GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
+                      -1);
+
+  if (renderer)
+    {
+      GtkTreePath *path = gtk_tree_model_get_path (tree_view->model, iter);
+
+      g_signal_handlers_block_by_func (tree_view,
+                                       gimp_container_tree_view_row_expanded,
+                                       view);
+
+      if (gimp_viewable_get_expanded (renderer->viewable))
+        gtk_tree_view_expand_row (tree_view->view, path, FALSE);
+      else
+        gtk_tree_view_collapse_row (tree_view->view, path);
+
+      g_signal_handlers_unblock_by_func (tree_view,
+                                         gimp_container_tree_view_row_expanded,
+                                         view);
+
+      gtk_tree_path_free (path);
+      g_object_unref (renderer);
+    }
+}
+
 static gboolean
 gimp_container_tree_view_select_item (GimpContainerView *view,
                                       GimpViewable      *viewable,
diff --git a/app/widgets/gimpcontainerview.c b/app/widgets/gimpcontainerview.c
index 9ca053d..d4f0585 100644
--- a/app/widgets/gimpcontainerview.c
+++ b/app/widgets/gimpcontainerview.c
@@ -72,6 +72,7 @@ struct _GimpContainerViewPrivate
   GtkWidget       *dnd_widget;
 
   GimpTreeHandler *name_changed_handler;
+  GimpTreeHandler *expanded_changed_handler;
 };
 
 
@@ -117,6 +118,8 @@ static void   gimp_container_view_thaw             (GimpContainerView  *view,
                                                     GimpContainer      *container);
 static void   gimp_container_view_name_changed     (GimpViewable       *viewable,
                                                     GimpContainerView  *view);
+static void   gimp_container_view_expanded_changed (GimpViewable       *viewable,
+                                                    GimpContainerView  *view);
 
 static void   gimp_container_view_connect_context    (GimpContainerView *view);
 static void   gimp_container_view_disconnect_context (GimpContainerView *view);
@@ -217,6 +220,7 @@ gimp_container_view_iface_base_init (GimpContainerViewInterface *view_iface)
   view_iface->remove_item        = NULL;
   view_iface->reorder_item       = NULL;
   view_iface->rename_item        = NULL;
+  view_iface->expand_item        = NULL;
   view_iface->clear_items        = gimp_container_view_real_clear_items;
   view_iface->set_view_size      = NULL;
   view_iface->get_selected       = gimp_container_view_real_get_selected;
@@ -980,6 +984,15 @@ gimp_container_view_add_container (GimpContainerView *view,
                                    G_CALLBACK (gimp_container_view_name_changed),
                                    view);
 
+      if (GIMP_CONTAINER_VIEW_GET_INTERFACE (view)->expand_item)
+        {
+          private->expanded_changed_handler =
+            gimp_tree_handler_connect (container,
+                                       "expanded-changed",
+                                       G_CALLBACK (gimp_container_view_expanded_changed),
+                                       view);
+        }
+
       g_type_class_unref (viewable_class);
     }
 
@@ -1088,8 +1101,10 @@ gimp_container_view_remove_container (GimpContainerView *view,
 
   if (container == private->container)
     {
-      gimp_tree_handler_disconnect (private->name_changed_handler);
-      private->name_changed_handler = NULL;
+      g_clear_pointer (&private->name_changed_handler,
+                       gimp_tree_handler_disconnect);
+      g_clear_pointer (&private->expanded_changed_handler,
+                       gimp_tree_handler_disconnect);
 
       /* optimization: when the toplevel container gets removed, call
        * clear_items() which will get rid of all view widget stuff
@@ -1213,6 +1228,23 @@ gimp_container_view_name_changed (GimpViewable      *viewable,
 }
 
 static void
+gimp_container_view_expanded_changed (GimpViewable      *viewable,
+                                      GimpContainerView *view)
+{
+  GimpContainerViewPrivate *private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
+  gpointer                  insert_data;
+
+  insert_data = g_hash_table_lookup (private->item_hash, viewable);
+
+  if (insert_data)
+    {
+      GIMP_CONTAINER_VIEW_GET_INTERFACE (view)->expand_item (view,
+                                                             viewable,
+                                                             insert_data);
+    }
+}
+
+static void
 gimp_container_view_connect_context (GimpContainerView *view)
 {
   GimpContainerViewPrivate *private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
diff --git a/app/widgets/gimpcontainerview.h b/app/widgets/gimpcontainerview.h
index 7573417..657e05f 100644
--- a/app/widgets/gimpcontainerview.h
+++ b/app/widgets/gimpcontainerview.h
@@ -83,6 +83,9 @@ struct _GimpContainerViewInterface
   void     (* rename_item)        (GimpContainerView *view,
                                    GimpViewable      *object,
                                    gpointer           insert_data);
+  void     (* expand_item)        (GimpContainerView *view,
+                                   GimpViewable      *object,
+                                   gpointer           insert_data);
   void     (* clear_items)        (GimpContainerView *view);
   void     (* set_view_size)      (GimpContainerView *view);
   gint     (* get_selected)       (GimpContainerView  *view,


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