[gtk/bin-removal: 19/49] button: Derive from GtkWidget



commit 44122e25ff8576dd3b3bef34a4f1b47959425935
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat May 2 10:30:46 2020 -0400

    button: Derive from GtkWidget
    
    We want to remove GtkBin and GtkContainer as they don't
    provide much useful functionality anymore. This requires
    us to move get_request_mode and compute_expand down.
    
    We have to implement GtkBuildable, in order to keep
    the <child> element in ui files working for buttons.
    
    See #2681

 gtk/gtkbutton.c | 149 ++++++++++++++++++++++++++++++++------------------------
 gtk/gtkbutton.h |   6 +--
 2 files changed, 88 insertions(+), 67 deletions(-)
---
diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c
index b161c18059..7c10d21b16 100644
--- a/gtk/gtkbutton.c
+++ b/gtk/gtkbutton.c
@@ -56,9 +56,11 @@
 #include "gtkbuttonprivate.h"
 
 #include "gtkactionhelperprivate.h"
+#include "gtkbuildable.h"
 #include "gtkcheckbutton.h"
 #include "gtkgestureclick.h"
 #include "gtkeventcontrollerkey.h"
+#include "gtkbinlayout.h"
 #include "gtkimage.h"
 #include "gtkintl.h"
 #include "gtklabel.h"
@@ -80,6 +82,8 @@
 
 struct _GtkButtonPrivate
 {
+  GtkWidget             *child;
+
   GtkActionHelper       *action_helper;
 
   GtkGesture            *gesture;
@@ -140,50 +144,57 @@ static void gtk_button_grab_notify     (GtkWidget             *widget,
                                        gboolean               was_grabbed);
 static void gtk_button_do_release      (GtkButton             *button,
                                         gboolean               emit_clicked);
+static void gtk_button_set_child_type (GtkButton *button, guint child_type);
 
+static void gtk_button_buildable_iface_init      (GtkBuildableIface *iface);
 static void gtk_button_actionable_iface_init     (GtkActionableInterface *iface);
 
-static void gtk_button_set_child_type (GtkButton *button, guint child_type);
-
 static GParamSpec *props[LAST_PROP] = { NULL, };
 static guint button_signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_BIN,
+G_DEFINE_TYPE_WITH_CODE (GtkButton, gtk_button, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (GtkButton)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_button_buildable_iface_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIONABLE, gtk_button_actionable_iface_init))
 
 static void
-gtk_button_add (GtkContainer *container, GtkWidget *child)
+gtk_button_unmap (GtkWidget *widget)
 {
-  GtkButton *button = GTK_BUTTON (container);
-  GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
-
-  if (priv->child_type != WIDGET_CHILD)
-    gtk_container_remove (container, gtk_bin_get_child (GTK_BIN (button)));
+  GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
 
-  gtk_button_set_child_type (button, WIDGET_CHILD);
+  priv->in_button = FALSE;
 
-  GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, child);
+  GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
 }
 
 static void
-gtk_button_remove (GtkContainer *container, GtkWidget *child)
+gtk_button_compute_expand (GtkWidget *widget,
+                           gboolean  *hexpand,
+                           gboolean  *vexpand)
 {
-  GtkButton *button = GTK_BUTTON (container);
-
-  gtk_button_set_child_type (button, WIDGET_CHILD);
+  GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
 
-  GTK_CONTAINER_CLASS (gtk_button_parent_class)->remove (container, child);
+  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;
+    }
 }
 
-static void
-gtk_button_unmap (GtkWidget *widget)
+static GtkSizeRequestMode
+gtk_button_get_request_mode (GtkWidget *widget)
 {
   GtkButtonPrivate *priv = gtk_button_get_instance_private (GTK_BUTTON (widget));
 
-  priv->in_button = FALSE;
-
-  GTK_WIDGET_CLASS (gtk_button_parent_class)->unmap (widget);
+  if (priv->child)
+    return gtk_widget_get_request_mode (priv->child);
+  else
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
 }
 
 static void
