+
+ avg_w = avg_h = 0;
+ while (children)
+ {
+ GtkWidget *child;
+
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_get_visible (child))
+ {
+ nchildren += 1;
+ gtk_widget_get_preferred_size (child,
+ &child_requisition, NULL);
+ avg_w += child_requisition.width + ipad_w;
+ avg_h += child_requisition.height + ipad_h;
+ }
+ }
+ avg_w /= MAX (nchildren, 1);
+ avg_h /= MAX (nchildren, 1);
+
+ *widths = g_new (gint, nchildren);
+ *heights = g_new (gint, nchildren);
+
+ i = 0;
+ children = list;
+ while (children)
+ {
+ GtkWidget *child;
+ gboolean is_secondary;
+ gboolean non_homogeneous;
+
+ child = children->data;
+ children = children->next;
+
+ if (gtk_widget_get_visible (child))
+ {
+ is_secondary = gtk_button_box_get_child_secondary (bbox, child);
+ non_homogeneous = gtk_button_box_get_child_non_homogeneous (bbox, child);
+
+ if (is_secondary)
+ nsecondaries++;
+
+ gtk_widget_get_preferred_size (child, &child_requisition, NULL);
+
+ if (homogeneous ||
+ (!non_homogeneous && (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 ||
+ (!non_homogeneous && (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;
+}
+
+static void
+gtk_button_box_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ GtkButtonBoxPrivate *priv;
+ GtkButtonBox *bbox;
+ gint nvis_children;
+ gint max_size;
+ gint total_size;
+ gint spacing;
+ GtkOrientation orientation;
+ gint *widths;
+ gint *heights;
+ gint i;
+
+ bbox = GTK_BUTTON_BOX (widget);
+ priv = bbox->priv;
+
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+ spacing = gtk_box_get_spacing (GTK_BOX (widget));
+
+ 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)
+ {
+ requisition->width = 0;
+ requisition->height = 0;
+ }
+ else
+ {
+ switch (priv->layout_style)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->width = total_size + ((nvis_children + 1)*spacing);
+ else
+ requisition->height = total_size + ((nvis_children + 1)*spacing);
+
+ break;
+ case GTK_BUTTONBOX_EDGE:
+ case GTK_BUTTONBOX_START:
+ case GTK_BUTTONBOX_END:
+ case GTK_BUTTONBOX_CENTER:
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->width = total_size + ((nvis_children - 1)*spacing);
+ else
+ requisition->height = total_size + ((nvis_children - 1)*spacing);
+
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ requisition->height = max_size;
+ else
+ requisition->width = max_size;
+ }
+}
+
+static void
+gtk_button_box_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_button_box_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.width;
+}
+
+static void
+gtk_button_box_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_button_box_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.height;
+}
+
+static void
+gtk_button_box_get_preferred_width_for_height (GtkWidget *widget,
+ gint height,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_button_box_get_preferred_width (widget, minimum, natural);
+}
+
+static void
+gtk_button_box_get_preferred_height_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_button_box_get_preferred_height (widget, minimum, natural);
+}
+
+static void
+gtk_button_box_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ GtkButtonBoxPrivate *priv;
+ GtkButtonBox *bbox;
+ GList *children, *list;
+ GtkAllocation child_allocation;
+ gint nvis_children;
+ gint n_primaries;
+ gint n_secondaries;
+ gint x = 0;
+ gint y = 0;
+ gint secondary_x = 0;
+ gint secondary_y = 0;
+ gint width = 0;
+ gint height = 0;
+ gint childspacing = 0;
+ gint spacing;
+ GtkOrientation orientation;
+ gint ipad_x, ipad_y;
+ gint *widths;
+ gint *heights;
+ gint *sizes;
+ gint primary_size;
+ gint secondary_size;
+ gint total_size;
+ gint i;
+
+ bbox = GTK_BUTTON_BOX (widget);
+ priv = bbox->priv;
+
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+ 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;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ width = allocation->width;
+ else
+ height = allocation->height;
+
+ switch (priv->layout_style)
+ {
+ case GTK_BUTTONBOX_SPREAD:
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ childspacing = (width - total_size) / (nvis_children + 1);
+ x = allocation->x + childspacing;
+ secondary_x = x + primary_size + n_primaries * childspacing;
+ }
+ else
+ {
+ childspacing = (height - total_size) / (nvis_children + 1);
+ y = allocation->y + childspacing;
+ secondary_y = y + primary_size + n_primaries * childspacing;
+ }
+
+ break;
+
+ case GTK_BUTTONBOX_EDGE:
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (nvis_children >= 2)
+ {
+ childspacing = (width - total_size) / (nvis_children - 1);
+ x = allocation->x;
+ secondary_x = x + primary_size + n_primaries * childspacing;
+ }
+ else if (nvis_children == 1)
+ {
+ /* one child, just center */
+ childspacing = width;
+ x = secondary_x = allocation->x
+ + (allocation->width - widths[0]) / 2;
+ }
+ else
+ {
+ /* zero children, meh */
+ childspacing = width;
+ x = secondary_x = allocation->x + allocation->width / 2;
+ }
+ }
+ else
+ {
+ if (nvis_children >= 2)
+ {
+ childspacing = (height - total_size) / (nvis_children - 1);
+ y = allocation->y;
+ secondary_y = y + primary_size + n_primaries * childspacing;
+ }
+ else if (nvis_children == 1)
+ {
+ /* one child, just center */
+ childspacing = height;
+ y = secondary_y = allocation->y
+ + (allocation->height - heights[0]) / 2;
+ }
+ else
+ {
+ /* zero children, meh */
+ childspacing = height;
+ y = secondary_y = allocation->y + allocation->height / 2;
+ }
+ }
+
+ break;
+
+ case GTK_BUTTONBOX_START:
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ childspacing = spacing;
+ x = allocation->x;
+ secondary_x = allocation->x + allocation->width
+ - secondary_size - spacing * (n_secondaries - 1);
+ }
+ else
+ {
+ childspacing = spacing;
+ y = allocation->y;
+ secondary_y = allocation->y + allocation->height
+ - secondary_size - spacing * (n_secondaries - 1);
+ }
+
+ break;
+
+ case GTK_BUTTONBOX_END:
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ childspacing = spacing;
+ x = allocation->x + allocation->width
+ - primary_size - spacing * (n_primaries - 1);
+ secondary_x = allocation->x;
+ }
+ else
+ {
+ childspacing = spacing;
+ y = allocation->y + allocation->height
+ - primary_size - spacing * (n_primaries - 1);
+ secondary_y = allocation->y;
+ }
+
+ break;
+
+ case GTK_BUTTONBOX_CENTER:
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ childspacing = spacing;
+ x = allocation->x +
+ (allocation->width
+ - (primary_size + spacing * (n_primaries - 1))) / 2
+ + (secondary_size + n_secondaries * spacing) / 2;
+ secondary_x = allocation->x;
+ }
+ else
+ {
+ childspacing = spacing;
+ y = allocation->y +
+ (allocation->height
+ - (primary_size + spacing * (n_primaries - 1))) / 2
+ + (secondary_size + n_secondaries * spacing) / 2;
+ secondary_y = allocation->y;
+ }
+
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ children = list;
+ i = 0;