[gtk+/native-layout] Implemented GtkSizeRequest interface on GtkExpander
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/native-layout] Implemented GtkSizeRequest interface on GtkExpander
- Date: Sat, 26 Jun 2010 17:25:05 +0000 (UTC)
commit 89a8f35b28773ffeea12e374cd653149f29087a1
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sat Jun 26 13:20:02 2010 -0400
Implemented GtkSizeRequest interface on GtkExpander
In this particular case the label widget is never allocated
anything more than its natural width or its minimum height for
that width (thus prioritizing the content area to the label height).
We could allocate to the full available allocation but
a.) focus would be drawn around the complete allocation
instead of only the label
b.) labels in expanders will need explicit alignments
gtk/gtkexpander.c | 397 ++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 289 insertions(+), 108 deletions(-)
---
diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c
index b7a61f7..04fd2ff 100644
--- a/gtk/gtkexpander.c
+++ b/gtk/gtkexpander.c
@@ -27,6 +27,7 @@
#include "gtklabel.h"
#include "gtkbuildable.h"
+#include "gtksizerequest.h"
#include "gtkcontainer.h"
#include "gtkmarshalers.h"
#include "gtkmain.h"
@@ -82,8 +83,6 @@ static void gtk_expander_destroy (GtkObject *object);
static void gtk_expander_realize (GtkWidget *widget);
static void gtk_expander_unrealize (GtkWidget *widget);
-static void gtk_expander_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
static void gtk_expander_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_expander_map (GtkWidget *widget);
@@ -134,9 +133,29 @@ static void gtk_expander_buildable_add_child (GtkBuildable *buildable,
GObject *child,
const gchar *type);
+
+/* GtkSizeRequest */
+static void gtk_expander_size_request_init (GtkSizeRequestIface *iface);
+static void gtk_expander_get_width (GtkSizeRequest *widget,
+ gint *minimum_size,
+ gint *natural_size);
+static void gtk_expander_get_height (GtkSizeRequest *widget,
+ gint *minimum_size,
+ gint *natural_size);
+static void gtk_expander_get_height_for_width (GtkSizeRequest *layout,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
+static void gtk_expander_get_width_for_height (GtkSizeRequest *layout,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height);
+
G_DEFINE_TYPE_WITH_CODE (GtkExpander, gtk_expander, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
- gtk_expander_buildable_init))
+ gtk_expander_buildable_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
+ gtk_expander_size_request_init))
static void
gtk_expander_class_init (GtkExpanderClass *klass)
@@ -158,7 +177,6 @@ gtk_expander_class_init (GtkExpanderClass *klass)
widget_class->realize = gtk_expander_realize;
widget_class->unrealize = gtk_expander_unrealize;
- widget_class->size_request = gtk_expander_size_request;
widget_class->size_allocate = gtk_expander_size_allocate;
widget_class->map = gtk_expander_map;
widget_class->unmap = gtk_expander_unmap;
@@ -459,67 +477,6 @@ gtk_expander_unrealize (GtkWidget *widget)
}
static void
-gtk_expander_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- GtkExpander *expander;
- GtkBin *bin;
- GtkExpanderPrivate *priv;
- gint border_width;
- gint expander_size;
- gint expander_spacing;
- gboolean interior_focus;
- gint focus_width;
- gint focus_pad;
-
- bin = GTK_BIN (widget);
- expander = GTK_EXPANDER (widget);
- priv = expander->priv;
-
- border_width = GTK_CONTAINER (widget)->border_width;
-
- gtk_widget_style_get (widget,
- "interior-focus", &interior_focus,
- "focus-line-width", &focus_width,
- "focus-padding", &focus_pad,
- "expander-size", &expander_size,
- "expander-spacing", &expander_spacing,
- NULL);
-
- requisition->width = expander_size + 2 * expander_spacing +
- 2 * focus_width + 2 * focus_pad;
- requisition->height = interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
-
- if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
- {
- GtkRequisition label_requisition;
-
- gtk_widget_size_request (priv->label_widget, &label_requisition);
-
- requisition->width += label_requisition.width;
- requisition->height += label_requisition.height;
- }
-
- requisition->height = MAX (expander_size + 2 * expander_spacing, requisition->height);
-
- if (!interior_focus)
- requisition->height += 2 * focus_width + 2 * focus_pad;
-
- if (bin->child && GTK_WIDGET_CHILD_VISIBLE (bin->child))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (bin->child, &child_requisition);
-
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height + priv->spacing;
- }
-
- requisition->width += 2 * border_width;
- requisition->height += 2 * border_width;
-}
-
-static void
get_expander_bounds (GtkExpander *expander,
GdkRectangle *rect)
{
@@ -590,9 +547,8 @@ gtk_expander_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkExpander *expander;
- GtkBin *bin;
+ GtkWidget *child;
GtkExpanderPrivate *priv;
- GtkRequisition child_requisition;
gboolean child_visible = FALSE;
gint border_width;
gint expander_size;
@@ -600,14 +556,18 @@ gtk_expander_size_allocate (GtkWidget *widget,
gboolean interior_focus;
gint focus_width;
gint focus_pad;
- gint label_height;
+ gint label_height, top_min_height;
+ gint label_xpad, label_xoffset;
+ gint child_ypad, child_yoffset;
expander = GTK_EXPANDER (widget);
- bin = GTK_BIN (widget);
- priv = expander->priv;
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ priv = expander->priv;
border_width = GTK_CONTAINER (widget)->border_width;
+ widget->allocation = *allocation;
+
gtk_widget_style_get (widget,
"interior-focus", &interior_focus,
"focus-line-width", &focus_width,
@@ -616,45 +576,45 @@ gtk_expander_size_allocate (GtkWidget *widget,
"expander-spacing", &expander_spacing,
NULL);
- child_requisition.width = 0;
- child_requisition.height = 0;
- if (bin->child && GTK_WIDGET_CHILD_VISIBLE (bin->child))
- {
- child_visible = TRUE;
- gtk_widget_get_child_requisition (bin->child, &child_requisition);
- }
- widget->allocation = *allocation;
+ /* Calculate some offsets/padding first */
+ label_xoffset = border_width + expander_size + focus_width + 2 * expander_spacing + focus_pad;
+ label_xpad = 2 * border_width + expander_size + 2 * focus_width + 2 * expander_spacing + 2 * focus_pad;
+
+ child_yoffset = border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
+ child_ypad = 2 * border_width + priv->spacing + (interior_focus ? 0 : 2 * focus_width + 2 * focus_pad);
+ top_min_height = 2 * expander_spacing + expander_size;
+
+ child_visible = (child && GTK_WIDGET_CHILD_VISIBLE (child));
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
{
GtkAllocation label_allocation;
- GtkRequisition label_requisition;
+ gint natural_label_width;
gboolean ltr;
- gtk_widget_get_child_requisition (priv->label_widget, &label_requisition);
+ gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget), NULL, &natural_label_width);
+
+ label_allocation.width = MIN (natural_label_width, allocation->width - label_xpad);
+ label_allocation.width = MAX (label_allocation.width, 1);
+
+ /* We distribute the minimum height to the label widget and prioritize
+ * the child widget giving it the remaining height */
+ gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
+ label_allocation.width, &label_height, NULL);
ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
if (ltr)
- label_allocation.x = (widget->allocation.x +
- border_width + focus_width + focus_pad +
- expander_size + 2 * expander_spacing);
+ label_allocation.x =
+ widget->allocation.x + label_xoffset;
else
- label_allocation.x = (widget->allocation.x + widget->allocation.width -
- (label_requisition.width +
- border_width + focus_width + focus_pad +
- expander_size + 2 * expander_spacing));
+ label_allocation.x =
+ widget->allocation.x + widget->allocation.width -
+ (label_allocation.width + label_xoffset);
label_allocation.y = widget->allocation.y + border_width + focus_width + focus_pad;
-
- label_allocation.width = MIN (label_requisition.width,
- allocation->width - 2 * border_width -
- expander_size - 2 * expander_spacing -
- 2 * focus_width - 2 * focus_pad);
- label_allocation.width = MAX (label_allocation.width, 1);
-
- label_allocation.height = MIN (label_requisition.height,
+ label_allocation.height = MIN (label_height,
allocation->height - 2 * border_width -
2 * focus_width - 2 * focus_pad -
(child_visible ? priv->spacing : 0));
@@ -687,24 +647,17 @@ gtk_expander_size_allocate (GtkWidget *widget,
GtkAllocation child_allocation;
gint top_height;
- top_height = MAX (2 * expander_spacing + expander_size,
- label_height +
- (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
+ top_height = MAX (top_min_height,
+ label_height + (interior_focus ? 2 * focus_width + 2 * focus_pad : 0));
child_allocation.x = widget->allocation.x + border_width;
- child_allocation.y = widget->allocation.y + border_width + top_height + priv->spacing;
-
- if (!interior_focus)
- child_allocation.y += 2 * focus_width + 2 * focus_pad;
+ child_allocation.y = widget->allocation.y + top_height + child_yoffset;
child_allocation.width = MAX (allocation->width - 2 * border_width, 1);
-
- child_allocation.height = allocation->height - top_height -
- 2 * border_width - priv->spacing -
- (!interior_focus ? 2 * focus_width + 2 * focus_pad : 0);
+ child_allocation.height = allocation->height - top_height - child_ypad;
child_allocation.height = MAX (child_allocation.height, 1);
- gtk_widget_size_allocate (bin->child, &child_allocation);
+ gtk_widget_size_allocate (child, &child_allocation);
}
}
@@ -849,8 +802,9 @@ gtk_expander_paint_focus (GtkExpander *expander,
{
if (gtk_widget_get_visible (priv->label_widget))
{
- GtkAllocation label_allocation = priv->label_widget->allocation;
+ GtkAllocation label_allocation;
+ gtk_widget_get_allocation (priv->label_widget, &label_allocation);
width = label_allocation.width;
height = label_allocation.height;
}
@@ -1270,6 +1224,233 @@ gtk_expander_activate (GtkExpander *expander)
gtk_expander_set_expanded (expander, !expander->priv->expanded);
}
+
+static void
+gtk_expander_size_request_init (GtkSizeRequestIface *iface)
+{
+ iface->get_width = gtk_expander_get_width;
+ iface->get_height = gtk_expander_get_height;
+ iface->get_height_for_width = gtk_expander_get_height_for_width;
+ iface->get_width_for_height = gtk_expander_get_width_for_height;
+}
+
+static void
+gtk_expander_get_width (GtkSizeRequest *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkExpander *expander;
+ GtkWidget *child;
+ GtkExpanderPrivate *priv;
+ gint border_width;
+ gint expander_size;
+ gint expander_spacing;
+ gboolean interior_focus;
+ gint focus_width;
+ gint focus_pad;
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ expander = GTK_EXPANDER (widget);
+ priv = expander->priv;
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ gtk_widget_style_get (GTK_WIDGET (widget),
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ "expander-size", &expander_size,
+ "expander-spacing", &expander_spacing,
+ NULL);
+
+ *minimum_size = *natural_size =
+ expander_size + 2 * expander_spacing +
+ 2 * focus_width + 2 * focus_pad;
+
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
+ {
+ gint label_min, label_nat;
+
+ gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget),
+ &label_min, &label_nat);
+
+ *minimum_size += label_min;
+ *natural_size += label_nat;
+ }
+
+ if (child && GTK_WIDGET_CHILD_VISIBLE (child))
+ {
+ gint child_min, child_nat;
+
+ gtk_size_request_get_width (GTK_SIZE_REQUEST (child),
+ &child_min, &child_nat);
+
+ *minimum_size = MAX (*minimum_size, child_min);
+ *natural_size = MAX (*natural_size, child_nat);
+
+ }
+
+ *minimum_size += 2 * border_width;
+ *natural_size += 2 * border_width;
+}
+
+static void
+gtk_expander_get_height (GtkSizeRequest *widget,
+ gint *minimum_size,
+ gint *natural_size)
+{
+ GtkExpander *expander;
+ GtkWidget *child;
+ GtkExpanderPrivate *priv;
+ gint border_width;
+ gint expander_size;
+ gint expander_spacing;
+ gboolean interior_focus;
+ gint focus_width;
+ gint focus_pad;
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ expander = GTK_EXPANDER (widget);
+ priv = expander->priv;
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ gtk_widget_style_get (GTK_WIDGET (widget),
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ "expander-size", &expander_size,
+ "expander-spacing", &expander_spacing,
+ NULL);
+
+ *minimum_size = *natural_size =
+ interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
+
+
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
+ {
+ gint label_min, label_nat;
+
+ gtk_size_request_get_height (GTK_SIZE_REQUEST (priv->label_widget),
+ &label_min, &label_nat);
+
+ *minimum_size += label_min;
+ *natural_size += label_nat;
+ }
+
+ *minimum_size = MAX (*minimum_size, expander_size + 2 * expander_spacing);
+ *natural_size = MAX (*natural_size, *minimum_size);
+
+ if (!interior_focus)
+ {
+ gint extra = 2 * focus_width + 2 * focus_pad;
+ *minimum_size += extra;
+ *natural_size += extra;
+ }
+
+ if (child && GTK_WIDGET_CHILD_VISIBLE (child))
+ {
+ gint child_min, child_nat;
+
+ gtk_size_request_get_height (GTK_SIZE_REQUEST (child),
+ &child_min, &child_nat);
+
+ *minimum_size += child_min + priv->spacing;
+ *natural_size += child_nat + priv->spacing;
+
+ }
+
+ *minimum_size += 2 * border_width;
+ *natural_size += 2 * border_width;
+}
+
+static void
+gtk_expander_get_height_for_width (GtkSizeRequest *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height)
+{
+ GtkExpander *expander;
+ GtkWidget *child;
+ GtkExpanderPrivate *priv;
+ gint border_width;
+ gint expander_size;
+ gint expander_spacing;
+ gboolean interior_focus;
+ gint focus_width;
+ gint focus_pad;
+ gint label_xpad;
+
+ child = gtk_bin_get_child (GTK_BIN (widget));
+ expander = GTK_EXPANDER (widget);
+ priv = expander->priv;
+
+ border_width = GTK_CONTAINER (widget)->border_width;
+
+ gtk_widget_style_get (GTK_WIDGET (widget),
+ "interior-focus", &interior_focus,
+ "focus-line-width", &focus_width,
+ "focus-padding", &focus_pad,
+ "expander-size", &expander_size,
+ "expander-spacing", &expander_spacing,
+ NULL);
+
+ label_xpad = 2 * border_width + expander_size + 2 * expander_spacing - 2 * focus_width + 2 * focus_pad;
+
+ *minimum_height = *natural_height =
+ interior_focus ? (2 * focus_width + 2 * focus_pad) : 0;
+
+
+ if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
+ {
+ gint label_min, label_nat;
+
+ gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
+ MAX (width - label_xpad, 1),
+ &label_min, &label_nat);
+
+ *minimum_height += label_min;
+ *natural_height += label_nat;
+ }
+
+ *minimum_height = MAX (*minimum_height, expander_size + 2 * expander_spacing);
+ *natural_height = MAX (*natural_height, *minimum_height);
+
+ if (!interior_focus)
+ {
+ gint extra = 2 * focus_width + 2 * focus_pad;
+ *minimum_height += extra;
+ *natural_height += extra;
+ }
+
+ if (child && GTK_WIDGET_CHILD_VISIBLE (child))
+ {
+ gint child_min, child_nat;
+
+ gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (child),
+ MAX (width - 2 * border_width, 1),
+ &child_min, &child_nat);
+
+ *minimum_height += child_min + priv->spacing;
+ *natural_height += child_nat + priv->spacing;
+ }
+
+ *minimum_height += 2 * border_width;
+ *natural_height += 2 * border_width;
+}
+
+static void
+gtk_expander_get_width_for_height (GtkSizeRequest *widget,
+ gint height,
+ gint *minimum_width,
+ gint *natural_width)
+{
+ gtk_size_request_get_width (widget, minimum_width, natural_width);
+ //GTK_SIZE_REQUEST_GET_IFACE (widget)->get_width (widget, minimum_width, natural_width);
+}
+
+
+
/**
* gtk_expander_new:
* @label: the text of the label
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]