@@ -191,11 +202,9 @@ gtk_button_class_init (GtkButtonClass *klass)
 {
   GObjectClass *gobject_class;
   GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
 
   gobject_class = G_OBJECT_CLASS (klass);
   widget_class = (GtkWidgetClass*) klass;
-  container_class = GTK_CONTAINER_CLASS (klass);
 
   gobject_class->dispose      = gtk_button_dispose;
   gobject_class->set_property = gtk_button_set_property;
@@ -207,9 +216,8 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class->unmap = gtk_button_unmap;
   widget_class->grab_focus = gtk_widget_grab_focus_self;
   widget_class->focus = gtk_widget_focus_self;
-
-  container_class->add    = gtk_button_add;
-  container_class->remove = gtk_button_remove;
+  widget_class->compute_expand = gtk_button_compute_expand;
+  widget_class->get_request_mode = gtk_button_get_request_mode;
 
   klass->clicked = NULL;
   klass->activate = gtk_real_button_activate;
@@ -288,6 +296,7 @@ gtk_button_class_init (GtkButtonClass *klass)
                  G_TYPE_NONE, 0);
   widget_class->activate_signal = button_signals[ACTIVATE];
 
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_BUTTON_ACCESSIBLE);
   gtk_widget_class_set_css_name (widget_class, I_("button"));
 }
@@ -441,6 +450,7 @@ gtk_button_dispose (GObject *object)
   GtkButton *button = GTK_BUTTON (object);
   GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
 
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
   g_clear_object (&priv->action_helper);
 
   G_OBJECT_CLASS (gtk_button_parent_class)->dispose (object);
