[gtk+/wip/matthiasc/tab-strip] Don't derive from GtkBox



commit b875aaba99982b6d123dd07ac4d5feadf91809b1
Author: Matthias Clasen <mclasen redhat com>
Date:   Wed May 25 21:27:17 2016 -0400

    Don't derive from GtkBox
    
    Instead, derive from GtkContainer and use a box gadget to
    manage our internal children.

 gtk/gtktabstrip.c |  192 +++++++++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtktabstrip.h |    6 +-
 2 files changed, 182 insertions(+), 16 deletions(-)
---
diff --git a/gtk/gtktabstrip.c b/gtk/gtktabstrip.c
index eee7a33..77a3424 100644
--- a/gtk/gtktabstrip.c
+++ b/gtk/gtktabstrip.c
@@ -27,18 +27,21 @@
 #include "gtkorientable.h"
 #include "gtkscrolledwindow.h"
 #include "gtkbutton.h"
+#include "gtkbox.h"
 #include "gtkadjustmentprivate.h"
+#include "gtkboxgadgetprivate.h"
+#include "gtkwidgetprivate.h"
 
 /*
  * TODO:
  * - reordering
  * - dnd
- * - use a box gadget instead of GtkBox for tabs
  * - improve scrolling: scroll by tabs for click/activation
  */
 
 typedef struct
 {
+  GtkCssGadget    *gadget;
   GtkStack        *stack;
   GtkPositionType  edge;
   gboolean         closable;
@@ -52,7 +55,7 @@ typedef struct
   guint            autoscroll_id;
 } GtkTabStripPrivate;
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkTabStrip, gtk_tab_strip, GTK_TYPE_BOX)
+G_DEFINE_TYPE_WITH_PRIVATE (GtkTabStrip, gtk_tab_strip, GTK_TYPE_CONTAINER)
 
 enum {
   PROP_0,
@@ -76,7 +79,37 @@ static void
 gtk_tab_strip_add (GtkContainer *container,
                    GtkWidget    *widget)
 {
-  GTK_CONTAINER_CLASS (gtk_tab_strip_parent_class)->add (container, widget);
+  g_warning ("Can't add children to %s", G_OBJECT_TYPE_NAME (container));
+}
+
+static void
+gtk_tab_strip_remove (GtkContainer *container,
+                      GtkWidget    *widget)
+{
+  g_warning ("Can't remove children from %s", G_OBJECT_TYPE_NAME (container));
+}
+
+static void
+gtk_tab_strip_forall (GtkContainer *container,
+                      gboolean      include_internals,
+                      GtkCallback   callback,
+                      gpointer      callback_data)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (container);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  if (include_internals)
+    {
+      (*callback) (priv->start_scroll, callback_data);
+      (*callback) (priv->scrolledwindow, callback_data);
+      (*callback) (priv->end_scroll, callback_data);
+    }
+}
+
+static GType
+gtk_tab_strip_child_type (GtkContainer *container)
+{
+  return G_TYPE_NONE;
 }
 
 static void
@@ -93,6 +126,98 @@ gtk_tab_strip_destroy (GtkWidget *widget)
 }
 
 static void
+gtk_tab_strip_get_preferred_width (GtkWidget *widget,
+                                   gint      *minimum_size,
+                                   gint      *natural_size)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  gtk_css_gadget_get_preferred_size (priv->gadget,
+                                     GTK_ORIENTATION_HORIZONTAL,
+                                     -1,
+                                     minimum_size, natural_size,
+                                     NULL, NULL);
+}
+
+static void
+gtk_tab_strip_get_preferred_height (GtkWidget *widget,
+                                    gint      *minimum_size,
+                                    gint      *natural_size)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  gtk_css_gadget_get_preferred_size (priv->gadget,
+                                     GTK_ORIENTATION_VERTICAL,
+                                     -1,
+                                     minimum_size, natural_size,
+                                     NULL, NULL);
+}
+
+static void
+gtk_tab_strip_get_preferred_width_for_height (GtkWidget *widget,
+                                              gint       height,
+                                              gint      *minimum_size,
+                                              gint      *natural_size)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  gtk_css_gadget_get_preferred_size (priv->gadget,
+                                     GTK_ORIENTATION_HORIZONTAL,
+                                     height,
+                                     minimum_size, natural_size,
+                                     NULL, NULL);
+}
+
+static void
+gtk_tab_strip_get_preferred_height_for_width (GtkWidget *widget,
+                                              gint       width,
+                                              gint      *minimum_size,
+                                              gint      *natural_size)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  gtk_css_gadget_get_preferred_size (priv->gadget,
+                                     GTK_ORIENTATION_VERTICAL,
+                                     width,
+                                     minimum_size, natural_size,
+                                     NULL, NULL);
+}
+
+static void
+gtk_tab_strip_size_allocate (GtkWidget     *widget,
+                             GtkAllocation *allocation)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+  GtkAllocation clip;
+
+  gtk_widget_set_allocation (widget, allocation);
+
+  gtk_css_gadget_allocate (priv->gadget,
+                           allocation,
+                           gtk_widget_get_allocated_baseline (widget),
+                           &clip);
+
+  gtk_widget_set_clip (widget, &clip);
+}
+
+static gboolean
+gtk_tab_strip_draw (GtkWidget *widget,
+                    cairo_t   *cr)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (widget);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  gtk_css_gadget_draw (priv->gadget, cr);
+
+  return FALSE;
+}
+
+static void
 gtk_tab_strip_get_property (GObject    *object,
                             guint       prop_id,
                             GValue     *value,
@@ -154,6 +279,17 @@ gtk_tab_strip_set_property (GObject      *object,
     }
 }
 
