[gtk/bin-removal: 5/28] flowboxchild: Derive from GtkWidget



commit ecdc52536cc2f9cc8fffdc012d91d588a3a0e983
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 2 20:53:40 2020 -0400

    flowboxchild: Derive from GtkWidget
    
    We want to remove GtkBin and GtkContainer as they don't
    provide much useful functionality anymore.
    
    See #2681

 demos/gtk-demo/sliding_puzzle.c      |   5 +-
 docs/reference/gtk/gtk4-sections.txt |   2 +
 gtk/a11y/gtkflowboxchildaccessible.c |   2 +-
 gtk/gtkemojichooser.c                |   4 +-
 gtk/gtkflowbox.c                     | 174 +++++++++++++++++++++++++++++++++--
 gtk/gtkflowbox.h                     |  13 ++-
 tests/testflowbox.c                  |   8 +-
 7 files changed, 187 insertions(+), 21 deletions(-)
---
diff --git a/demos/gtk-demo/sliding_puzzle.c b/demos/gtk-demo/sliding_puzzle.c
index 03ac047e6a..b564e200b5 100644
--- a/demos/gtk-demo/sliding_puzzle.c
+++ b/demos/gtk-demo/sliding_puzzle.c
@@ -367,10 +367,11 @@ reconfigure (void)
       child = selected->data;
       g_list_free (selected);
     }
-  image = gtk_bin_get_child (GTK_BIN (child));
+
+  image = gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child));
   puzzle = gtk_image_get_paintable (GTK_IMAGE (image));
 
-  start_puzzle (puzzle); 
+  start_puzzle (puzzle);
   popover = gtk_widget_get_ancestor (size_spin, GTK_TYPE_POPOVER);
   gtk_popover_popdown (GTK_POPOVER (popover));
   grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 32b14b1ed6..2e94aef317 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -5758,6 +5758,8 @@ gtk_flow_box_bind_model
 <SUBSECTION GtkFlowBoxChild>
 GtkFlowBoxChild
 gtk_flow_box_child_new
+gtk_flow_box_child_set_child
+gtk_flow_box_child_get_child
 gtk_flow_box_child_get_index
 gtk_flow_box_child_is_selected
 gtk_flow_box_child_changed
diff --git a/gtk/a11y/gtkflowboxchildaccessible.c b/gtk/a11y/gtkflowboxchildaccessible.c
index 2476f97ab0..794c4f5ee3 100644
--- a/gtk/a11y/gtkflowboxchildaccessible.c
+++ b/gtk/a11y/gtkflowboxchildaccessible.c
@@ -22,7 +22,7 @@
 #include "gtk/gtkflowbox.h"
 
 
-G_DEFINE_TYPE (GtkFlowBoxChildAccessible, gtk_flow_box_child_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE)
+G_DEFINE_TYPE (GtkFlowBoxChildAccessible, gtk_flow_box_child_accessible, GTK_TYPE_WIDGET_ACCESSIBLE)
 
 static void
 gtk_flow_box_child_accessible_init (GtkFlowBoxChildAccessible *accessible)
diff --git a/gtk/gtkemojichooser.c b/gtk/gtkemojichooser.c
index eee1ac7934..89479f5ca5 100644
--- a/gtk/gtkemojichooser.c
+++ b/gtk/gtkemojichooser.c
@@ -372,7 +372,7 @@ emoji_activated (GtkFlowBox      *box,
 
   gtk_popover_popdown (GTK_POPOVER (chooser));
 
-  label = gtk_bin_get_child (GTK_BIN (child));
+  label = gtk_flow_box_child_get_child (child);
   text = g_strdup (gtk_label_get_label (GTK_LABEL (label)));
 
   item = (GVariant*) g_object_get_data (G_OBJECT (child), "emoji-data");
@@ -542,7 +542,7 @@ add_emoji (GtkWidget    *box,
   if (modifier != 0)
     g_object_set_data (G_OBJECT (child), "modifier", GUINT_TO_POINTER (modifier));
 
-  gtk_container_add (GTK_CONTAINER (child), label);
+  gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (child), label);
   gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
 }
 
diff --git a/gtk/gtkflowbox.c b/gtk/gtkflowbox.c
index e0f0a61317..98d66f18ed 100644
--- a/gtk/gtkflowbox.c
+++ b/gtk/gtkflowbox.c
@@ -79,6 +79,8 @@
 #include "gtkflowboxprivate.h"
 
 #include "gtkadjustment.h"
+#include "gtkbinlayout.h"
+#include "gtkbuildable.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkcssnodeprivate.h"
 #include "gtkgesturedrag.h"
@@ -99,7 +101,7 @@
 
 #include "a11y/gtkflowboxaccessibleprivate.h"
 #include "a11y/gtkflowboxchildaccessible.h"
-
+ 
 /* Forward declarations and utilities {{{1 */
 
 static void gtk_flow_box_update_cursor       (GtkFlowBox      *box,
@@ -256,16 +258,26 @@ enum {
 
 static guint child_signals[CHILD_LAST_SIGNAL] = { 0 };
 
+enum {
+  PROP_CHILD = 1
+};
+
 typedef struct _GtkFlowBoxChildPrivate GtkFlowBoxChildPrivate;
 struct _GtkFlowBoxChildPrivate
 {
+  GtkWidget     *child;
   GSequenceIter *iter;
   gboolean       selected;
 };
 
 #define CHILD_PRIV(child) ((GtkFlowBoxChildPrivate*)gtk_flow_box_child_get_instance_private 
((GtkFlowBoxChild*)(child)))
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkFlowBoxChild, gtk_flow_box_child, GTK_TYPE_BIN)
+static void gtk_flow_box_child_buildable_iface_init (GtkBuildableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkFlowBoxChild, gtk_flow_box_child, GTK_TYPE_WIDGET,
+                         G_ADD_PRIVATE (GtkFlowBoxChild)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_flow_box_child_buildable_iface_init))
 
 /* Internal API {{{2 */
 
@@ -291,14 +303,36 @@ gtk_flow_box_child_set_focus (GtkFlowBoxChild *child)
 
 /* GtkWidget implementation {{{2 */
 
