summaryrefslogtreecommitdiff
path: root/gtk/gtkbbox.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2010-08-22 00:30:31 -0400
committerMatthias Clasen <mclasen@redhat.com>2010-08-22 00:33:37 -0400
commitfe1a39b1f2358af206b6cd8107360427cca21bb5 (patch)
tree2dd9420b0e406a87c2b5d0aa8ebee58eece43254 /gtk/gtkbbox.c
parentdf5ade16abababba349c1404881a205b8f4d655c (diff)
downloadgtk+-fe1a39b1f2358af206b6cd8107360427cca21bb5.tar.gz
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.
Diffstat (limited to 'gtk/gtkbbox.c')
-rw-r--r--gtk/gtkbbox.c314
1 files changed, 196 insertions, 118 deletions
diff --git a/gtk/gtkbbox.c b/gtk/gtkbbox.c
index 655ba9ace9..aae0f742a5 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);
}
/**