[gtk+] boxgadget: Add
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] boxgadget: Add
- Date: Mon, 11 Jan 2016 16:30:39 +0000 (UTC)
commit acc534ebfa2a3c292aca590c8a116a6340d2274d
Author: Benjamin Otte <otte redhat com>
Date: Wed Dec 23 04:09:30 2015 +0100
boxgadget: Add
Adds a GtkBoxGadget that is a Gadget that behaves like a GtkBox.
Use this gadget to implement the notebook base gadget.
gtk/Makefile.am | 2 +
gtk/gtkboxgadget.c | 511 +++++++++++++++++++++++++++++++++++++++++++++
gtk/gtkboxgadgetprivate.h | 74 +++++++
gtk/gtknotebook.c | 334 +++++++-----------------------
4 files changed, 658 insertions(+), 263 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index ff259d1..527037a 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -365,6 +365,7 @@ gtk_private_h_sources = \
gtkbitmaskprivateimpl.h \
gtkbookmarksmanager.h \
gtkboxprivate.h \
+ gtkboxgadgetprivate.h \
gtkbuilderprivate.h \
gtkbuiltiniconprivate.h \
gtkbuttonprivate.h \
@@ -600,6 +601,7 @@ gtk_base_c_sources = \
gtkbookmarksmanager.c \
gtkborder.c \
gtkbox.c \
+ gtkboxgadget.c \
gtkbuildable.c \
gtkbuilder.c \
gtkbuilderparser.c \
diff --git a/gtk/gtkboxgadget.c b/gtk/gtkboxgadget.c
new file mode 100644
index 0000000..6ea8529
--- /dev/null
+++ b/gtk/gtkboxgadget.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright © 2015 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#include "config.h"
+
+#include "gtkboxgadgetprivate.h"
+
+#include "gtkcssnodeprivate.h"
+#include "gtkmain.h"
+#include "gtkprivate.h"
+#include "gtksizerequest.h"
+#include "gtkwidgetprivate.h"
+
+typedef struct _GtkBoxGadgetPrivate GtkBoxGadgetPrivate;
+struct _GtkBoxGadgetPrivate {
+ GtkOrientation orientation;
+ GArray *children;
+};
+
+typedef gboolean (* ComputeExpandFunc) (GObject *object, GtkOrientation orientation);
+
+typedef struct _GtkBoxGadgetChild GtkBoxGadgetChild;
+struct _GtkBoxGadgetChild {
+ GObject *object;
+ ComputeExpandFunc compute_expand;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GtkBoxGadget, gtk_box_gadget, GTK_TYPE_CSS_GADGET,
+ G_ADD_PRIVATE (GtkBoxGadget))
+
+static gboolean
+gtk_box_gadget_child_is_visible (GObject *child)
+{
+ if (GTK_IS_WIDGET (child))
+ return gtk_widget_get_visible (GTK_WIDGET (child));
+ else
+ return gtk_css_gadget_get_visible (GTK_CSS_GADGET (child));
+}
+
+static void
+gtk_box_gadget_measure_child (GObject *child,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ if (GTK_IS_WIDGET (child))
+ {
+ _gtk_widget_get_preferred_size_for_size (GTK_WIDGET (child),
+ orientation,
+ for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+ }
+ else
+ {
+ gtk_css_gadget_get_preferred_size (GTK_CSS_GADGET (child),
+ orientation,
+ for_size,
+ minimum, natural,
+ minimum_baseline, natural_baseline);
+ }
+}
+
+static void
+gtk_box_gadget_distribute (GtkBoxGadget *gadget,
+ gint size,
+ GtkRequestedSize *sizes)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ guint i, n_expand;
+
+ n_expand = 0;
+
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ gtk_box_gadget_measure_child (child->object,
+ priv->orientation,
+ -1,
+ &sizes[i].minimum_size, &sizes[i].natural_size,
+ NULL, NULL);
+ if (gtk_box_gadget_child_is_visible (child->object) &&
+ child->compute_expand (child->object, priv->orientation))
+ n_expand++;
+ size -= sizes[i].minimum_size;
+ }
+
+ g_assert (size >= 0);
+
+ size = gtk_distribute_natural_allocation (size, priv->children->len, sizes);
+
+ if (size <= 0 || n_expand == 0)
+ return;
+
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ if (!gtk_box_gadget_child_is_visible (child->object) ||
+ !child->compute_expand (child->object, priv->orientation))
+ continue;
+
+ sizes[i].minimum_size += size / n_expand;
+ /* distribute all pixels, even if there's a remainder */
+ size -= size / n_expand;
+ n_expand--;
+ }
+}
+
+static void
+gtk_box_gadget_measure_orientation (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ gint child_min, child_nat;
+ guint i;
+
+ *minimum = 0;
+ *natural = 0;
+
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ gtk_box_gadget_measure_child (child->object,
+ orientation,
+ for_size,
+ &child_min, &child_nat,
+ NULL, NULL);
+
+ *minimum += child_min;
+ *natural += child_nat;
+ }
+}
+
+static void
+gtk_box_gadget_measure_opposite (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ int child_min, child_nat, child_min_baseline, child_nat_baseline;
+ int total_min, above_min, below_min, total_nat, above_nat, below_nat;
+ GtkRequestedSize *sizes;
+ guint i;
+
+ if (for_size >= 0)
+ {
+ sizes = g_newa (GtkRequestedSize, priv->children->len);
+ gtk_box_gadget_distribute (GTK_BOX_GADGET (gadget), for_size, sizes);
+ }
+
+ above_min = below_min = above_nat = below_nat = -1;
+ total_min = total_nat = 0;
+
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ gtk_box_gadget_measure_child (child->object,
+ orientation,
+ for_size >= 0 ? sizes[i].minimum_size : for_size,
+ &child_min, &child_nat,
+ &child_min_baseline, &child_nat_baseline);
+
+ if (child_min_baseline >= 0)
+ {
+ above_min = MAX (above_min, child_min - child_min_baseline);
+ below_min = MAX (below_min, child_min_baseline);
+ above_nat = MAX (above_nat, child_nat - child_nat_baseline);
+ below_nat = MAX (below_nat, child_nat_baseline);
+ }
+ else
+ {
+ total_min = MAX (total_min, child_min);
+ total_nat = MAX (total_nat, child_nat);
+ }
+ }
+
+ if (above_min >= 0)
+ {
+ total_min = MAX (total_min, above_min + below_min);
+ total_nat = MAX (total_nat, above_nat + below_nat);
+ /* assume GTK_BASELINE_POSITION_CENTER for now */
+ *minimum_baseline = above_min + (total_min - (above_min + below_min)) / 2;
+ *natural_baseline = above_nat + (total_nat - (above_nat + below_nat)) / 2;
+ }
+
+ *minimum = total_min;
+ *natural = total_nat;
+}
+
+static void
+gtk_box_gadget_get_preferred_size (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+
+ if (priv->orientation == orientation)
+ gtk_box_gadget_measure_orientation (gadget, orientation, for_size, minimum, natural, minimum_baseline,
natural_baseline);
+ else
+ gtk_box_gadget_measure_opposite (gadget, orientation, for_size, minimum, natural, minimum_baseline,
natural_baseline);
+}
+
+static void
+gtk_box_gadget_allocate_child (GObject *child,
+ GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip)
+{
+ if (GTK_IS_WIDGET (child))
+ {
+ gtk_widget_size_allocate_with_baseline (GTK_WIDGET (child),
+ allocation,
+ baseline);
+ gtk_widget_get_clip (GTK_WIDGET (child), out_clip);
+ }
+ else
+ {
+ gtk_css_gadget_allocate (GTK_CSS_GADGET (child),
+ allocation,
+ baseline,
+ out_clip);
+ }
+}
+
+static void
+gtk_box_gadget_allocate (GtkCssGadget *gadget,
+ const GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ GtkRequestedSize *sizes;
+ GtkAllocation child_allocation, child_clip;
+ guint i;
+
+ child_allocation = *allocation;
+ sizes = g_newa (GtkRequestedSize, priv->children->len);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gtk_box_gadget_distribute (GTK_BOX_GADGET (gadget), allocation->width, sizes);
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ child_allocation.width = sizes[i].minimum_size;
+ gtk_box_gadget_allocate_child (child->object, &child_allocation, baseline, &child_clip);
+ if (i == 0)
+ *out_clip = child_clip;
+ else
+ gdk_rectangle_union (out_clip, &child_clip, out_clip);
+ child_allocation.x += sizes[i].minimum_size;
+ }
+ }
+ else
+ {
+ gtk_box_gadget_distribute (GTK_BOX_GADGET (gadget), allocation->height, sizes);
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ child_allocation.height = sizes[i].minimum_size;
+ gtk_box_gadget_allocate_child (child->object, &child_allocation, -1, &child_clip);
+ if (i == 0)
+ *out_clip = child_clip;
+ else
+ gdk_rectangle_union (out_clip, &child_clip, out_clip);
+ child_allocation.y += sizes[i].minimum_size;
+ }
+ }
+}
+
+static gboolean
+gtk_box_gadget_draw (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ guint i;
+
+ for (i = 0 ; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ if (GTK_IS_WIDGET (child->object))
+ {
+ gtk_container_propagate_draw (GTK_CONTAINER (gtk_css_gadget_get_owner (gadget)),
+ GTK_WIDGET (child->object),
+ cr);
+ }
+ else
+ {
+ gtk_css_gadget_draw (GTK_CSS_GADGET (child->object),
+ cr);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_box_gadget_finalize (GObject *object)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (object));
+
+ g_array_free (priv->children, TRUE);
+
+ G_OBJECT_CLASS (gtk_box_gadget_parent_class)->finalize (object);
+}
+
+static void
+gtk_box_gadget_class_init (GtkBoxGadgetClass *klass)
+{
+ GtkCssGadgetClass *gadget_class = GTK_CSS_GADGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gtk_box_gadget_finalize;
+
+ gadget_class->get_preferred_size = gtk_box_gadget_get_preferred_size;
+ gadget_class->allocate = gtk_box_gadget_allocate;
+ gadget_class->draw = gtk_box_gadget_draw;
+}
+
+static void
+gtk_box_gadget_clear_child (gpointer data)
+{
+ GtkBoxGadgetChild *child = data;
+
+ g_object_unref (child->object);
+}
+
+static void
+gtk_box_gadget_init (GtkBoxGadget *gadget)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (gadget);
+
+ priv->children = g_array_new (FALSE, FALSE, sizeof (GtkBoxGadgetChild));
+ g_array_set_clear_func (priv->children, gtk_box_gadget_clear_child);
+}
+
+GtkCssGadget *
+gtk_box_gadget_new_for_node (GtkCssNode *node,
+ GtkWidget *owner)
+{
+ return g_object_new (GTK_TYPE_BOX_GADGET,
+ "node", node,
+ "owner", owner,
+ NULL);
+}
+
+GtkCssGadget *
+gtk_box_gadget_new (const char *name,
+ GtkWidget *owner,
+ GtkCssGadget *parent,
+ GtkCssGadget *next_sibling)
+{
+ GtkCssNode *node;
+ GtkCssGadget *result;
+
+ node = gtk_css_node_new ();
+ gtk_css_node_set_name (node, g_intern_string (name));
+ if (parent)
+ gtk_css_node_insert_before (gtk_css_gadget_get_node (parent),
+ node,
+ next_sibling ? gtk_css_gadget_get_node (next_sibling) : NULL);
+
+ result = gtk_box_gadget_new_for_node (node, owner);
+
+ g_object_unref (node);
+
+ return result;
+}
+
+void
+gtk_box_gadget_set_orientation (GtkBoxGadget *gadget,
+ GtkOrientation orientation)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (gadget);
+
+ priv->orientation = orientation;
+}
+
+static void
+gtk_box_gadget_insert_object (GtkBoxGadget *gadget,
+ int pos,
+ GObject *object,
+ ComputeExpandFunc compute_expand_func)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (gadget);
+ GtkBoxGadgetChild child;
+
+ child.object = g_object_ref (object);
+ child.compute_expand = compute_expand_func;
+
+ if (pos < 0 || pos >= priv->children->len)
+ g_array_append_val (priv->children, child);
+ else
+ g_array_insert_val (priv->children, pos, child);
+}
+
+void
+gtk_box_gadget_insert_widget (GtkBoxGadget *gadget,
+ int pos,
+ GtkWidget *widget)
+{
+ gtk_box_gadget_insert_object (gadget,
+ pos,
+ G_OBJECT (widget),
+ (ComputeExpandFunc) gtk_widget_compute_expand);
+}
+
+void
+gtk_box_gadget_remove_object (GtkBoxGadget *gadget,
+ GObject *object)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (gadget);
+ guint i;
+
+ for (i = 0; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ if (child->object == object)
+ {
+ g_array_remove_index (priv->children, i);
+ break;
+ }
+ }
+}
+
+void
+gtk_box_gadget_remove_widget (GtkBoxGadget *gadget,
+ GtkWidget *widget)
+{
+ gtk_box_gadget_remove_object (gadget, G_OBJECT (widget));
+}
+
+static gboolean
+only_horizontal (GObject *object,
+ GtkOrientation orientation)
+{
+ return orientation == GTK_ORIENTATION_HORIZONTAL;
+}
+
+static gboolean
+only_vertical (GObject *object,
+ GtkOrientation orientation)
+{
+ return orientation == GTK_ORIENTATION_VERTICAL;
+}
+
+void
+gtk_box_gadget_insert_gadget (GtkBoxGadget *gadget,
+ int pos,
+ GtkCssGadget *cssgadget,
+ gboolean hexpand,
+ gboolean vexpand)
+{
+ gtk_box_gadget_insert_object (gadget,
+ pos,
+ G_OBJECT (cssgadget),
+ hexpand ? (vexpand ? (ComputeExpandFunc) gtk_true : only_horizontal)
+ : (vexpand ? only_vertical : (ComputeExpandFunc) gtk_false));
+}
+
+void
+gtk_box_gadget_remove_gadget (GtkBoxGadget *gadget,
+ GtkCssGadget *cssgadget)
+{
+ gtk_box_gadget_remove_object (gadget, G_OBJECT (cssgadget));
+}
+
diff --git a/gtk/gtkboxgadgetprivate.h b/gtk/gtkboxgadgetprivate.h
new file mode 100644
index 0000000..ce64e41
--- /dev/null
+++ b/gtk/gtkboxgadgetprivate.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2015 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+#ifndef __GTK_BOX_GADGET_PRIVATE_H__
+#define __GTK_BOX_GADGET_PRIVATE_H__
+
+#include "gtk/gtkcssgadgetprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_BOX_GADGET (gtk_box_gadget_get_type ())
+#define GTK_BOX_GADGET(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_BOX_GADGET, GtkBoxGadget))
+#define GTK_BOX_GADGET_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_BOX_GADGET, GtkBoxGadgetClass))
+#define GTK_IS_BOX_GADGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_BOX_GADGET))
+#define GTK_IS_BOX_GADGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_BOX_GADGET))
+#define GTK_BOX_GADGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_BOX_GADGET,
GtkBoxGadgetClass))
+
+typedef struct _GtkBoxGadget GtkBoxGadget;
+typedef struct _GtkBoxGadgetClass GtkBoxGadgetClass;
+
+struct _GtkBoxGadget
+{
+ GtkCssGadget parent;
+};
+
+struct _GtkBoxGadgetClass
+{
+ GtkCssGadgetClass parent_class;
+};
+
+GType gtk_box_gadget_get_type (void) G_GNUC_CONST;
+
+GtkCssGadget * gtk_box_gadget_new (const char *name,
+ GtkWidget *owner,
+ GtkCssGadget *parent,
+ GtkCssGadget *next_sibling);
+GtkCssGadget * gtk_box_gadget_new_for_node (GtkCssNode *node,
+ GtkWidget *owner);
+
+void gtk_box_gadget_set_orientation (GtkBoxGadget *gadget,
+ GtkOrientation orientation);
+
+void gtk_box_gadget_insert_widget (GtkBoxGadget *gadget,
+ int pos,
+ GtkWidget *widget);
+void gtk_box_gadget_remove_widget (GtkBoxGadget *gadget,
+ GtkWidget *widget);
+void gtk_box_gadget_insert_gadget (GtkBoxGadget *gadget,
+ int pos,
+ GtkCssGadget *cssgadget,
+ gboolean hexpand,
+ gboolean vexpand);
+void gtk_box_gadget_remove_gadget (GtkBoxGadget *gadget,
+ GtkCssGadget *cssgadget);
+
+G_END_DECLS
+
+#endif /* __GTK_BOX_GADGET_PRIVATE_H__ */
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index 38dab30..727f221 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -43,6 +43,7 @@
#include "gtkbuildable.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetpath.h"
+#include "gtkboxgadgetprivate.h"
#include "gtkcsscustomgadgetprivate.h"
#include "gtkcssstylepropertyprivate.h"
#include "gtksizerequest.h"
@@ -521,26 +522,6 @@ static gboolean gtk_notebook_draw_stack (GtkCssGadget *gadget,
int width,
int height,
gpointer data);
-static void gtk_notebook_measure_contents (GtkCssGadget *gadget,
- GtkOrientation orientation,
- gint for_size,
- gint *minimum,
- gint *natural,
- gint *minimum_baseline,
- gint *natural_baseline,
- gpointer data);
-static void gtk_notebook_allocate_contents (GtkCssGadget *gadget,
- const GtkAllocation *allocation,
- int baseline,
- GtkAllocation *out_clip,
- gpointer data);
-static gboolean gtk_notebook_draw_contents (GtkCssGadget *gadget,
- cairo_t *cr,
- int x,
- int y,
- int width,
- int height,
- gpointer data);
/*** GtkNotebook Private Functions ***/
static void gtk_notebook_redraw_tabs (GtkNotebook *notebook);
@@ -603,6 +584,8 @@ static void gtk_notebook_menu_label_unparent (GtkWidget *widget,
static void gtk_notebook_menu_detacher (GtkWidget *widget,
GtkMenu *menu);
+static void gtk_notebook_update_tab_pos (GtkNotebook *notebook);
+
/*** GtkNotebook Private Setters ***/
static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
gboolean overload,
@@ -1350,14 +1333,10 @@ gtk_notebook_init (GtkNotebook *notebook)
gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
widget_node = gtk_widget_get_css_node (GTK_WIDGET (notebook));
- priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
- GTK_WIDGET (notebook),
- gtk_notebook_measure_contents,
- gtk_notebook_allocate_contents,
- gtk_notebook_draw_contents,
- NULL,
- NULL);
+ priv->gadget = gtk_box_gadget_new_for_node (widget_node,
+ GTK_WIDGET (notebook));
gtk_css_gadget_add_class (priv->gadget, GTK_STYLE_CLASS_FRAME);
+ gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
priv->stack_gadget = gtk_css_custom_gadget_new ("stack",
GTK_WIDGET (notebook),
@@ -1369,6 +1348,7 @@ gtk_notebook_init (GtkNotebook *notebook)
NULL,
NULL);
gtk_css_gadget_set_state (priv->stack_gadget, gtk_css_node_get_state (widget_node));
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->stack_gadget, TRUE, TRUE);
priv->header_gadget = gtk_css_custom_gadget_new ("header",
GTK_WIDGET (notebook),
@@ -1381,6 +1361,8 @@ gtk_notebook_init (GtkNotebook *notebook)
NULL);
gtk_css_gadget_add_class (priv->header_gadget, GTK_STYLE_CLASS_TOP);
gtk_css_gadget_set_state (priv->header_gadget, gtk_css_node_get_state (widget_node));
+ gtk_css_gadget_set_visible (priv->header_gadget, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
priv->tabs_node = gtk_css_node_new ();
gtk_css_node_set_name (priv->tabs_node, I_("tabs"));
@@ -1995,7 +1977,7 @@ gtk_notebook_realize (GtkWidget *widget)
gtk_widget_set_realized (widget, TRUE);
- gtk_notebook_get_event_window_position (notebook, &event_window_pos);
+ gtk_css_gadget_get_border_allocation (priv->header_gadget, &event_window_pos, NULL);
window = gtk_widget_get_parent_window (widget);
gtk_widget_set_window (widget, window);
@@ -2280,115 +2262,6 @@ gtk_notebook_measure_stack (GtkCssGadget *gadget,
}
}
-static GtkOrientation
-get_orientation_from_tab_pos (GtkNotebook *notebook)
-{
- GtkPositionType tab_pos = notebook->priv->tab_pos;
-
- if (tab_pos == GTK_POS_LEFT || tab_pos == GTK_POS_RIGHT)
- return GTK_ORIENTATION_HORIZONTAL;
- else
- return GTK_ORIENTATION_VERTICAL;
-}
-
-static void
-gtk_notebook_distribute_content_size (GtkNotebook *notebook,
- gint size,
- gint *header_size,
- gint *stack_size)
-{
- GtkNotebookPrivate *priv = notebook->priv;
- GtkOrientation orientation = get_orientation_from_tab_pos (notebook);
- GtkRequestedSize request[2];
-
- if (size < 0)
- {
- *header_size = -1;
- *stack_size = -1;
- return;
- }
-
- gtk_css_gadget_get_preferred_size (priv->header_gadget,
- orientation,
- -1,
- &request[0].minimum_size, &request[0].natural_size,
- NULL, NULL);
- gtk_css_gadget_get_preferred_size (priv->stack_gadget,
- orientation,
- -1,
- &request[1].minimum_size, &request[1].natural_size,
- NULL, NULL);
-
- size = gtk_distribute_natural_allocation (size - request[0].minimum_size - request[1].minimum_size,
- G_N_ELEMENTS (request),
- request);
-
- *header_size = request[0].minimum_size;
- *stack_size = request[1].minimum_size + size;
-}
-
-static void
-gtk_notebook_measure_contents (GtkCssGadget *gadget,
- GtkOrientation orientation,
- gint size,
- gint *minimum,
- gint *natural,
- gint *minimum_baseline,
- gint *natural_baseline,
- gpointer unused)
-{
- GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
- GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkNotebookPrivate *priv = notebook->priv;
- gint stack_min, stack_nat, header_min, header_nat;
-
- if (!priv->show_tabs || !gtk_notebook_has_current_page (notebook))
- {
- gtk_css_gadget_get_preferred_size (priv->stack_gadget,
- orientation,
- size,
- minimum, natural,
- NULL, NULL);
-
- }
- else if (orientation == get_orientation_from_tab_pos (notebook))
- {
- gtk_css_gadget_get_preferred_size (priv->header_gadget,
- orientation,
- size,
- &header_min, &header_nat,
- NULL, NULL);
- gtk_css_gadget_get_preferred_size (priv->stack_gadget,
- orientation,
- size,
- &stack_min, &stack_nat,
- NULL, NULL);
-
- *minimum = header_min + stack_min;
- *natural = header_nat + stack_nat;
- }
- else
- {
- gint header_size, stack_size;
-
- gtk_notebook_distribute_content_size (notebook, size, &header_size, &stack_size);
-
- gtk_css_gadget_get_preferred_size (priv->header_gadget,
- orientation,
- header_size,
- &header_min, &header_nat,
- NULL, NULL);
- gtk_css_gadget_get_preferred_size (priv->stack_gadget,
- orientation,
- stack_size,
- &stack_min, &stack_nat,
- NULL, NULL);
-
- *minimum = MAX (header_min, stack_min);
- *natural = MAX (header_nat, stack_nat);
- }
-}
-
static void
gtk_notebook_get_preferred_width_for_height (GtkWidget *widget,
gint height,
@@ -2518,106 +2391,39 @@ gtk_notebook_allocate_stack (GtkCssGadget *gadget,
}
static void
-gtk_notebook_allocate_contents (GtkCssGadget *gadget,
- const GtkAllocation *allocation,
- int baseline,
- GtkAllocation *out_clip,
- gpointer unused)
+gtk_notebook_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
- GtkAllocation stack_allocation, header_allocation;
-
- stack_allocation = *allocation;
-
- if (!priv->show_tabs || !gtk_notebook_has_current_page (notebook))
- {
- gtk_css_gadget_allocate (priv->stack_gadget, &stack_allocation, -1, out_clip);
- if (gtk_widget_get_realized (widget))
- gdk_window_hide (priv->event_window);
- }
- else
- {
- GtkAllocation stack_clip, header_clip;
-
- header_allocation = stack_allocation;
-
- switch (get_effective_tab_pos (notebook))
- {
- case GTK_POS_TOP:
- gtk_notebook_distribute_content_size (notebook,
- stack_allocation.height,
- &header_allocation.height,
- &stack_allocation.height);
- stack_allocation.y += header_allocation.height;
- break;
-
- case GTK_POS_BOTTOM:
- gtk_notebook_distribute_content_size (notebook,
- stack_allocation.height,
- &header_allocation.height,
- &stack_allocation.height);
- header_allocation.y += stack_allocation.height;
- break;
-
- case GTK_POS_LEFT:
- gtk_notebook_distribute_content_size (notebook,
- stack_allocation.width,
- &header_allocation.width,
- &stack_allocation.width);
- stack_allocation.x += header_allocation.width;
- break;
+ GtkAllocation clip;
- case GTK_POS_RIGHT:
- gtk_notebook_distribute_content_size (notebook,
- stack_allocation.width,
- &header_allocation.width,
- &stack_allocation.width);
- header_allocation.x += stack_allocation.width;
- break;
+ gtk_widget_set_allocation (widget, allocation);
- default:
- g_assert_not_reached ();
- break;
- }
+ gtk_css_gadget_allocate (priv->gadget,
+ allocation,
+ gtk_widget_get_allocated_baseline (widget),
+ &clip);
- gtk_css_gadget_allocate (priv->header_gadget, &header_allocation, -1, &header_clip);
- gtk_css_gadget_allocate (priv->stack_gadget, &stack_allocation, -1, &stack_clip);
+ gtk_widget_set_clip (widget, &clip);
- gdk_rectangle_union (&stack_clip, &header_clip, out_clip);
+ if (gtk_widget_get_realized (widget))
+ {
+ GdkRectangle position;
- if (gtk_widget_get_realized (widget))
+ if (gtk_notebook_get_event_window_position (notebook, &position))
{
- GtkAllocation position;
- gtk_css_gadget_get_border_allocation (priv->header_gadget, &position, NULL);
gdk_window_move_resize (priv->event_window,
position.x, position.y,
position.width, position.height);
if (gtk_widget_get_mapped (GTK_WIDGET (notebook)))
gdk_window_show_unraised (priv->event_window);
}
+ else
+ gdk_window_hide (priv->event_window);
}
}
-static void
-gtk_notebook_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkNotebookPrivate *priv = notebook->priv;
- 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_notebook_draw_stack (GtkCssGadget *gadget,
cairo_t *cr,
@@ -2640,40 +2446,6 @@ gtk_notebook_draw_stack (GtkCssGadget *gadget,
}
static gboolean
-gtk_notebook_draw_contents (GtkCssGadget *gadget,
- cairo_t *cr,
- int x,
- int y,
- int width,
- int height,
- gpointer unused)
-{
- GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
- GtkNotebook *notebook = GTK_NOTEBOOK (widget);
- GtkNotebookPrivate *priv = notebook->priv;
- GdkWindow *window;
-
- window = gtk_widget_get_window (widget);
- if (gtk_cairo_should_draw_window (cr, window))
- {
- gtk_css_gadget_draw (priv->stack_gadget, cr);
-
- if (priv->show_tabs && gtk_notebook_has_current_page (notebook))
- gtk_css_gadget_draw (priv->header_gadget, cr);
- }
-
- if (gtk_notebook_has_current_page (notebook) && priv->operation == DRAG_OPERATION_REORDER &&
- gtk_cairo_should_draw_window (cr, priv->drag_window))
- {
- gtk_notebook_draw_tab (notebook,
- priv->cur_page,
- cr);
- }
-
- return FALSE;
-}
-
-static gboolean
gtk_notebook_draw (GtkWidget *widget,
cairo_t *cr)
{
@@ -4800,19 +4572,22 @@ page_visible_cb (GtkWidget *child,
gtk_widget_set_visible (parent, gtk_widget_get_visible (child));
}
- if (priv->cur_page == page &&
- !gtk_widget_get_visible (child))
+ if (priv->cur_page == page)
{
- list = g_list_find (priv->children, priv->cur_page);
- if (list)
+ if (!gtk_widget_get_visible (child))
{
- next = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
- if (!next)
- next = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
- }
+ list = g_list_find (priv->children, priv->cur_page);
+ if (list)
+ {
+ next = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
+ if (!next)
+ next = gtk_notebook_search_page (notebook, list, STEP_PREV, TRUE);
+ }
- if (next)
- gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next));
+ if (next)
+ gtk_notebook_switch_page (notebook, GTK_NOTEBOOK_PAGE (next));
+ }
+ gtk_css_gadget_set_visible (priv->header_gadget, priv->show_tabs && gtk_notebook_has_current_page
(notebook));
}
if (!gtk_notebook_has_current_page (notebook) && gtk_widget_get_visible (child))
@@ -6632,6 +6407,7 @@ gtk_notebook_real_switch_page (GtkNotebook *notebook,
priv->cur_page = page;
gtk_css_node_set_state (page->cssnode,
gtk_css_node_get_state (page->cssnode) | GTK_STATE_FLAG_ACTIVE);
+ gtk_css_gadget_set_visible (priv->header_gadget, priv->show_tabs);
if (!priv->focus_tab ||
priv->focus_tab->data != (gpointer) priv->cur_page)
@@ -7418,11 +7194,14 @@ gtk_notebook_set_show_tabs (GtkNotebook *notebook,
else
gtk_widget_hide (page->tab_label);
}
+ gtk_css_gadget_set_visible (priv->header_gadget,
+ gtk_notebook_has_current_page (notebook));
}
else
{
gtk_widget_set_can_focus (GTK_WIDGET (notebook), TRUE);
gtk_notebook_update_labels (notebook);
+ gtk_css_gadget_set_visible (priv->header_gadget, FALSE);
}
for (i = 0; i < N_ACTION_WIDGETS; i++)
@@ -7431,6 +7210,7 @@ gtk_notebook_set_show_tabs (GtkNotebook *notebook,
gtk_widget_set_child_visible (priv->action_widget[i], show_tabs);
}
+ gtk_notebook_update_tab_pos (notebook);
gtk_widget_reset_style (GTK_WIDGET (notebook));
gtk_widget_queue_resize (GTK_WIDGET (notebook));
@@ -7476,6 +7256,34 @@ gtk_notebook_update_tab_pos (GtkNotebook *notebook)
else
gtk_css_gadget_remove_class (priv->header_gadget, tab_pos_names[i]);
}
+
+ gtk_box_gadget_remove_gadget (GTK_BOX_GADGET (priv->gadget), priv->header_gadget);
+ switch (tab_pos)
+ {
+ case GTK_POS_TOP:
+ if (priv->show_tabs)
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
+ break;
+
+ case GTK_POS_BOTTOM:
+ if (priv->show_tabs)
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
+ break;
+
+ case GTK_POS_LEFT:
+ if (priv->show_tabs)
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
+ break;
+
+ case GTK_POS_RIGHT:
+ if (priv->show_tabs)
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
+ break;
+ }
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]