[gtk+] Make button boxes semi-homogeneous
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Make button boxes semi-homogeneous
- Date: Sun, 22 Aug 2010 04:34:37 +0000 (UTC)
commit fe1a39b1f2358af206b6cd8107360427cca21bb5
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Aug 22 00:30:31 2010 -0400
Make button boxes semi-homogeneous
If a child is too large (> 1.5 the average), let it have its own
size. The old behaviour of fully homogeneous button boxes can still
be had by setting the homogeneous property to TRUE. Bug 84188.
gtk/gtkbbox.c | 314 +++++++++++++++++++++++++++++++++++---------------------
1 files changed, 196 insertions(+), 118 deletions(-)
---
diff --git a/gtk/gtkbbox.c b/gtk/gtkbbox.c
index 655ba9a..aae0f74 100644
--- a/gtk/gtkbbox.c
+++ b/gtk/gtkbbox.c
@@ -394,14 +394,15 @@ gtk_button_box_set_child_secondary (GtkButtonBox *widget,
}
/* Ask children how much space they require and round up
- to match minimum size and internal padding.
- Returns the size each single child should have. */
+ * to match minimum size and internal padding.
+ * Returns the size each single child should have.
+ */
static void
-_gtk_button_box_child_requisition (GtkWidget *widget,
- int *nvis_children,
- int *nvis_secondaries,
- int *width,
- int *height)
+gtk_button_box_child_requisition (GtkWidget *widget,
+ gint *nvis_children,
+ gint *nvis_secondaries,
+ gint **widths,
+ gint **heights)
{
GtkButtonBoxPriv *priv;
GtkButtonBox *bbox;
@@ -410,6 +411,7 @@ _gtk_button_box_child_requisition (GtkWidget *widget,
gint nsecondaries;
gint needed_width;
gint needed_height;
+ gint avg_w, avg_h;
GtkRequisition child_requisition;
gint ipad_w;
gint ipad_h;
@@ -417,12 +419,16 @@ _gtk_button_box_child_requisition (GtkWidget *widget,
gint child_min_height;
gint ipad_x;
gint ipad_y;
+ gboolean homogeneous;
+ gint i;
g_return_if_fail (GTK_IS_BUTTON_BOX (widget));
bbox = GTK_BUTTON_BOX (widget);
priv = bbox->priv;
+ homogeneous = gtk_box_get_homogeneous (GTK_BOX (widget));
+
gtk_widget_style_get (widget,
"child-min-width", &child_min_width,
"child-min-height", &child_min_height,
@@ -437,41 +443,92 @@ _gtk_button_box_child_requisition (GtkWidget *widget,
needed_height = child_min_height;
ipad_w = ipad_x * 2;
ipad_h = ipad_y * 2;
-
+
+ avg_w = avg_h = 0;
while (children)
{
GtkWidget *child;
- gboolean is_secondary;
child = children->data;
children = children->next;
- is_secondary = gtk_button_box_get_child_secondary (bbox, child);
-
if (gtk_widget_get_visible (child))
{
nchildren += 1;
gtk_widget_size_request (child, &child_requisition);
+ avg_w += child_requisition.width + ipad_w;
+ avg_h += child_requisition.height + ipad_h;
+ }
+ }
+ avg_w /= nchildren;
+ avg_h /= nchildren;
+
+ *widths = g_new (gint, nchildren);
+ *heights = g_new (gint, nchildren);
+
+ i = 0;
+ children = list;
+ while (children)
+ {
+ GtkWidget *child;
+ gboolean is_secondary;
- if (child_requisition.width + ipad_w > needed_width)
- needed_width = child_requisition.width + ipad_w;
- if (child_requisition.height + ipad_h > needed_height)
- needed_height = child_requisition.height + ipad_h;
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_get_visible (child))
+ {
+ is_secondary = gtk_button_box_get_child_secondary (bbox, child);
if (is_secondary)
nsecondaries++;
+
+ gtk_widget_get_child_requisition (child, &child_requisition);
+
+ if (homogeneous ||
+ (child_requisition.width + ipad_w < avg_w * 1.5)) /* &&
+ child_requisition.width + ipad_w > avg_w / 1.5)) */
+ {
+ (*widths)[i] = -1;
+ if (child_requisition.width + ipad_w > needed_width)
+ needed_width = child_requisition.width + ipad_w;
+ }
+ else
+ {
+ (*widths)[i] = child_requisition.width + ipad_w;
+ }
+
+ if (homogeneous ||
+ (child_requisition.height + ipad_h < avg_h * 1.5)) /* &&
+ child_requisition.height + ipad_h > avg_h / 1.5)) */
+ {
+ (*heights)[i] = -1;
+ if (child_requisition.height + ipad_h > needed_height)
+ needed_height = child_requisition.height + ipad_h;
+ }
+ else
+ {
+ (*heights)[i] = child_requisition.height + ipad_h;
+ }
+
+ i++;
}
}
g_list_free (list);
+ for (i = 0; i < nchildren; i++)
+ {
+ if ((*widths)[i] == -1)
+ (*widths)[i] = needed_width;
+ if ((*heights)[i] == -1)
+ (*heights)[i] = needed_height;
+ }
+
if (nvis_children)
*nvis_children = nchildren;
+
if (nvis_secondaries)
*nvis_secondaries = nsecondaries;
- if (width)
- *width = needed_width;
- if (height)
- *height = needed_height;
}
static void
@@ -479,27 +536,45 @@ gtk_button_box_size_request (GtkWidget *widget,
GtkRequisition *requisition)
{
GtkButtonBoxPriv *priv;
- GtkBox *box;
GtkButtonBox *bbox;
gint nvis_children;
- gint child_width;
- gint child_height;
+ gint max_size;
+ gint total_size;
gint spacing;
guint border_width;
GtkOrientation orientation;
+ gint *widths;
+ gint *heights;
+ gint i;
- box = GTK_BOX (widget);
bbox = GTK_BUTTON_BOX (widget);
priv = bbox->priv;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
- spacing = gtk_box_get_spacing (box);
+ spacing = gtk_box_get_spacing (GTK_BOX (widget));
- _gtk_button_box_child_requisition (widget,
- &nvis_children,
- NULL,
- &child_width,
- &child_height);
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ NULL,
+ &widths, &heights);
+
+ max_size = 0;
+ total_size = 0;
+ for (i = 0; i < nvis_children; i++)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ total_size += widths[i];
+ max_size = MAX (max_size, heights[i]);
+ }
+ else
+ {
+ total_size += heights[i];
+ max_size = MAX (max_size, widths[i]);
+ }
+ }
+ g_free (widths);
+ g_free (heights);
if (nvis_children == 0)
{
@@ -512,11 +587,9 @@ gtk_button_box_size_request (GtkWidget *widget,
{
case GTK_BUTTONBOX_SPREAD:
if (orientation == GTK_ORIENTATION_HORIZONTAL)
- requisition->width =
- nvis_children*child_width + ((nvis_children+1)*spacing);
+ requisition->width = total_size + ((nvis_children + 1)*spacing);
else
- requisition->height =
- nvis_children*child_height + ((nvis_children+1)*spacing);
+ requisition->height = total_size + ((nvis_children + 1)*spacing);
break;
case GTK_BUTTONBOX_EDGE:
@@ -524,11 +597,9 @@ gtk_button_box_size_request (GtkWidget *widget,
case GTK_BUTTONBOX_END:
case GTK_BUTTONBOX_CENTER:
if (orientation == GTK_ORIENTATION_HORIZONTAL)
- requisition->width =
- nvis_children*child_width + ((nvis_children-1)*spacing);
+ requisition->width = total_size + ((nvis_children - 1)*spacing);
else
- requisition->height =
- nvis_children*child_height + ((nvis_children-1)*spacing);
+ requisition->height = total_size + ((nvis_children - 1)*spacing);
break;
default:
@@ -537,12 +608,12 @@ gtk_button_box_size_request (GtkWidget *widget,
}
if (orientation == GTK_ORIENTATION_HORIZONTAL)
- requisition->height = child_height;
+ requisition->height = max_size;
else
- requisition->width = child_width;
+ requisition->width = max_size;
}
- border_width = gtk_container_get_border_width (GTK_CONTAINER (box));
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
requisition->width += border_width * 2;
requisition->height += border_width * 2;
}
@@ -552,38 +623,74 @@ gtk_button_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkButtonBoxPriv *priv;
- GtkBox *base_box;
- GtkButtonBox *box;
+ GtkButtonBox *bbox;
GList *children, *list;
GtkAllocation child_allocation;
gint nvis_children;
+ gint n_primaries;
gint n_secondaries;
- gint child_width;
- gint child_height;
gint x = 0;
gint y = 0;
gint secondary_x = 0;
gint secondary_y = 0;
gint width = 0;
gint height = 0;
- gint childspace;
gint childspacing = 0;
gint spacing;
guint border_width;
GtkOrientation orientation;
+ gint ipad_x, ipad_y;
+ gint *widths;
+ gint *heights;
+ gint *sizes;
+ gint primary_size;
+ gint secondary_size;
+ gint total_size;
+ gint i;
- base_box = GTK_BOX (widget);
- box = GTK_BUTTON_BOX (widget);
- priv = box->priv;
+ bbox = GTK_BUTTON_BOX (widget);
+ priv = bbox->priv;
- border_width = gtk_container_get_border_width (GTK_CONTAINER (box));
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
- spacing = gtk_box_get_spacing (base_box);
- _gtk_button_box_child_requisition (widget,
- &nvis_children,
- &n_secondaries,
- &child_width,
- &child_height);
+ spacing = gtk_box_get_spacing (GTK_BOX (widget));
+ gtk_widget_style_get (widget,
+ "child-internal-pad-x", &ipad_x,
+ "child-internal-pad-y", &ipad_y,
+ NULL);
+ gtk_button_box_child_requisition (widget,
+ &nvis_children,
+ &n_secondaries,
+ &widths, &heights);
+
+ n_primaries = nvis_children - n_secondaries;
+ primary_size = 0;
+ secondary_size = 0;
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ sizes = widths;
+ else
+ sizes = heights;
+
+ i = 0;
+ list = children = _gtk_box_get_children (GTK_BOX (widget));
+ while (children)
+ {
+ GtkWidget *child;
+
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_get_visible (child))
+ {
+ if (gtk_button_box_get_child_secondary (bbox, child))
+ secondary_size += sizes[i];
+ else
+ primary_size += sizes[i];
+ i++;
+ }
+ }
+ total_size = primary_size + secondary_size;
+
widget->allocation = *allocation;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -597,19 +704,15 @@ gtk_button_box_size_allocate (GtkWidget *widget,
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- childspacing = (width - (nvis_children * child_width))
- / (nvis_children + 1);
+ childspacing = (width - total_size) / (nvis_children + 1);
x = allocation->x + border_width + childspacing;
- secondary_x = x + ((nvis_children - n_secondaries)
- * (child_width + childspacing));
+ secondary_x = x + primary_size + n_primaries * childspacing;
}
else
{
- childspacing = (height - (nvis_children * child_height))
- / (nvis_children + 1);
+ childspacing = (height - total_size) / (nvis_children + 1);
y = allocation->y + border_width + childspacing;
- secondary_y = y + ((nvis_children - n_secondaries)
- * (child_height + childspacing));
+ secondary_y = y + primary_size + n_primaries * childspacing;
}
break;
@@ -620,36 +723,32 @@ gtk_button_box_size_allocate (GtkWidget *widget,
{
if (nvis_children >= 2)
{
- childspacing = (width - (nvis_children * child_width))
- / (nvis_children - 1);
+ childspacing = (width - total_size) / (nvis_children - 1);
x = allocation->x + border_width;
- secondary_x = x + ((nvis_children - n_secondaries)
- * (child_width + childspacing));
+ secondary_x = x + primary_size + n_primaries * childspacing;
}
else
{
/* one or zero children, just center */
childspacing = width;
x = secondary_x = allocation->x
- + (allocation->width - child_width) / 2;
+ + (allocation->width - widths[0]) / 2;
}
}
else
{
if (nvis_children >= 2)
{
- childspacing = (height - (nvis_children*child_height))
- / (nvis_children-1);
+ childspacing = (height - total_size) / (nvis_children - 1);
y = allocation->y + border_width;
- secondary_y = y + ((nvis_children - n_secondaries)
- * (child_height + childspacing));
+ secondary_y = y + primary_size + n_primaries * childspacing;
}
else
{
/* one or zero children, just center */
childspacing = height;
y = secondary_y = allocation->y
- + (allocation->height - child_height) / 2;
+ + (allocation->height - heights[0]) / 2;
}
}
@@ -662,18 +761,14 @@ gtk_button_box_size_allocate (GtkWidget *widget,
childspacing = spacing;
x = allocation->x + border_width;
secondary_x = allocation->x + allocation->width
- - child_width * n_secondaries
- - spacing * (n_secondaries - 1)
- - border_width;
+ - secondary_size - spacing * (n_secondaries - 1) - border_width;
}
else
{
childspacing = spacing;
y = allocation->y + border_width;
secondary_y = allocation->y + allocation->height
- - child_height * n_secondaries
- - spacing * (n_secondaries - 1)
- - border_width;
+ - secondary_size - spacing * (n_secondaries - 1) - border_width;
}
break;
@@ -684,18 +779,14 @@ gtk_button_box_size_allocate (GtkWidget *widget,
{
childspacing = spacing;
x = allocation->x + allocation->width
- - child_width * (nvis_children - n_secondaries)
- - spacing * (nvis_children - n_secondaries - 1)
- - border_width;
+ - primary_size - spacing * (n_primaries - 1) - border_width;
secondary_x = allocation->x + border_width;
}
else
{
childspacing = spacing;
y = allocation->y + allocation->height
- - child_height * (nvis_children - n_secondaries)
- - spacing * (nvis_children - n_secondaries - 1)
- - border_width;
+ - primary_size - spacing * (n_primaries - 1) - border_width;
secondary_y = allocation->y + border_width;
}
@@ -708,9 +799,8 @@ gtk_button_box_size_allocate (GtkWidget *widget,
childspacing = spacing;
x = allocation->x +
(allocation->width
- - (child_width * (nvis_children - n_secondaries)
- + spacing * (nvis_children - n_secondaries - 1))) / 2
- + (n_secondaries * child_width + n_secondaries * spacing) / 2;
+ - (primary_size + spacing * (n_primaries - 1))) / 2
+ + (secondary_size + n_secondaries * spacing) / 2;
secondary_x = allocation->x + border_width;
}
else
@@ -718,9 +808,8 @@ gtk_button_box_size_allocate (GtkWidget *widget,
childspacing = spacing;
y = allocation->y +
(allocation->height
- - (child_height * (nvis_children - n_secondaries)
- + spacing * (nvis_children - n_secondaries - 1))) / 2
- + (n_secondaries * child_height + n_secondaries * spacing) / 2;
+ - (primary_size + spacing * (n_primaries - 1))) / 2
+ + (secondary_size + n_secondaries * spacing) / 2;
secondary_y = allocation->y + border_width;
}
@@ -731,74 +820,63 @@ gtk_button_box_size_allocate (GtkWidget *widget,
break;
}
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- y = allocation->y + (allocation->height - child_height) / 2;
- childspace = child_width + childspacing;
- }
- else
- {
- x = allocation->x + (allocation->width - child_width) / 2;
- childspace = child_height + childspacing;
- }
-
- list = children = _gtk_box_get_children (GTK_BOX (box));
-
+ children = list;
+ i = 0;
while (children)
{
GtkWidget *child;
- gboolean is_secondary;
child = children->data;
children = children->next;
- is_secondary = gtk_button_box_get_child_secondary (box, child);
-
if (gtk_widget_get_visible (child))
{
- child_allocation.width = child_width;
- child_allocation.height = child_height;
+ child_allocation.width = widths[i];
+ child_allocation.height = heights[i];
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- child_allocation.y = y;
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
- if (is_secondary)
+ if (gtk_button_box_get_child_secondary (bbox, child))
{
child_allocation.x = secondary_x;
- secondary_x += childspace;
+ secondary_x += child_allocation.width + childspacing;
}
else
{
child_allocation.x = x;
- x += childspace;
+ x += child_allocation.width + childspacing;
}
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
child_allocation.x = (allocation->x + allocation->width)
- - (child_allocation.x + child_width - allocation->x);
+ - (child_allocation.x + child_allocation.width - allocation->x);
}
else
{
- child_allocation.x = x;
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
- if (is_secondary)
+ if (gtk_button_box_get_child_secondary (bbox, child))
{
child_allocation.y = secondary_y;
- secondary_y += childspace;
+ secondary_y += child_allocation.height + childspacing;
}
else
{
child_allocation.y = y;
- y += childspace;
+ y += child_allocation.height + childspacing;
}
}
gtk_widget_size_allocate (child, &child_allocation);
+ i++;
}
}
g_list_free (list);
+ g_free (widths);
+ g_free (heights);
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]