Commit b875aaba authored by Matthias Clasen's avatar Matthias Clasen

Don't derive from GtkBox

Instead, derive from GtkContainer and use a box gadget to
manage our internal children.
parent 39d863ca
......@@ -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
......@@ -92,6 +125,98 @@ gtk_tab_strip_destroy (GtkWidget *widget)
GTK_WIDGET_CLASS (gtk_tab_strip_parent_class)->destroy (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,
......@@ -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));
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment