Properly evaluate natural size. Consider natural size for child placement.
2007-07-02 Mathias Hasselmann <mathias.hasselmann@gmx.de> * gtk/gtkbin.c: Properly evaluate natural size. * gtk/gtkhbox.c: Consider natural size for child placement. * gtk/gtklabel.c: Drop any PangoLayout width assigned during the size allocation process to get proper natural size readings. * tests/testextendedlayout.c: Add some GtkHPaned to the natural size test for dynamic evaluation of the algorithm. svn path=/branches/extended-layout/; revision=18339
This commit is contained in:
committed by
Mathias Hasselmann
parent
f568484846
commit
24b2fa20f1
@@ -1,3 +1,14 @@
|
||||
2007-07-02 Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
|
||||
* gtk/gtkbin.c: Properly evaluate natural size.
|
||||
* gtk/gtkhbox.c: Consider natural size for child placement.
|
||||
* gtk/gtklabel.c: Drop any PangoLayout width assigned during the
|
||||
size allocation process to get proper natural size readings.
|
||||
* tests/testextendedlayout.c: Add some GtkHPaned to the natural
|
||||
size test for dynamic evaluation of the algorithm. Create guides for
|
||||
the button of the height-for-width test for debugging, as it is
|
||||
affected by natural sizing of GtkHBox.
|
||||
|
||||
2007-07-01 Mathias Hasselmann <mathias.hasselmann@gmx.de>
|
||||
|
||||
* gtk/gtk.symbols, gtk/gtkextendedlayout.c, gtk/gtkextendedlayout.h:
|
||||
|
||||
23
gtk/gtkbin.c
23
gtk/gtkbin.c
@@ -73,8 +73,8 @@ gtk_bin_child_type (GtkContainer *container)
|
||||
{
|
||||
if (!GTK_BIN (container)->child)
|
||||
return GTK_TYPE_WIDGET;
|
||||
else
|
||||
return G_TYPE_NONE;
|
||||
|
||||
return G_TYPE_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -195,11 +195,22 @@ gtk_bin_extended_layout_get_natural_size (GtkExtendedLayout *layout,
|
||||
GtkRequisition *requisition)
|
||||
{
|
||||
GtkBin *bin = GTK_BIN (layout);
|
||||
GtkExtendedLayout *child_layout;
|
||||
|
||||
g_return_if_fail (GTK_IS_EXTENDED_LAYOUT (bin->child));
|
||||
|
||||
layout = GTK_EXTENDED_LAYOUT (bin->child);
|
||||
return gtk_extended_layout_get_natural_size (layout, requisition);
|
||||
child_layout = GTK_EXTENDED_LAYOUT (bin->child);
|
||||
gtk_extended_layout_get_natural_size (child_layout, requisition);
|
||||
|
||||
if (GTK_EXTENDED_LAYOUT_HAS_PADDING (layout))
|
||||
{
|
||||
GtkBorder padding;
|
||||
|
||||
gtk_extended_layout_get_padding (layout, &padding);
|
||||
|
||||
requisition->width += padding.left + padding.right;
|
||||
requisition->height += padding.top + padding.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
@@ -222,9 +233,7 @@ gtk_bin_extended_layout_get_baselines (GtkExtendedLayout *layout,
|
||||
GtkBorder padding;
|
||||
|
||||
if (GTK_EXTENDED_LAYOUT_HAS_PADDING (bin))
|
||||
{
|
||||
gtk_extended_layout_get_padding (layout, &padding);
|
||||
}
|
||||
gtk_extended_layout_get_padding (layout, &padding);
|
||||
else
|
||||
padding.top = GTK_CONTAINER (bin)->border_width;
|
||||
|
||||
|
||||
120
gtk/gtkhbox.c
120
gtk/gtkhbox.c
@@ -173,13 +173,12 @@ gtk_hbox_size_request (GtkWidget *widget,
|
||||
if (nvis_children > 0)
|
||||
{
|
||||
GtkHBoxPrivate *priv = GTK_HBOX_GET_PRIVATE (widget);
|
||||
gint effective_baseline, i;
|
||||
gint effective_baseline = 0, i;
|
||||
gint *baselines = NULL;
|
||||
|
||||
if (priv->baseline_policy != GTK_BASELINE_NONE)
|
||||
{
|
||||
baselines = g_newa (gint, nvis_children);
|
||||
effective_baseline = 0;
|
||||
|
||||
i = 0;
|
||||
children = box->children;
|
||||
@@ -265,13 +264,9 @@ gtk_hbox_size_allocate (GtkWidget *widget,
|
||||
GtkBoxChild *child;
|
||||
GList *children;
|
||||
|
||||
GtkTextDirection direction;
|
||||
|
||||
box = GTK_BOX (widget);
|
||||
widget->allocation = *allocation;
|
||||
|
||||
direction = gtk_widget_get_direction (widget);
|
||||
|
||||
nvis_children = 0;
|
||||
nexpand_children = 0;
|
||||
children = box->children;
|
||||
@@ -292,46 +287,103 @@ gtk_hbox_size_allocate (GtkWidget *widget,
|
||||
if (nvis_children > 0)
|
||||
{
|
||||
GtkHBoxPrivate *priv = GTK_HBOX_GET_PRIVATE (widget);
|
||||
GtkAllocation child_allocation;
|
||||
gint effective_baseline, i;
|
||||
|
||||
gint effective_baseline;
|
||||
GtkPackType packing;
|
||||
gint *baselines;
|
||||
|
||||
gint width;
|
||||
gint extra;
|
||||
GtkTextDirection direction;
|
||||
gint border_width;
|
||||
|
||||
baselines = g_newa (gint, nvis_children);
|
||||
effective_baseline = 0;
|
||||
GtkAllocation child_allocation;
|
||||
|
||||
gint *natural_requisitions;
|
||||
gint *minimum_requisitions;
|
||||
|
||||
gint natural_width;
|
||||
gint minimum_width;
|
||||
|
||||
gint available, natural, extra;
|
||||
gint i;
|
||||
|
||||
direction = gtk_widget_get_direction (widget);
|
||||
border_width = GTK_CONTAINER (box)->border_width;
|
||||
|
||||
natural_width = 0;
|
||||
natural_requisitions = g_newa (gint, nvis_children);
|
||||
minimum_requisitions = g_newa (gint, nvis_children);
|
||||
|
||||
children = box->children;
|
||||
i = 0;
|
||||
|
||||
while (children)
|
||||
{
|
||||
child = children->data;
|
||||
children = children->next;
|
||||
|
||||
if (GTK_WIDGET_VISIBLE (child->widget))
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
|
||||
gtk_widget_size_request (child->widget, &child_requisition);
|
||||
minimum_requisitions[i] = child_requisition.width;
|
||||
|
||||
if (GTK_IS_EXTENDED_LAYOUT (child->widget) &&
|
||||
GTK_EXTENDED_LAYOUT_HAS_NATURAL_SIZE (child->widget))
|
||||
{
|
||||
gtk_extended_layout_get_natural_size (
|
||||
GTK_EXTENDED_LAYOUT (child->widget),
|
||||
&child_requisition);
|
||||
natural_requisitions[i] =
|
||||
child_requisition.width -
|
||||
minimum_requisitions[i];
|
||||
}
|
||||
else
|
||||
natural_requisitions[i] = 0;
|
||||
|
||||
natural_width += natural_requisitions[i++];
|
||||
}
|
||||
}
|
||||
|
||||
minimum_width = widget->requisition.width - border_width * 2 -
|
||||
(nvis_children - 1) * box->spacing;
|
||||
|
||||
if (box->homogeneous)
|
||||
{
|
||||
width = (allocation->width -
|
||||
GTK_CONTAINER (box)->border_width * 2 -
|
||||
(nvis_children - 1) * box->spacing);
|
||||
extra = width / nvis_children;
|
||||
available = (allocation->width - border_width * 2 -
|
||||
(nvis_children - 1) * box->spacing);
|
||||
extra = available / nvis_children;
|
||||
natural = 0;
|
||||
}
|
||||
else if (nexpand_children > 0)
|
||||
{
|
||||
width = (gint) allocation->width - (gint) widget->requisition.width;
|
||||
extra = width / nexpand_children;
|
||||
available = (gint)allocation->width - widget->requisition.width;
|
||||
natural = MAX (0, MIN (available, natural_width));
|
||||
available -= natural;
|
||||
|
||||
extra = MAX (0, available / nexpand_children);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = 0;
|
||||
available = 0;
|
||||
natural = 0;
|
||||
extra = 0;
|
||||
}
|
||||
|
||||
child_allocation.y = allocation->y + GTK_CONTAINER (box)->border_width;
|
||||
child_allocation.height = MAX (1, (gint) allocation->height - (gint) GTK_CONTAINER (box)->border_width * 2);
|
||||
effective_baseline = 0;
|
||||
baselines = g_newa (gint, nvis_children);
|
||||
|
||||
child_allocation.y = allocation->y + border_width;
|
||||
child_allocation.height = MAX (1, (gint) allocation->height - (gint) border_width * 2);
|
||||
|
||||
for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
|
||||
{
|
||||
gint x;
|
||||
|
||||
if (GTK_PACK_START == packing)
|
||||
x = allocation->x + GTK_CONTAINER (box)->border_width;
|
||||
x = allocation->x + border_width;
|
||||
else
|
||||
x = allocation->x + allocation->width - GTK_CONTAINER (box)->border_width;
|
||||
x = allocation->x + allocation->width - border_width;
|
||||
|
||||
i = 0;
|
||||
children = box->children;
|
||||
@@ -344,37 +396,37 @@ gtk_hbox_size_allocate (GtkWidget *widget,
|
||||
{
|
||||
if ((child->pack == packing))
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
gint child_width;
|
||||
|
||||
gtk_widget_get_child_requisition (child->widget, &child_requisition);
|
||||
|
||||
if (box->homogeneous)
|
||||
{
|
||||
if (nvis_children == 1)
|
||||
child_width = width;
|
||||
child_width = available;
|
||||
else
|
||||
child_width = extra;
|
||||
|
||||
nvis_children -= 1;
|
||||
width -= extra;
|
||||
available -= extra;
|
||||
}
|
||||
else
|
||||
{
|
||||
child_width = child_requisition.width + child->padding * 2;
|
||||
child_width = minimum_requisitions[i] + child->padding * 2;
|
||||
|
||||
if (child->expand)
|
||||
{
|
||||
if (nexpand_children == 1)
|
||||
child_width += width;
|
||||
child_width += available;
|
||||
else
|
||||
child_width += extra;
|
||||
|
||||
nexpand_children -= 1;
|
||||
width -= extra;
|
||||
available -= extra;
|
||||
}
|
||||
}
|
||||
|
||||
if (natural_width > 0)
|
||||
child_width += natural * natural_requisitions[i] / natural_width;
|
||||
|
||||
if (child->fill)
|
||||
{
|
||||
child_allocation.width = MAX (1, (gint) child_width - (gint) child->padding * 2);
|
||||
@@ -382,7 +434,7 @@ gtk_hbox_size_allocate (GtkWidget *widget,
|
||||
}
|
||||
else
|
||||
{
|
||||
child_allocation.width = child_requisition.width;
|
||||
child_allocation.width = minimum_requisitions[i];
|
||||
child_allocation.x = x + (child_width - child_allocation.width) / 2;
|
||||
}
|
||||
|
||||
@@ -498,8 +550,8 @@ gtk_hbox_extended_layout_get_natural_size (GtkExtendedLayout *layout,
|
||||
GtkBoxChild *child;
|
||||
GList *children;
|
||||
|
||||
requisition->width = 0;
|
||||
requisition->height = 0;
|
||||
requisition->width = GTK_CONTAINER (box)->border_width * 2;
|
||||
requisition->height = GTK_CONTAINER (box)->border_width * 2;
|
||||
|
||||
children = box->children;
|
||||
while (children)
|
||||
|
||||
@@ -4276,14 +4276,21 @@ gtk_label_extended_layout_get_natural_size (GtkExtendedLayout *layout,
|
||||
{
|
||||
GtkLabel *label;
|
||||
gboolean ellipsize;
|
||||
PangoLayout *tmp;
|
||||
|
||||
label = GTK_LABEL (layout);
|
||||
ellipsize = label->ellipsize;
|
||||
label->ellipsize = PANGO_ELLIPSIZE_NONE;
|
||||
|
||||
tmp = label->layout;
|
||||
label->layout = pango_layout_copy (tmp);
|
||||
|
||||
pango_layout_set_width (label->layout, -1);
|
||||
gtk_label_size_request (GTK_WIDGET (label), requisition);
|
||||
|
||||
g_object_unref (label->layout);
|
||||
label->ellipsize = ellipsize;
|
||||
label->layout = tmp;
|
||||
}
|
||||
|
||||
static gint
|
||||
|
||||
@@ -193,6 +193,7 @@ test_case_append_guide (TestCase *self,
|
||||
|
||||
static void
|
||||
append_natural_size_box (TestCase *test,
|
||||
GtkWidget *vbox,
|
||||
const gchar *caption,
|
||||
PangoEllipsizeMode ellipsize)
|
||||
{
|
||||
@@ -218,32 +219,98 @@ append_natural_size_box (TestCase *test,
|
||||
gtk_label_set_markup (GTK_LABEL (label), caption);
|
||||
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (test->widget), label, FALSE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (test->widget), hbox, FALSE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
restore_paned (gpointer data)
|
||||
{
|
||||
GtkPaned *paned;
|
||||
GtkWidget *hint;
|
||||
gint pos;
|
||||
|
||||
|
||||
paned = GTK_PANED (data);
|
||||
hint = gtk_paned_get_child2 (paned);
|
||||
gtk_widget_set_sensitive (hint, TRUE);
|
||||
|
||||
pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (paned), "initial-position"));
|
||||
gtk_paned_set_position (paned, pos);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shrink_paned_timeout (gpointer data)
|
||||
{
|
||||
GtkPaned *paned;
|
||||
gint pos;
|
||||
|
||||
paned = GTK_PANED (data);
|
||||
pos = gtk_paned_get_position (paned);
|
||||
|
||||
if (pos < 20)
|
||||
{
|
||||
g_timeout_add (1000, restore_paned, paned);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_paned_set_position (paned, pos - 5);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
shrink_paned (GtkWidget *button,
|
||||
gpointer data)
|
||||
{
|
||||
GtkPaned *paned;
|
||||
GtkWidget *hint;
|
||||
|
||||
paned = GTK_PANED (data);
|
||||
hint = gtk_paned_get_child2 (paned);
|
||||
gtk_widget_set_sensitive (hint, FALSE);
|
||||
|
||||
g_object_set_data (G_OBJECT (paned), "initial-position",
|
||||
GINT_TO_POINTER (gtk_paned_get_position (paned)));
|
||||
g_timeout_add (50, shrink_paned_timeout, paned);
|
||||
}
|
||||
|
||||
static TestCase*
|
||||
create_natural_size_test (TestSuite *suite)
|
||||
{
|
||||
GtkWidget *vbox, *hint, *button;
|
||||
|
||||
TestCase *test = test_case_new (suite, "Natural Size", NULL,
|
||||
gtk_vbox_new (FALSE, 12));
|
||||
gtk_hpaned_new ());
|
||||
gtk_container_set_border_width (GTK_CONTAINER (test->widget), 6);
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (test->widget), 12);
|
||||
vbox = gtk_vbox_new (FALSE, 12);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
|
||||
gtk_paned_pack1 (GTK_PANED (test->widget), vbox, TRUE, TRUE);
|
||||
|
||||
append_natural_size_box (test,
|
||||
append_natural_size_box (test, vbox,
|
||||
"<b>No ellipsizing</b>",
|
||||
PANGO_ELLIPSIZE_NONE);
|
||||
append_natural_size_box (test,
|
||||
append_natural_size_box (test, vbox,
|
||||
"<b>Ellipsizing at start</b>",
|
||||
PANGO_ELLIPSIZE_START);
|
||||
append_natural_size_box (test,
|
||||
append_natural_size_box (test, vbox,
|
||||
"<b>Ellipsizing in the middle</b>",
|
||||
PANGO_ELLIPSIZE_MIDDLE);
|
||||
append_natural_size_box (test,
|
||||
append_natural_size_box (test, vbox,
|
||||
"<b>Ellipsizing at end</b>",
|
||||
PANGO_ELLIPSIZE_END);
|
||||
|
||||
button = gtk_button_new_with_label ("Shrink to check ellipsing");
|
||||
gtk_label_set_angle (GTK_LABEL (GTK_BIN (button)->child), -90);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (shrink_paned), test->widget);
|
||||
|
||||
hint = gtk_alignment_new (1.0, 0.5, 0.0, 1.0);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hint), 6);
|
||||
gtk_container_add (GTK_CONTAINER (hint), button);
|
||||
gtk_paned_pack2 (GTK_PANED (test->widget), hint, FALSE, FALSE);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
@@ -278,6 +345,8 @@ create_height_for_width_test (TestSuite *suite)
|
||||
GTK_ICON_SIZE_DIALOG));
|
||||
gtk_box_pack_start (GTK_BOX (test->widget), child, FALSE, TRUE, 0);
|
||||
|
||||
test_case_append_guide (test, child, GUIDE_EXTERIOUR_BOTH, 1);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user