[gtk/layout-child-type] Connect LayoutManager to LayoutChild



commit 3f0f7c73e091c2179b2175eb56aef62f16dd9b10
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu Mar 28 16:58:00 2019 +0000

    Connect LayoutManager to LayoutChild
    
    If we want to inspect the type of layout properties exposed by a
    GtkLayoutManager, we need a way to connect the layout manager type to
    the GtkLayoutChild type it creates. In order to do so, we can set the
    GtkLayoutChild type on a field of the GtkLayoutManagerClass structure.
    
    Storing the GtkLayoutChild type on the class structure of the layout
    manager also allows us to implement a default create_layout_child()
    virtual function.

 gtk/gtkfixedlayout.c   |  2 ++
 gtk/gtklayoutmanager.c | 42 ++++++++++++++++++++++++++++--------------
 gtk/gtklayoutmanager.h |  3 +++
 3 files changed, 33 insertions(+), 14 deletions(-)
---
diff --git a/gtk/gtkfixedlayout.c b/gtk/gtkfixedlayout.c
index 0895753edf..94e4c687b2 100644
--- a/gtk/gtkfixedlayout.c
+++ b/gtk/gtkfixedlayout.c
@@ -314,6 +314,8 @@ gtk_fixed_layout_class_init (GtkFixedLayoutClass *klass)
 {
   GtkLayoutManagerClass *layout_class = GTK_LAYOUT_MANAGER_CLASS (klass);
 
+  layout_class->layout_child_type = GTK_TYPE_FIXED_LAYOUT_CHILD;
+
   layout_class->measure = gtk_fixed_layout_measure;
   layout_class->allocate = gtk_fixed_layout_allocate;
   layout_class->create_layout_child = gtk_fixed_layout_create_layout_child;
diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c
index 90432eed87..cd7d1406b1 100644
--- a/gtk/gtklayoutmanager.c
+++ b/gtk/gtklayoutmanager.c
@@ -97,8 +97,6 @@ typedef struct {
 
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkLayoutManager, gtk_layout_manager, G_TYPE_OBJECT)
 
-static GQuark quark_layout_child;
-
 static GtkSizeRequestMode
 gtk_layout_manager_real_get_request_mode (GtkLayoutManager *manager,
                                           GtkWidget        *widget)
@@ -141,14 +139,32 @@ gtk_layout_manager_real_allocate (GtkLayoutManager *manager,
   LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, allocate);
 }
 
+static GtkLayoutChild *
+gtk_layout_manager_real_create_layout_child (GtkLayoutManager *manager,
+                                             GtkWidget        *widget,
+                                             GtkWidget        *child)
+{
+  GtkLayoutManagerClass *manager_class = GTK_LAYOUT_MANAGER_GET_CLASS (manager);
+
+  if (manager_class->layout_child_type == G_TYPE_INVALID)
+    {
+      LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, create_layout_child);
+      return NULL;
+    }
+
+  return g_object_new (manager_class->layout_child_type,
+                       "layout-manager", manager,
+                       "child-widget", widget,
+                       NULL);
+}
+
 static void
 gtk_layout_manager_class_init (GtkLayoutManagerClass *klass)
 {
   klass->get_request_mode = gtk_layout_manager_real_get_request_mode;
   klass->measure = gtk_layout_manager_real_measure;
   klass->allocate = gtk_layout_manager_real_allocate;
-
-  quark_layout_child = g_quark_from_static_string ("-GtkLayoutManager-layout-child");
+  klass->create_layout_child = gtk_layout_manager_real_create_layout_child;
 }
 
 static void
@@ -382,14 +398,6 @@ gtk_layout_manager_get_layout_child (GtkLayoutManager *manager,
       return NULL;
     }
 
-  if (GTK_LAYOUT_MANAGER_GET_CLASS (manager)->create_layout_child == NULL)
-    {
-      g_critical ("The layout manager of type %s %p does not create "
-                  "GtkLayoutChild instances",
-                  G_OBJECT_TYPE_NAME (manager), manager);
-      return NULL;
-    }
-
   if (priv->layout_children == NULL)
     {
       priv->layout_children = g_hash_table_new_full (NULL, NULL,
@@ -410,9 +418,15 @@ gtk_layout_manager_get_layout_child (GtkLayoutManager *manager,
     }
 
   res = GTK_LAYOUT_MANAGER_GET_CLASS (manager)->create_layout_child (manager, parent, child);
-  g_assert (res != NULL);
-  g_assert (g_type_is_a (G_OBJECT_TYPE (res), GTK_TYPE_LAYOUT_CHILD));
+  if (res == NULL)
+    {
+      g_critical ("The layout manager of type %s %p does not create "
+                  "GtkLayoutChild instances",
+                  G_OBJECT_TYPE_NAME (manager), manager);
+      return NULL;
+    }
 
+  g_assert (g_type_is_a (G_OBJECT_TYPE (res), GTK_TYPE_LAYOUT_CHILD));
   g_hash_table_insert (priv->layout_children, child, res);
 
   return res;
diff --git a/gtk/gtklayoutmanager.h b/gtk/gtklayoutmanager.h
index 53f4931c69..06659ee70e 100644
--- a/gtk/gtklayoutmanager.h
+++ b/gtk/gtklayoutmanager.h
@@ -39,6 +39,7 @@ G_DECLARE_DERIVABLE_TYPE (GtkLayoutManager, gtk_layout_manager, GTK, LAYOUT_MANA
  *   sizes of the widget using the layout manager for a given orientation
  * @allocate: a virtual function, used to allocate the size of the widget
  *   using the layout manager
+ * @layout_child_type: the type of #GtkLayoutChild used by this layout manager
  * @create_layout_child: a virtual function, used to create a #GtkLayoutChild
  *   meta object for the layout properties
  *
@@ -70,6 +71,8 @@ struct _GtkLayoutManagerClass
                                               int               height,
                                               int               baseline);
 
+  GType              layout_child_type;
+
   GtkLayoutChild *   (* create_layout_child) (GtkLayoutManager *manager,
                                               GtkWidget        *widget,
                                               GtkWidget        *for_child);


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