+static GtkBuildableIface *parent_child_buildable_iface;
+
+static void
+gtk_flow_box_child_buildable_add_child (GtkBuildable *buildable,
+                                        GtkBuilder   *builder,
+                                        GObject      *child,
+                                        const gchar  *type)
+{
+  if (GTK_IS_WIDGET (child))
+    gtk_flow_box_child_set_child (GTK_FLOW_BOX_CHILD (buildable), GTK_WIDGET (child));
+  else
+    parent_child_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_flow_box_child_buildable_iface_init (GtkBuildableIface *iface)
+{
+  parent_child_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->add_child = gtk_flow_box_child_buildable_add_child;
+}
+
 static gboolean
 gtk_flow_box_child_focus (GtkWidget        *widget,
                           GtkDirectionType  direction)
 {
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (widget);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+  GtkWidget *child = priv->child;
   gboolean had_focus = FALSE;
-  GtkWidget *child;
-
-  child = gtk_bin_get_child (GTK_BIN (widget));
 
   /* Without "can-focus" flag try to pass the focus to the child immediately */
   if (!gtk_widget_get_can_focus (widget))
@@ -384,6 +418,77 @@ gtk_flow_box_child_get_request_mode (GtkWidget *widget)
     return GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
 }
 
+static void
+gtk_flow_box_child_dispose (GObject *object)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (gtk_flow_box_child_parent_class)->dispose (object);
+}
+
+static void
+gtk_flow_box_child_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+
+  switch (prop_id)
+    {
+    case PROP_CHILD:
+      g_value_set_object (value, gtk_flow_box_child_get_child (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_flow_box_child_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (object);
+
+  switch (prop_id)
+    {
+    case PROP_CHILD:
+      gtk_flow_box_child_set_child (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_flow_box_child_compute_expand (GtkWidget *widget,
+                                   gboolean  *hexpand,
+                                   gboolean  *vexpand)
+{
+  GtkFlowBoxChild *self = GTK_FLOW_BOX_CHILD (widget);
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  if (priv->child)
+    {
+      *hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
+      *vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
+    }
+  else
+    {
+      *hexpand = FALSE;
+      *vexpand = FALSE;
+    }
+}
+
 /* GObject implementation {{{2 */
 
 static void
@@ -392,11 +497,25 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
+  object_class->dispose = gtk_flow_box_child_dispose;
+  object_class->get_property = gtk_flow_box_child_get_property;
+  object_class->set_property = gtk_flow_box_child_set_property;
+
   widget_class->get_request_mode = gtk_flow_box_child_get_request_mode;
+  widget_class->compute_expand = gtk_flow_box_child_compute_expand;
   widget_class->focus = gtk_flow_box_child_focus;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
 
   class->activate = gtk_flow_box_child_activate;
 
+  g_object_class_install_property (object_class,
+                                   PROP_CHILD,
+                                   g_param_spec_object ("child",
+                                                        P_("Child"),
+                                                        P_("The child widget"),
+                                                        GTK_TYPE_WIDGET,
+                                                        GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY));
+
   /**
    * GtkFlowBoxChild::activate:
    * @child: The child on which the signal is emitted
@@ -419,6 +538,7 @@ gtk_flow_box_child_class_init (GtkFlowBoxChildClass *class)
                   G_TYPE_NONE, 0);
   widget_class->activate_signal = child_signals[CHILD_ACTIVATE];
 
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_LIST_ITEM);
   gtk_widget_class_set_css_name (widget_class, I_("flowboxchild"));
 }
@@ -427,7 +547,7 @@ static void
 gtk_flow_box_child_init (GtkFlowBoxChild *child)
 {
 }
-
+ 
 /* Public API {{{2 */
 
 /**
@@ -444,6 +564,43 @@ gtk_flow_box_child_new (void)
   return g_object_new (GTK_TYPE_FLOW_BOX_CHILD, NULL);
 }
 
+/**
+ * gtk_flow_box_child_set_child:
+ * @self: a #GtkFlowBoxChild
+ * @child: (allow-none): the child widget
+ *
+ * Sets the child widget of @self.
+ */
+void
+gtk_flow_box_child_set_child (GtkFlowBoxChild *self,
+                              GtkWidget       *child)
+{
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  priv->child = child;
+  if (child)
+    gtk_widget_set_parent (child, GTK_WIDGET (self));
+  g_object_notify (G_OBJECT (self), "child");
+}
+
+/**
+ * gtk_flow_box_child_get_child:
+ * @self: a #GtkFlowBoxChild
+ *
+ * Gets the child widget of @self.
+ *
+ * Returns: (nullable) (transfer none): the child widget of @self
+ */
+GtkWidget *
+gtk_flow_box_child_get_child (GtkFlowBoxChild *self)
+{
+  GtkFlowBoxChildPrivate *priv = CHILD_PRIV (self);
+
+  return priv->child;
+}
+
 /**
  * gtk_flow_box_child_get_index:
  * @child: a #GtkFlowBoxChild
@@ -3198,7 +3355,7 @@ gtk_flow_box_move_cursor (GtkFlowBox      *box,
     {
       GtkWidget *subchild;
 
-      subchild = gtk_bin_get_child (GTK_BIN (child));
+      subchild = gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child));
       if (subchild)
         {
           GtkDirectionType direction = count < 0 ? GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
@@ -3853,8 +4010,7 @@ gtk_flow_box_insert (GtkFlowBox *box,
   else
     {
       child = GTK_FLOW_BOX_CHILD (gtk_flow_box_child_new ());
-      gtk_widget_show (GTK_WIDGET (child));
-      gtk_container_add (GTK_CONTAINER (child), widget);
+      gtk_flow_box_child_set_child (child, widget);
     }
 
   if (priv->sort_func != NULL)
diff --git a/gtk/gtkflowbox.h b/gtk/gtkflowbox.h
index ad1172d0e1..9b1729490d 100644
--- a/gtk/gtkflowbox.h
+++ b/gtk/gtkflowbox.h
@@ -29,7 +29,7 @@
 #error "Only <gtk/gtk.h> can be included directly."
 #endif
 
-#include <gtk/gtkbin.h>
+#include <gtk/gtkcontainer.h>
 
 G_BEGIN_DECLS
 
@@ -51,12 +51,12 @@ typedef struct _GtkFlowBoxChildClass  GtkFlowBoxChildClass;
 
 struct _GtkFlowBoxChild
 {
-  GtkBin parent_instance;
+  GtkWidget parent_instance;
 };
 
 struct _GtkFlowBoxChildClass
 {
-  GtkBinClass parent_class;
+  GtkWidgetClass parent_class;
 
   void (* activate) (GtkFlowBoxChild *child);
 
@@ -80,6 +80,13 @@ GDK_AVAILABLE_IN_ALL
 GType                 gtk_flow_box_child_get_type            (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
 GtkWidget*            gtk_flow_box_child_new                 (void);
+
+GDK_AVAILABLE_IN_ALL
+void                  gtk_flow_box_child_set_child          (GtkFlowBoxChild *self,
+                                                             GtkWidget       *child);
+GDK_AVAILABLE_IN_ALL
+GtkWidget *           gtk_flow_box_child_get_child          (GtkFlowBoxChild *self);
+
 GDK_AVAILABLE_IN_ALL
 gint                  gtk_flow_box_child_get_index           (GtkFlowBoxChild *child);
 GDK_AVAILABLE_IN_ALL
diff --git a/tests/testflowbox.c b/tests/testflowbox.c
index 30ae1c0b90..f44cbed2d9 100644
--- a/tests/testflowbox.c
+++ b/tests/testflowbox.c
@@ -304,7 +304,7 @@ on_child_activated (GtkFlowBox *self,
                     GtkWidget  *child)
 {
   const char *id;
-  id = g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (child))), "id");
+  id = g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (GTK_FLOW_BOX_CHILD (child))), "id");
   g_message ("Child activated %p: %s", child, id);
 }
 
@@ -316,7 +316,7 @@ selection_foreach (GtkFlowBox      *self,
   const char *id;
   GtkWidget *child;
 
-  child = gtk_bin_get_child (GTK_BIN (child_info));
+  child = gtk_flow_box_child_get_child (child_info);
   id = g_object_get_data (G_OBJECT (child), "id");
   g_message ("Child selected %p: %s", child, id);
 }
@@ -357,8 +357,8 @@ sort_func (GtkFlowBoxChild *a,
 {
   gchar *ida, *idb;
 
-  ida = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (a))), "id");
-  idb = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (b))), "id");
+  ida = (gchar *)g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (a)), "id");
+  idb = (gchar *)g_object_get_data (G_OBJECT (gtk_flow_box_child_get_child (b)), "id");
   return g_strcmp0 (ida, idb);
 }
 


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