+static void
+gtk_tab_strip_finalize (GObject *object)
+{
+  GtkTabStrip *self = GTK_TAB_STRIP (object);
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  g_clear_object (&priv->gadget);
+
+  G_OBJECT_CLASS (gtk_tab_strip_parent_class)->finalize (object);
+}
+
 static GtkTab *gtk_tab_strip_real_create_tab (GtkTabStrip *self,
                                               GtkWidget   *widget);
 
@@ -166,10 +302,20 @@ gtk_tab_strip_class_init (GtkTabStripClass *klass)
 
   object_class->get_property = gtk_tab_strip_get_property;
   object_class->set_property = gtk_tab_strip_set_property;
+  object_class->finalize = gtk_tab_strip_finalize;
 
   widget_class->destroy = gtk_tab_strip_destroy;
+  widget_class->get_preferred_width = gtk_tab_strip_get_preferred_width;
+  widget_class->get_preferred_height = gtk_tab_strip_get_preferred_height;
+  widget_class->get_preferred_width_for_height = gtk_tab_strip_get_preferred_width_for_height;
+  widget_class->get_preferred_height_for_width = gtk_tab_strip_get_preferred_height_for_width;
+  widget_class->size_allocate = gtk_tab_strip_size_allocate;
+  widget_class->draw = gtk_tab_strip_draw;
 
   container_class->add = gtk_tab_strip_add;
+  container_class->remove = gtk_tab_strip_remove;
+  container_class->forall = gtk_tab_strip_forall;
+  container_class->child_type = gtk_tab_strip_child_type;
 
   klass->create_tab = gtk_tab_strip_real_create_tab;
 
@@ -208,6 +354,17 @@ gtk_tab_strip_class_init (GtkTabStripClass *klass)
   gtk_widget_class_set_css_name (widget_class, "tabs");
 }
 
+static gboolean
+gtk_tab_strip_get_orientation (GtkTabStrip *self)
+{
+  GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
+
+  if (priv->edge == GTK_POS_TOP || priv->edge == GTK_POS_BOTTOM)
+    return GTK_ORIENTATION_HORIZONTAL;
+  else
+    return GTK_ORIENTATION_VERTICAL;
+}
+
 static void
 update_scrolling (GtkTabStrip *self)
 {
@@ -217,7 +374,7 @@ update_scrolling (GtkTabStrip *self)
 
   if (priv->scrollable)
     {
-      if (gtk_orientable_get_orientation (GTK_ORIENTABLE (self)) == GTK_ORIENTATION_HORIZONTAL)
+      if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
         hscroll = GTK_POLICY_EXTERNAL;
       else
         vscroll = GTK_POLICY_EXTERNAL;
@@ -237,7 +394,7 @@ autoscroll_cb (GtkWidget     *widget,
   GtkAdjustment *adj;
   gdouble value;
 
-  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (self)) == GTK_ORIENTATION_HORIZONTAL)
+  if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
     adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
   else
     adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
@@ -304,7 +461,7 @@ scroll_button_activate (GtkWidget   *button,
   GtkAdjustment *adj;
   gdouble value;
 
-  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (self)) == GTK_ORIENTATION_HORIZONTAL)
+  if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
     adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
   else
     adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
@@ -326,7 +483,7 @@ adjustment_changed (GtkTabStrip *self)
   gdouble value;
   gboolean at_lower, at_upper;
 
-  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (self)) == GTK_ORIENTATION_HORIZONTAL)
+  if (gtk_tab_strip_get_orientation (self) == GTK_ORIENTATION_HORIZONTAL)
     adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
   else
     adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->scrolledwindow));