@@ -537,7 +547,7 @@ gtk_button_get_property (GObject         *object,
       g_value_set_string (value, gtk_button_get_icon_name (button));
       break;
     case PROP_CHILD:
-      g_value_set_object (value, gtk_button_get_child (button));
+      g_value_set_object (value, priv->child);
       break;
     case PROP_ACTION_NAME:
       g_value_set_string (value, gtk_action_helper_get_action_name (priv->action_helper));
@@ -578,6 +588,28 @@ gtk_button_actionable_iface_init (GtkActionableInterface *iface)
   iface->set_action_target_value = gtk_button_set_action_target_value;
 }
 
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_button_buildable_add_child (GtkBuildable *buildable,
+                                GtkBuilder   *builder,
+                                GObject      *child,
+                                const gchar  *type)
+{
+  if (GTK_IS_WIDGET (child))
+    gtk_button_set_child (GTK_BUTTON (buildable), GTK_WIDGET (child));
+  else
+    parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_button_buildable_iface_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->add_child = gtk_button_buildable_add_child;
+}
+
 /**
  * gtk_button_new:
  *
@@ -787,13 +819,8 @@ gtk_button_set_label (GtkButton   *button,
 
   g_return_if_fail (GTK_IS_BUTTON (button));
 
-  child = gtk_bin_get_child (GTK_BIN (button));
-
-  if (priv->child_type != LABEL_CHILD || child == NULL)
+  if (priv->child_type != LABEL_CHILD || priv->child == NULL)
     {
-      if (child != NULL)
-        gtk_button_remove (GTK_CONTAINER (button), child);
-
       child = gtk_label_new (NULL);
       if (priv->use_underline)
         {
@@ -801,15 +828,14 @@ gtk_button_set_label (GtkButton   *button,
           gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
         }
       if (GTK_IS_CHECK_BUTTON (button))
-        {
-          gtk_label_set_xalign (GTK_LABEL (child), 0.0);
-        }
-      gtk_button_add (GTK_CONTAINER (button), child);
+        gtk_label_set_xalign (GTK_LABEL (child), 0.0);
+
+      gtk_button_set_child (button,  child);
       gtk_widget_remove_css_class (GTK_WIDGET (button), "image-button");
       gtk_widget_add_css_class (GTK_WIDGET (button), "text-button");
     }
 
-  gtk_label_set_label (GTK_LABEL (child), label);
+  gtk_label_set_label (GTK_LABEL (priv->child), label);
   gtk_button_set_child_type (button, LABEL_CHILD);
   g_object_notify_by_pspec (G_OBJECT (button), props[PROP_LABEL]);
 }
@@ -835,10 +861,7 @@ gtk_button_get_label (GtkButton *button)
   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
 
   if (priv->child_type == LABEL_CHILD)
-    {
-      GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
-      return gtk_label_get_label (GTK_LABEL (child));
-    }
+    return gtk_label_get_label (GTK_LABEL (priv->child));
 
   return NULL;
 }
@@ -853,7 +876,7 @@ gtk_button_get_label (GtkButton *button)
  */
 void
 gtk_button_set_use_underline (GtkButton *button,
-                             gboolean   use_underline)
+                              gboolean   use_underline)
 {
   GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
 
@@ -865,11 +888,8 @@ gtk_button_set_use_underline (GtkButton *button,
     {
       if (priv->child_type == LABEL_CHILD)
         {
-          GtkWidget *child;
-          child = gtk_bin_get_child (GTK_BIN (button));
-
-          gtk_label_set_use_underline (GTK_LABEL (child), use_underline);
-          gtk_label_set_mnemonic_widget (GTK_LABEL (child), GTK_WIDGET (button));
+          gtk_label_set_use_underline (GTK_LABEL (priv->child), use_underline);
+          gtk_label_set_mnemonic_widget (GTK_LABEL (priv->child), GTK_WIDGET (button));
         }
 
       priv->use_underline = use_underline;
@@ -937,23 +957,20 @@ gtk_button_set_icon_name (GtkButton  *button,
                           const char *icon_name)
 {
   GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
-  GtkWidget *child;
 
   g_return_if_fail (GTK_IS_BUTTON (button));
   g_return_if_fail (icon_name != NULL);
 
-  child = gtk_bin_get_child (GTK_BIN (button));
-
-  if (priv->child_type != ICON_CHILD || child == NULL)
+  if (priv->child_type != ICON_CHILD || priv->child == NULL)
     {
-      child = gtk_image_new_from_icon_name (icon_name);
+      GtkWidget *child = gtk_image_new_from_icon_name (icon_name);
       gtk_button_set_child (GTK_BUTTON (button), child);
       gtk_widget_remove_css_class (GTK_WIDGET (button), "text-button");
       gtk_widget_add_css_class (GTK_WIDGET (button), "image-button");
     }
   else
     {
-      gtk_image_set_from_icon_name (GTK_IMAGE (child), icon_name);
+      gtk_image_set_from_icon_name (GTK_IMAGE (priv->child), icon_name);
     }
 
   gtk_button_set_child_type (button, ICON_CHILD);
@@ -976,11 +993,7 @@ gtk_button_get_icon_name (GtkButton *button)
   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
 
   if (priv->child_type == ICON_CHILD)
-    {
-      GtkWidget *child = gtk_bin_get_child (GTK_BIN (button));
-
-      return gtk_image_get_icon_name (GTK_IMAGE (child));
-    }
+    return gtk_image_get_icon_name (GTK_IMAGE (priv->child));
 
   return NULL;
 }
@@ -1004,13 +1017,19 @@ void
 gtk_button_set_child (GtkButton *button,
                       GtkWidget *child)
 {
+  GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
   g_return_if_fail (GTK_IS_BUTTON (button));
   g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
 
-  if (gtk_bin_get_child (GTK_BIN (button)))
-    gtk_button_remove (GTK_CONTAINER (button),
-                       gtk_bin_get_child (GTK_BIN (button)));
-  gtk_button_add (GTK_CONTAINER (button), child);
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  priv->child = child;
+
+  if (priv->child)
+    gtk_widget_set_parent (priv->child, GTK_WIDGET (button));
+
+  gtk_button_set_child_type (button, WIDGET_CHILD);
   g_object_notify (G_OBJECT (button), "child");
 }
 
@@ -1025,8 +1044,10 @@ gtk_button_set_child (GtkButton *button,
 GtkWidget *
 gtk_button_get_child (GtkButton *button)
 {
+  GtkButtonPrivate *priv = gtk_button_get_instance_private (button);
+
   g_return_val_if_fail (GTK_IS_BUTTON (button), NULL);
 
-  return gtk_bin_get_child (GTK_BIN (button));
+  return priv->child;
 }
 
diff --git a/gtk/gtkbutton.h b/gtk/gtkbutton.h
index 64440efb5f..fd4b54122f 100644
--- a/gtk/gtkbutton.h
+++ b/gtk/gtkbutton.h
@@ -30,7 +30,7 @@
 #error "Only <gtk/gtk.h> can be included directly."
 #endif
 
-#include <gtk/gtkbin.h>
+#include <gtk/gtkwidget.h>
 
 G_BEGIN_DECLS
 
@@ -48,7 +48,7 @@ typedef struct _GtkButtonClass        GtkButtonClass;
 struct _GtkButton
 {
   /*< private >*/
-  GtkBin parent_instance;
+  GtkWidget parent_instance;
 };
 
 /**
@@ -61,7 +61,7 @@ struct _GtkButton
  */
 struct _GtkButtonClass
 {
-  GtkBinClass        parent_class;
+  GtkWidgetClass        parent_class;
 
   /*< public >*/
 


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