@@ -347,17 +504,25 @@ gtk_tab_strip_init (GtkTabStrip *self)
 {
   GtkTabStripPrivate *priv = gtk_tab_strip_get_instance_private (self);
   GtkAdjustment *adj;
+  GtkCssNode *widget_node;
+
+  gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
 
   priv->edge = GTK_POS_TOP;
   priv->scrollable = FALSE;
   priv->closable = FALSE;
 
+  widget_node = gtk_widget_get_css_node (GTK_WIDGET (self));
+  priv->gadget = gtk_box_gadget_new_for_node (widget_node, GTK_WIDGET (self));
+  gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
+
   priv->start_scroll = gtk_button_new_from_icon_name ("pan-start-symbolic", GTK_ICON_SIZE_MENU);
   gtk_button_set_relief (GTK_BUTTON (priv->start_scroll), GTK_RELIEF_NONE);
   gtk_widget_show (priv->start_scroll);
   gtk_widget_set_no_show_all (priv->start_scroll, TRUE);
   gtk_widget_set_focus_on_click (priv->start_scroll, FALSE);
-  gtk_box_pack_start (GTK_BOX (self), priv->start_scroll, FALSE, FALSE, 0);
+  gtk_widget_set_parent (priv->start_scroll, GTK_WIDGET (self));
+  gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->gadget), 0, priv->start_scroll);
   g_signal_connect (priv->start_scroll, "button-press-event",
                     G_CALLBACK (scroll_button_event), self);
   g_signal_connect (priv->start_scroll, "button-release-event",
@@ -367,8 +532,9 @@ gtk_tab_strip_init (GtkTabStrip *self)
 
   priv->scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
   gtk_widget_show (priv->scrolledwindow);
-  gtk_box_pack_start (GTK_BOX (self), priv->scrolledwindow, TRUE, TRUE, 0);
-
+  gtk_widget_set_parent (priv->scrolledwindow, GTK_WIDGET (self));
+  gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->gadget), 1, priv->scrolledwindow);
+  gtk_box_gadget_set_gadget_expand (GTK_BOX_GADGET (priv->gadget), G_OBJECT (priv->scrolledwindow), TRUE);
   update_scrolling (self);
 
   priv->end_scroll = gtk_button_new_from_icon_name ("pan-end-symbolic", GTK_ICON_SIZE_MENU);
@@ -376,7 +542,8 @@ gtk_tab_strip_init (GtkTabStrip *self)
   gtk_widget_show (priv->end_scroll);
   gtk_widget_set_no_show_all (priv->end_scroll, TRUE);
   gtk_widget_set_focus_on_click (priv->end_scroll, FALSE);
-  gtk_box_pack_start (GTK_BOX (self), priv->end_scroll, FALSE, FALSE, 0);
+  gtk_widget_set_parent (priv->end_scroll, GTK_WIDGET (self));
+  gtk_box_gadget_insert_widget (GTK_BOX_GADGET (priv->gadget), 2, priv->end_scroll);
   g_signal_connect (priv->end_scroll, "button-press-event",
                     G_CALLBACK (scroll_button_event), self);
   g_signal_connect (priv->end_scroll, "button-release-event",
@@ -392,7 +559,6 @@ gtk_tab_strip_init (GtkTabStrip *self)
   g_signal_connect_swapped (adj, "changed", G_CALLBACK (adjustment_changed), self);
   g_signal_connect_swapped (adj, "value-changed", G_CALLBACK (adjustment_changed), self);
 
-
   priv->tabs = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
   gtk_widget_show (priv->tabs);
   gtk_container_add (GTK_CONTAINER (priv->scrolledwindow), priv->tabs);
@@ -701,7 +867,7 @@ gtk_tab_strip_set_edge (GtkTabStrip     *self,
   gtk_style_context_add_class (context, classes[priv->edge]);
 
   orientation = orientations[priv->edge];
-  gtk_orientable_set_orientation (GTK_ORIENTABLE (self), orientation);
+  gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), orientation);
   gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->tabs), orientation);
 
   image = gtk_button_get_image (GTK_BUTTON (priv->start_scroll));
diff --git a/gtk/gtktabstrip.h b/gtk/gtktabstrip.h
index 2a38dd2..92f3993 100644
--- a/gtk/gtktabstrip.h
+++ b/gtk/gtktabstrip.h
@@ -23,7 +23,7 @@
 #ifndef __GTK_TAB_STRIP_H__
 #define __GTK_TAB_STRIP_H__
 
-#include <gtk/gtkbox.h>
+#include <gtk/gtkcontainer.h>
 #include <gtk/gtkstack.h>
 #include <gtk/gtktab.h>
 #include <gtk/gtktypebuiltins.h>
@@ -42,12 +42,12 @@ typedef struct _GtkTabStripClass GtkTabStripClass;
 
 struct _GtkTabStrip
 {
-  GtkBox parent;
+  GtkContainer parent;
 };
 
 struct _GtkTabStripClass
 {
-  GtkBoxClass parent_class;
+  GtkContainerClass parent_class;
 
   GtkTab * (* create_tab) (GtkTabStrip *self,
                            GtkWidget   *child);


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