Compare commits

...

7 Commits

Author SHA1 Message Date
Alexander Larsson
dba6649098 Add tests/testbaseline 2013-03-07 19:57:43 +01:00
Alexander Larsson
fe2062925c GtkButton: Add baseline align support 2013-03-07 19:57:43 +01:00
Alexander Larsson
169ba01c2a GtkAlignment: Support baselines
We now report any baselines from the child, and allocate it.
Also, in the case of a baselign aligned child we ignore yscale/yalign
as that is not supportable.
2013-03-07 19:57:43 +01:00
Alexander Larsson
3244628724 GtkBox: Add baseline alignment for horizontal boxes
Report a baseline based height and baseline whenever there
are children with ALIGN_BASELINE.

Assign baseline to childen in size_allocate. Either the one inherited
from the parent if set, or otherwise calculate one based on any
ALIGN_BASELINE children.
2013-03-07 19:57:43 +01:00
Alexander Larsson
2954b45f54 GtkLabel: Support baseline
Report the baseline in get_preferred_height_and_baseline_for_width().
2013-03-07 19:57:43 +01:00
Alexander Larsson
d8a65ae304 Initial support for baselines
This modifies the size machinery in order to allow baseline support.

We add a new widget vfunc get_preferred_height_and_baseline_for_width which
queries the normal height_for_width (or non-for-width if width is -1) and
additionally returns optional (-1 means "no baseline") baselines for the minimal
and natural heights.

We also add a new gtk_widget_size_allocate_with_baseline() which baseline-aware
containers can use to allocate children with a specific baseline, either one inherited
from the parent, or one introduced due to requested baseline alignment in the
container itself. size_allocate_with_baseline() works just like a normal size
allocation, except the baseline gets recorded so that the child can access it
via gtk_widget_get_allocated_baseline() when it aligns itself.

There are also adjust_baseline_request/allocation similar to the allocation
adjustment, and we extend the size request cache to also store the baselines.
2013-03-07 19:57:43 +01:00
Alexander Larsson
854fedbb45 Add GTK_ALIGN_BASELINE to GtkAlign
Setting this means baseline aware containers should align the widget
according to the baseline. For other containers this behaves like
FILL.

In order to not suprise old code with a new enum value we always
return _FILL for _BASELINE unless you specifically request it via
gtk_widget_get_valign_with_baseline().
2013-03-07 19:57:43 +01:00
15 changed files with 1010 additions and 156 deletions

View File

@@ -108,6 +108,12 @@ static void gtk_alignment_get_preferred_height_for_width (GtkWidget *w
gint for_size, gint for_size,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void gtk_alignment_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint for_size,
gint *minimum_size,
gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline);
G_DEFINE_TYPE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN) G_DEFINE_TYPE (GtkAlignment, gtk_alignment, GTK_TYPE_BIN)
@@ -128,6 +134,7 @@ gtk_alignment_class_init (GtkAlignmentClass *class)
widget_class->get_preferred_height = gtk_alignment_get_preferred_height; widget_class->get_preferred_height = gtk_alignment_get_preferred_height;
widget_class->get_preferred_width_for_height = gtk_alignment_get_preferred_width_for_height; widget_class->get_preferred_width_for_height = gtk_alignment_get_preferred_width_for_height;
widget_class->get_preferred_height_for_width = gtk_alignment_get_preferred_height_for_width; widget_class->get_preferred_height_for_width = gtk_alignment_get_preferred_height_for_width;
widget_class->get_preferred_height_and_baseline_for_width = gtk_alignment_get_preferred_height_and_baseline_for_width;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_XALIGN, PROP_XALIGN,
@@ -507,6 +514,7 @@ gtk_alignment_size_allocate (GtkWidget *widget,
gint width, height; gint width, height;
guint border_width; guint border_width;
gint padding_horizontal, padding_vertical; gint padding_horizontal, padding_vertical;
gint baseline;
padding_horizontal = 0; padding_horizontal = 0;
padding_vertical = 0; padding_vertical = 0;
@@ -520,6 +528,7 @@ gtk_alignment_size_allocate (GtkWidget *widget,
gint child_nat_width; gint child_nat_width;
gint child_nat_height; gint child_nat_height;
gint child_width, child_height; gint child_width, child_height;
double yalign, yscale;
border_width = gtk_container_get_border_width (GTK_CONTAINER (alignment)); border_width = gtk_container_get_border_width (GTK_CONTAINER (alignment));
@@ -529,6 +538,25 @@ gtk_alignment_size_allocate (GtkWidget *widget,
width = MAX (1, allocation->width - padding_horizontal - 2 * border_width); width = MAX (1, allocation->width - padding_horizontal - 2 * border_width);
height = MAX (1, allocation->height - padding_vertical - 2 * border_width); height = MAX (1, allocation->height - padding_vertical - 2 * border_width);
baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline != -1)
baseline -= border_width + priv->padding_top;
/* If we get a baseline set that means we're baseline aligned, and the parent
honored that. In that case we have to ignore yalign/yscale as we need
yalign based on the baseline and always FILL mode to ensure we can place
the baseline anywhere */
if (baseline != -1)
{
yalign = 0;
yscale = 1.0;
}
else
{
yalign = priv->yalign;
yscale = priv->yscale;
}
if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
{ {
gtk_widget_get_preferred_width (child, NULL, &child_nat_width); gtk_widget_get_preferred_width (child, NULL, &child_nat_width);
@@ -559,8 +587,8 @@ gtk_alignment_size_allocate (GtkWidget *widget,
if (height > child_height) if (height > child_height)
child_allocation.height = (child_height * child_allocation.height = (child_height *
(1.0 - priv->yscale) + (1.0 - yscale) +
height * priv->yscale); height * yscale);
else else
child_allocation.height = height; child_allocation.height = height;
@@ -569,9 +597,9 @@ gtk_alignment_size_allocate (GtkWidget *widget,
else else
child_allocation.x = priv->xalign * (width - child_allocation.width) + allocation->x + border_width + priv->padding_left; child_allocation.x = priv->xalign * (width - child_allocation.width) + allocation->x + border_width + priv->padding_left;
child_allocation.y = priv->yalign * (height - child_allocation.height) + allocation->y + border_width + priv->padding_top; child_allocation.y = yalign * (height - child_allocation.height) + allocation->y + border_width + priv->padding_top;
gtk_widget_size_allocate (child, &child_allocation); gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline);
} }
} }
@@ -581,18 +609,30 @@ gtk_alignment_get_preferred_size (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkAlignment *alignment = GTK_ALIGNMENT (widget); GtkAlignment *alignment = GTK_ALIGNMENT (widget);
GtkAlignmentPrivate *priv = alignment->priv; GtkAlignmentPrivate *priv = alignment->priv;
GtkWidget *child; GtkWidget *child;
guint minimum, natural; guint minimum, natural;
guint top_offset;
guint border;
natural = minimum = gtk_container_get_border_width (GTK_CONTAINER (widget)) * 2; if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
border = gtk_container_get_border_width (GTK_CONTAINER (widget));
natural = minimum = border * 2;
top_offset = border;
if ((child = gtk_bin_get_child (GTK_BIN (widget))) && gtk_widget_get_visible (child)) if ((child = gtk_bin_get_child (GTK_BIN (widget))) && gtk_widget_get_visible (child))
{ {
gint child_min, child_nat; gint child_min, child_nat;
gint child_min_baseline = -1, child_nat_baseline = -1;
/* Request extra space for the padding: */ /* Request extra space for the padding: */
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -619,9 +659,10 @@ gtk_alignment_get_preferred_size (GtkWidget *widget,
else else
{ {
minimum += (priv->padding_top + priv->padding_bottom); minimum += (priv->padding_top + priv->padding_bottom);
top_offset += priv->padding_top;
if (for_size < 0) if (for_size < 0)
gtk_widget_get_preferred_height (child, &child_min, &child_nat); gtk_widget_get_preferred_height_and_baseline_for_width (child, -1, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline);
else else
{ {
gint min_width; gint min_width;
@@ -634,8 +675,13 @@ gtk_alignment_get_preferred_size (GtkWidget *widget,
for_size = (min_width * (1.0 - priv->xscale) + for_size = (min_width * (1.0 - priv->xscale) +
for_size * priv->xscale); for_size * priv->xscale);
gtk_widget_get_preferred_height_for_width (child, for_size, &child_min, &child_nat); gtk_widget_get_preferred_height_and_baseline_for_width (child, for_size, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline);
} }
if (minimum_baseline && child_min_baseline >= 0)
*minimum_baseline = child_min_baseline + top_offset;
if (natural_baseline && child_nat_baseline >= 0)
*natural_baseline = child_nat_baseline + top_offset;
} }
natural = minimum; natural = minimum;
@@ -656,7 +702,7 @@ gtk_alignment_get_preferred_width (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size); gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -664,7 +710,7 @@ gtk_alignment_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size); gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size, NULL, NULL);
} }
@@ -674,7 +720,7 @@ gtk_alignment_get_preferred_width_for_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, for_size, minimum_size, natural_size); gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, for_size, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -683,9 +729,21 @@ gtk_alignment_get_preferred_height_for_width (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size); gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size, NULL, NULL);
} }
static void
gtk_alignment_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint for_size,
gint *minimum_size,
gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{
gtk_alignment_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size, minimum_baseline, natural_baseline);
}
/** /**
* gtk_alignment_set_padding: * gtk_alignment_set_padding:
* @alignment: a #GtkAlignment * @alignment: a #GtkAlignment

View File

@@ -94,7 +94,8 @@ enum {
PROP_0, PROP_0,
PROP_ORIENTATION, PROP_ORIENTATION,
PROP_SPACING, PROP_SPACING,
PROP_HOMOGENEOUS PROP_HOMOGENEOUS,
PROP_BASELINE_POSITION
}; };
enum { enum {
@@ -116,6 +117,7 @@ struct _GtkBoxPrivate
guint default_expand : 1; guint default_expand : 1;
guint homogeneous : 1; guint homogeneous : 1;
guint spacing_set : 1; guint spacing_set : 1;
guint baseline_pos : 2;
}; };
typedef struct _GtkBoxChild GtkBoxChild; typedef struct _GtkBoxChild GtkBoxChild;
@@ -200,6 +202,12 @@ static void gtk_box_get_preferred_height_for_width (GtkWidget
gint width, gint width,
gint *minimum_height, gint *minimum_height,
gint *natural_height); gint *natural_height);
static void gtk_box_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline);
G_DEFINE_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER, G_DEFINE_TYPE_WITH_CODE (GtkBox, gtk_box, GTK_TYPE_CONTAINER,
@@ -220,6 +228,7 @@ gtk_box_class_init (GtkBoxClass *class)
widget_class->get_preferred_width = gtk_box_get_preferred_width; widget_class->get_preferred_width = gtk_box_get_preferred_width;
widget_class->get_preferred_height = gtk_box_get_preferred_height; widget_class->get_preferred_height = gtk_box_get_preferred_height;
widget_class->get_preferred_height_for_width = gtk_box_get_preferred_height_for_width; widget_class->get_preferred_height_for_width = gtk_box_get_preferred_height_for_width;
widget_class->get_preferred_height_and_baseline_for_width = gtk_box_get_preferred_height_and_baseline_for_width;
widget_class->get_preferred_width_for_height = gtk_box_get_preferred_width_for_height; widget_class->get_preferred_width_for_height = gtk_box_get_preferred_width_for_height;
widget_class->compute_expand = gtk_box_compute_expand; widget_class->compute_expand = gtk_box_compute_expand;
widget_class->direction_changed = gtk_box_direction_changed; widget_class->direction_changed = gtk_box_direction_changed;
@@ -255,6 +264,15 @@ gtk_box_class_init (GtkBoxClass *class)
FALSE, FALSE,
GTK_PARAM_READWRITE)); GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_BASELINE_POSITION,
g_param_spec_enum ("baseline-position",
P_("Baseline position"),
P_("The position of the baseline aligned widgets if extra space is availible"),
GTK_TYPE_BASELINE_POSITION,
GTK_BASELINE_POSITION_CENTER,
GTK_PARAM_READWRITE));
/** /**
* GtkBox:expand: * GtkBox:expand:
* *
@@ -340,6 +358,7 @@ gtk_box_init (GtkBox *box)
private->homogeneous = FALSE; private->homogeneous = FALSE;
private->spacing = 0; private->spacing = 0;
private->spacing_set = FALSE; private->spacing_set = FALSE;
private->baseline_pos = GTK_BASELINE_POSITION_CENTER;
} }
static void static void
@@ -361,6 +380,9 @@ gtk_box_set_property (GObject *object,
case PROP_SPACING: case PROP_SPACING:
gtk_box_set_spacing (box, g_value_get_int (value)); gtk_box_set_spacing (box, g_value_get_int (value));
break; break;
case PROP_BASELINE_POSITION:
gtk_box_set_baseline_position (box, g_value_get_enum (value));
break;
case PROP_HOMOGENEOUS: case PROP_HOMOGENEOUS:
gtk_box_set_homogeneous (box, g_value_get_boolean (value)); gtk_box_set_homogeneous (box, g_value_get_boolean (value));
break; break;
@@ -387,6 +409,9 @@ gtk_box_get_property (GObject *object,
case PROP_SPACING: case PROP_SPACING:
g_value_set_int (value, private->spacing); g_value_set_int (value, private->spacing);
break; break;
case PROP_BASELINE_POSITION:
g_value_set_enum (value, private->baseline_pos);
break;
case PROP_HOMOGENEOUS: case PROP_HOMOGENEOUS:
g_value_set_boolean (value, private->homogeneous); g_value_set_boolean (value, private->homogeneous);
break; break;
@@ -435,6 +460,11 @@ gtk_box_size_allocate (GtkWidget *widget,
GtkTextDirection direction; GtkTextDirection direction;
GtkAllocation child_allocation; GtkAllocation child_allocation;
GtkRequestedSize *sizes; GtkRequestedSize *sizes;
gint child_minimum_baseline, child_natural_baseline;
gint minimum_above, natural_above;
gint minimum_below, natural_below;
gboolean have_baseline;
gint baseline;
GtkPackType packing; GtkPackType packing;
@@ -461,6 +491,10 @@ gtk_box_size_allocate (GtkWidget *widget,
else else
size = allocation->height - (nvis_children - 1) * private->spacing; size = allocation->height - (nvis_children - 1) * private->spacing;
have_baseline = FALSE;
minimum_above = natural_above = 0;
minimum_below = natural_below = 0;
/* Retrieve desired size for visible children. */ /* Retrieve desired size for visible children. */
for (i = 0, children = private->children; children; children = children->next) for (i = 0, children = private->children; children; children = children->next)
{ {
@@ -475,11 +509,11 @@ gtk_box_size_allocate (GtkWidget *widget,
&sizes[i].minimum_size, &sizes[i].minimum_size,
&sizes[i].natural_size); &sizes[i].natural_size);
else else
gtk_widget_get_preferred_height_for_width (child->widget, gtk_widget_get_preferred_height_and_baseline_for_width (child->widget,
allocation->width, allocation->width,
&sizes[i].minimum_size, &sizes[i].minimum_size,
&sizes[i].natural_size); &sizes[i].natural_size,
NULL, NULL);
/* Assert the api is working properly */ /* Assert the api is working properly */
if (sizes[i].minimum_size < 0) if (sizes[i].minimum_size < 0)
@@ -537,28 +571,9 @@ gtk_box_size_allocate (GtkWidget *widget,
extra = 0; extra = 0;
} }
/* Allocate child positions. */ /* Allocate child sizes. */
for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing) for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
{ {
if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
{
child_allocation.y = allocation->y;
child_allocation.height = MAX (1, allocation->height);
if (packing == GTK_PACK_START)
x = allocation->x;
else
x = allocation->x + allocation->width;
}
else
{
child_allocation.x = allocation->x;
child_allocation.width = MAX (1, allocation->width);
if (packing == GTK_PACK_START)
y = allocation->y;
else
y = allocation->y + allocation->height;
}
for (i = 0, children = private->children; for (i = 0, children = private->children;
children; children;
children = children->next) children = children->next)
@@ -605,6 +620,105 @@ gtk_box_size_allocate (GtkWidget *widget,
} }
} }
sizes[i].natural_size = child_size;
if (private->orientation == GTK_ORIENTATION_HORIZONTAL &&
gtk_widget_get_valign_with_baseline (child->widget) == GTK_ALIGN_BASELINE)
{
int child_allocation_width;
int child_minimum_height, child_natural_height;
if (child->fill)
child_allocation_width = MAX (1, child_size - child->padding * 2);
else
child_allocation_width = sizes[i].minimum_size;
child_minimum_baseline = -1;
child_natural_baseline = -1;
gtk_widget_get_preferred_height_and_baseline_for_width (child->widget,
child_allocation_width,
&child_minimum_height, &child_natural_height,
&child_minimum_baseline, &child_natural_baseline);
if (child_minimum_baseline >= 0)
{
have_baseline = TRUE;
minimum_below = MAX (minimum_below, child_minimum_height - child_minimum_baseline);
natural_below = MAX (natural_below, child_natural_height - child_natural_baseline);
minimum_above = MAX (minimum_above, child_minimum_baseline);
natural_above = MAX (natural_above, child_natural_baseline);
}
}
i++;
}
}
baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline == -1 && have_baseline)
{
gint height = MAX (1, allocation->height);
/* TODO: This is purely based on the minimum baseline, when things fit we should
use the natural one? */
switch (private->baseline_pos)
{
case GTK_BASELINE_POSITION_TOP:
baseline = minimum_above;
break;
case GTK_BASELINE_POSITION_CENTER:
baseline = minimum_above + (height - (minimum_above + minimum_below)) / 2;
break;
case GTK_BASELINE_POSITION_BOTTOM:
baseline = height - minimum_below;
break;
}
}
/* Allocate child positions. */
for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
{
if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
{
child_allocation.y = allocation->y;
child_allocation.height = MAX (1, allocation->height);
if (packing == GTK_PACK_START)
x = allocation->x;
else
x = allocation->x + allocation->width;
}
else
{
child_allocation.x = allocation->x;
child_allocation.width = MAX (1, allocation->width);
if (packing == GTK_PACK_START)
y = allocation->y;
else
y = allocation->y + allocation->height;
}
for (i = 0, children = private->children;
children;
children = children->next)
{
child = children->data;
/* If widget is not visible, skip it. */
if (!gtk_widget_get_visible (child->widget))
continue;
/* If widget is packed differently skip it, but still increment i,
* since widget is visible and will be handled in next loop iteration.
*/
if (child->pack != packing)
{
i++;
continue;
}
child_size = sizes[i].natural_size;
/* Assign the child's position. */ /* Assign the child's position. */
if (private->orientation == GTK_ORIENTATION_HORIZONTAL) if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
{ {
@@ -658,7 +772,7 @@ gtk_box_size_allocate (GtkWidget *widget,
child_allocation.y -= child_size; child_allocation.y -= child_size;
} }
} }
gtk_widget_size_allocate (child->widget, &child_allocation); gtk_widget_size_allocate_with_baseline (child->widget, &child_allocation, baseline);
i++; i++;
} }
@@ -1015,18 +1129,28 @@ static void
gtk_box_get_size (GtkWidget *widget, gtk_box_get_size (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkBox *box; GtkBox *box;
GtkBoxPrivate *private; GtkBoxPrivate *private;
GList *children; GList *children;
gint nvis_children; gint nvis_children;
gint minimum, natural; gint minimum, natural;
gint minimum_above, natural_above;
gint minimum_below, natural_below;
gboolean have_baseline;
gint min_baseline, nat_baseline;
box = GTK_BOX (widget); box = GTK_BOX (widget);
private = box->priv; private = box->priv;
have_baseline = FALSE;
minimum = natural = 0; minimum = natural = 0;
minimum_above = natural_above = 0;
minimum_below = natural_below = 0;
min_baseline = nat_baseline = -1;
nvis_children = 0; nvis_children = 0;
@@ -1037,13 +1161,15 @@ gtk_box_get_size (GtkWidget *widget,
if (gtk_widget_get_visible (child->widget)) if (gtk_widget_get_visible (child->widget))
{ {
gint child_minimum, child_natural; gint child_minimum, child_natural;
gint child_minimum_baseline = -1, child_natural_baseline = -1;
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_get_preferred_width (child->widget, gtk_widget_get_preferred_width (child->widget,
&child_minimum, &child_natural); &child_minimum, &child_natural);
else else
gtk_widget_get_preferred_height (child->widget, gtk_widget_get_preferred_height_and_baseline_for_width (child->widget, -1,
&child_minimum, &child_natural); &child_minimum, &child_natural,
&child_minimum_baseline, &child_natural_baseline);
if (private->orientation == orientation) if (private->orientation == orientation)
{ {
@@ -1063,12 +1189,23 @@ gtk_box_get_size (GtkWidget *widget,
natural += child_natural + child->padding * 2; natural += child_natural + child->padding * 2;
} }
} }
else
{
if (child_minimum_baseline >= 0)
{
have_baseline = TRUE;
minimum_below = MAX (minimum_below, child_minimum - child_minimum_baseline);
natural_below = MAX (natural_below, child_natural - child_natural_baseline);
minimum_above = MAX (minimum_above, child_minimum_baseline);
natural_above = MAX (natural_above, child_natural_baseline);
}
else else
{ {
/* The biggest mins and naturals in the opposing orientation */ /* The biggest mins and naturals in the opposing orientation */
minimum = MAX (minimum, child_minimum); minimum = MAX (minimum, child_minimum);
natural = MAX (natural, child_natural); natural = MAX (natural, child_natural);
} }
}
nvis_children += 1; nvis_children += 1;
} }
@@ -1085,11 +1222,23 @@ gtk_box_get_size (GtkWidget *widget,
natural += (nvis_children - 1) * private->spacing; natural += (nvis_children - 1) * private->spacing;
} }
if (have_baseline)
{
min_baseline = minimum_above;
nat_baseline = natural_above;
}
if (minimum_size) if (minimum_size)
*minimum_size = minimum; *minimum_size = MAX (minimum, minimum_below + minimum_above);
if (natural_size) if (natural_size)
*natural_size = natural; *natural_size = MAX (natural, natural_below + natural_above);
if (minimum_baseline)
*minimum_baseline = min_baseline;
if (natural_baseline)
*natural_baseline = nat_baseline;
} }
static void static void
@@ -1097,7 +1246,7 @@ gtk_box_get_preferred_width (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_box_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size); gtk_box_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -1105,14 +1254,16 @@ gtk_box_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_box_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size); gtk_box_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size, NULL, NULL);
} }
static void static void
gtk_box_compute_size_for_opposing_orientation (GtkBox *box, gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
gint avail_size, gint avail_size,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkBoxPrivate *private = box->priv; GtkBoxPrivate *private = box->priv;
GtkBoxChild *child; GtkBoxChild *child;
@@ -1120,11 +1271,16 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
gint nvis_children; gint nvis_children;
gint nexpand_children; gint nexpand_children;
gint computed_minimum = 0, computed_natural = 0; gint computed_minimum = 0, computed_natural = 0;
gint computed_minimum_above = 0, computed_natural_above = 0;
gint computed_minimum_below = 0, computed_natural_below = 0;
gint computed_minimum_baseline = -1, computed_natural_baseline = -1;
GtkRequestedSize *sizes; GtkRequestedSize *sizes;
GtkPackType packing; GtkPackType packing;
gint size, extra, i; gint size, extra, i;
gint child_size, child_minimum, child_natural; gint child_size, child_minimum, child_natural;
gint child_minimum_baseline, child_natural_baseline;
gint n_extra_widgets = 0; gint n_extra_widgets = 0;
gboolean have_baseline;
count_expand_children (box, &nvis_children, &nexpand_children); count_expand_children (box, &nvis_children, &nexpand_children);
@@ -1199,6 +1355,7 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
extra = 0; extra = 0;
} }
have_baseline = FALSE;
/* Allocate child positions. */ /* Allocate child positions. */
for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing) for (packing = GTK_PACK_START; packing <= GTK_PACK_END; ++packing)
{ {
@@ -1260,26 +1417,64 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
} }
child_minimum_baseline = child_natural_baseline = -1;
/* Assign the child's position. */ /* Assign the child's position. */
if (private->orientation == GTK_ORIENTATION_HORIZONTAL) if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_get_preferred_height_for_width (child->widget, gtk_widget_get_preferred_height_and_baseline_for_width (child->widget, child_size,
child_size, &child_minimum, &child_natural); &child_minimum, &child_natural,
&child_minimum_baseline, &child_natural_baseline);
else /* (private->orientation == GTK_ORIENTATION_VERTICAL) */ else /* (private->orientation == GTK_ORIENTATION_VERTICAL) */
gtk_widget_get_preferred_width_for_height (child->widget, gtk_widget_get_preferred_width_for_height (child->widget,
child_size, &child_minimum, &child_natural); child_size, &child_minimum, &child_natural);
if (child_minimum_baseline >= 0)
{
have_baseline = TRUE;
computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
}
else
{
computed_minimum = MAX (computed_minimum, child_minimum); computed_minimum = MAX (computed_minimum, child_minimum);
computed_natural = MAX (computed_natural, child_natural); computed_natural = MAX (computed_natural, child_natural);
} }
}
i += 1; i += 1;
} }
} }
if (have_baseline)
{
computed_minimum = MAX (computed_minimum, computed_minimum_below + computed_minimum_above);
computed_natural = MAX (computed_natural, computed_natural_below + computed_natural_above);
switch (private->baseline_pos)
{
case GTK_BASELINE_POSITION_TOP:
computed_minimum_baseline = computed_minimum_above;
computed_natural_baseline = computed_natural_above;
break;
case GTK_BASELINE_POSITION_CENTER:
computed_minimum_baseline = computed_minimum_above + MAX((computed_minimum - (computed_minimum_above + computed_minimum_below)) / 2, 0);
computed_natural_baseline = computed_natural_above + MAX((computed_natural - (computed_natural_above + computed_natural_below)) / 2, 0);
break;
case GTK_BASELINE_POSITION_BOTTOM:
computed_minimum_baseline = computed_minimum - computed_minimum_below;
computed_natural_baseline = computed_natural - computed_natural_below;
break;
}
}
if (minimum_baseline)
*minimum_baseline = computed_minimum_baseline;
if (natural_baseline)
*natural_baseline = computed_natural_baseline;
if (minimum_size) if (minimum_size)
*minimum_size = computed_minimum; *minimum_size = computed_minimum;
if (natural_size) if (natural_size)
*natural_size = computed_natural; *natural_size = MAX (computed_natural, computed_natural_below + computed_natural_above);
} }
static void static void
@@ -1355,24 +1550,46 @@ gtk_box_get_preferred_width_for_height (GtkWidget *widget,
GtkBoxPrivate *private = box->priv; GtkBoxPrivate *private = box->priv;
if (private->orientation == GTK_ORIENTATION_VERTICAL) if (private->orientation == GTK_ORIENTATION_VERTICAL)
gtk_box_compute_size_for_opposing_orientation (box, height, minimum_width, natural_width); gtk_box_compute_size_for_opposing_orientation (box, height, minimum_width, natural_width, NULL, NULL);
else else
gtk_box_compute_size_for_orientation (box, height, minimum_width, natural_width); gtk_box_compute_size_for_orientation (box, height, minimum_width, natural_width);
} }
static void
gtk_box_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline)
{
GtkBox *box = GTK_BOX (widget);
GtkBoxPrivate *private = box->priv;
if (width < 0)
gtk_box_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_height, natural_height, minimum_baseline, natural_baseline);
else
{
if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_box_compute_size_for_opposing_orientation (box, width, minimum_height, natural_height, minimum_baseline, natural_baseline);
else
{
if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
gtk_box_compute_size_for_orientation (box, width, minimum_height, natural_height);
}
}
}
static void static void
gtk_box_get_preferred_height_for_width (GtkWidget *widget, gtk_box_get_preferred_height_for_width (GtkWidget *widget,
gint width, gint width,
gint *minimum_height, gint *minimum_height,
gint *natural_height) gint *natural_height)
{ {
GtkBox *box = GTK_BOX (widget); gtk_box_get_preferred_height_and_baseline_for_width (widget, width, minimum_height, natural_height, NULL, NULL);
GtkBoxPrivate *private = box->priv;
if (private->orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_box_compute_size_for_opposing_orientation (box, width, minimum_height, natural_height);
else
gtk_box_compute_size_for_orientation (box, width, minimum_height, natural_height);
} }
/** /**
@@ -1550,6 +1767,35 @@ gtk_box_get_spacing (GtkBox *box)
return box->priv->spacing; return box->priv->spacing;
} }
void
gtk_box_set_baseline_position (GtkBox *box,
GtkBaselinePosition position)
{
GtkBoxPrivate *private;
g_return_if_fail (GTK_IS_BOX (box));
private = box->priv;
if (position != private->baseline_pos)
{
private->baseline_pos = position;
g_object_notify (G_OBJECT (box), "baseline-position");
gtk_widget_queue_resize (GTK_WIDGET (box));
}
}
GtkBaselinePosition
gtk_box_get_baseline_position (GtkBox *box)
{
g_return_val_if_fail (GTK_IS_BOX (box), GTK_BASELINE_POSITION_CENTER);
return box->priv->baseline_pos;
}
void void
_gtk_box_set_spacing_set (GtkBox *box, _gtk_box_set_spacing_set (GtkBox *box,
gboolean spacing_set) gboolean spacing_set)

View File

@@ -89,6 +89,9 @@ gboolean gtk_box_get_homogeneous (GtkBox *box);
void gtk_box_set_spacing (GtkBox *box, void gtk_box_set_spacing (GtkBox *box,
gint spacing); gint spacing);
gint gtk_box_get_spacing (GtkBox *box); gint gtk_box_get_spacing (GtkBox *box);
void gtk_box_set_baseline_position (GtkBox *box,
GtkBaselinePosition position);
GtkBaselinePosition gtk_box_get_baseline_position (GtkBox *box);
void gtk_box_reorder_child (GtkBox *box, void gtk_box_reorder_child (GtkBox *box,
GtkWidget *child, GtkWidget *child,

View File

@@ -170,6 +170,12 @@ static void gtk_button_get_preferred_width (GtkWidget *widget,
static void gtk_button_get_preferred_height (GtkWidget *widget, static void gtk_button_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void gtk_button_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_size,
gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline);
static guint button_signals[LAST_SIGNAL] = { 0 }; static guint button_signals[LAST_SIGNAL] = { 0 };
@@ -196,6 +202,7 @@ gtk_button_class_init (GtkButtonClass *klass)
widget_class->get_preferred_width = gtk_button_get_preferred_width; widget_class->get_preferred_width = gtk_button_get_preferred_width;
widget_class->get_preferred_height = gtk_button_get_preferred_height; widget_class->get_preferred_height = gtk_button_get_preferred_height;
widget_class->get_preferred_height_and_baseline_for_width = gtk_button_get_preferred_height_and_baseline_for_width;
widget_class->destroy = gtk_button_destroy; widget_class->destroy = gtk_button_destroy;
widget_class->screen_changed = gtk_button_screen_changed; widget_class->screen_changed = gtk_button_screen_changed;
widget_class->realize = gtk_button_realize; widget_class->realize = gtk_button_realize;
@@ -1150,11 +1157,15 @@ gtk_button_construct_child (GtkButton *button)
else else
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, image_spacing); box = gtk_box_new (GTK_ORIENTATION_VERTICAL, image_spacing);
gtk_widget_set_valign (box, GTK_ALIGN_BASELINE);
if (priv->align_set) if (priv->align_set)
align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0); align = gtk_alignment_new (priv->xalign, priv->yalign, 0.0, 0.0);
else else
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
gtk_widget_set_valign (align, GTK_ALIGN_BASELINE);
if (priv->image_position == GTK_POS_LEFT || if (priv->image_position == GTK_POS_LEFT ||
priv->image_position == GTK_POS_TOP) priv->image_position == GTK_POS_TOP)
gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box), priv->image, FALSE, FALSE, 0);
@@ -1172,6 +1183,8 @@ gtk_button_construct_child (GtkButton *button)
else else
label = gtk_label_new (label_text); label = gtk_label_new (label_text);
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
if (priv->image_position == GTK_POS_RIGHT || if (priv->image_position == GTK_POS_RIGHT ||
priv->image_position == GTK_POS_BOTTOM) priv->image_position == GTK_POS_BOTTOM)
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
@@ -1196,6 +1209,8 @@ gtk_button_construct_child (GtkButton *button)
else else
label = gtk_label_new (priv->label_text); label = gtk_label_new (priv->label_text);
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
if (priv->align_set) if (priv->align_set)
gtk_misc_set_alignment (GTK_MISC (label), priv->xalign, priv->yalign); gtk_misc_set_alignment (GTK_MISC (label), priv->xalign, priv->yalign);
@@ -1584,6 +1599,7 @@ gtk_button_size_allocate (GtkWidget *widget,
GtkBorder border; GtkBorder border;
gint focus_width; gint focus_width;
gint focus_pad; gint focus_pad;
gint baseline;
context = gtk_widget_get_style_context (widget); context = gtk_widget_get_style_context (widget);
@@ -1651,7 +1667,10 @@ gtk_button_size_allocate (GtkWidget *widget,
child_allocation.width = MAX (1, child_allocation.width); child_allocation.width = MAX (1, child_allocation.width);
child_allocation.height = MAX (1, child_allocation.height); child_allocation.height = MAX (1, child_allocation.height);
gtk_widget_size_allocate (child, &child_allocation); baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline != -1)
baseline -= child_allocation.y - allocation->y;
gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline);
} }
} }
@@ -2063,7 +2082,9 @@ static void
gtk_button_get_size (GtkWidget *widget, gtk_button_get_size (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkButton *button = GTK_BUTTON (widget); GtkButton *button = GTK_BUTTON (widget);
GtkStyleContext *context; GtkStyleContext *context;
@@ -2074,6 +2095,7 @@ gtk_button_get_size (GtkWidget *widget,
gint focus_width; gint focus_width;
gint focus_pad; gint focus_pad;
gint minimum, natural; gint minimum, natural;
gint top_offset;
context = gtk_widget_get_style_context (widget); context = gtk_widget_get_style_context (widget);
@@ -2084,6 +2106,8 @@ gtk_button_get_size (GtkWidget *widget,
"focus-padding", &focus_pad, "focus-padding", &focus_pad,
NULL); NULL);
top_offset = 0;
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
{ {
minimum = padding.left + padding.right + minimum = padding.left + padding.right +
@@ -2097,8 +2121,13 @@ gtk_button_get_size (GtkWidget *widget,
minimum = padding.top + padding.bottom + minimum = padding.top + padding.bottom +
border.top + border.bottom; border.top + border.bottom;
top_offset = padding.top + border.top + focus_width + focus_pad;
if (gtk_widget_get_can_default (GTK_WIDGET (widget))) if (gtk_widget_get_can_default (GTK_WIDGET (widget)))
{
minimum += default_border.top + default_border.bottom; minimum += default_border.top + default_border.bottom;
top_offset += default_border.top;
}
} }
minimum += 2 * (focus_width + focus_pad); minimum += 2 * (focus_width + focus_pad);
@@ -2108,11 +2137,17 @@ gtk_button_get_size (GtkWidget *widget,
gtk_widget_get_visible (child)) gtk_widget_get_visible (child))
{ {
gint child_min, child_nat; gint child_min, child_nat;
gint child_min_baseline = -1, child_nat_baseline = -1;
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_widget_get_preferred_width (child, &child_min, &child_nat); gtk_widget_get_preferred_width (child, &child_min, &child_nat);
else else
gtk_widget_get_preferred_height (child, &child_min, &child_nat); gtk_widget_get_preferred_height_and_baseline_for_width (child, -1, &child_min, &child_nat, &child_min_baseline, &child_nat_baseline);
if (minimum_baseline && child_min_baseline >= 0)
*minimum_baseline = child_min_baseline + top_offset;
if (natural_baseline && child_nat_baseline >= 0)
*natural_baseline = child_nat_baseline + top_offset;
minimum += child_min; minimum += child_min;
natural += child_nat; natural += child_nat;
@@ -2130,7 +2165,7 @@ gtk_button_get_preferred_width (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size); gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -2138,7 +2173,20 @@ gtk_button_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size); gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size, NULL, NULL);
}
static void
gtk_button_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_size,
gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{
/* GtkButton is GTK_SIZE_REQUEST_CONSTANT mode, so width will be -1 all the time */
g_assert (width == -1);
gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size, minimum_baseline, natural_baseline);
} }
/** /**

View File

@@ -309,12 +309,17 @@ static void gtk_container_adjust_size_request (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void gtk_container_adjust_baseline_request (GtkWidget *widget,
gint *minimum_baseline,
gint *natural_baseline);
static void gtk_container_adjust_size_allocation (GtkWidget *widget, static void gtk_container_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size, gint *natural_size,
gint *allocated_pos, gint *allocated_pos,
gint *allocated_size); gint *allocated_size);
static void gtk_container_adjust_baseline_allocation (GtkWidget *widget,
gint *baseline);
static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget); static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget);
static gchar* gtk_container_child_default_composite_name (GtkContainer *container, static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
@@ -444,7 +449,9 @@ gtk_container_class_init (GtkContainerClass *class)
widget_class->focus = gtk_container_focus; widget_class->focus = gtk_container_focus;
widget_class->adjust_size_request = gtk_container_adjust_size_request; widget_class->adjust_size_request = gtk_container_adjust_size_request;
widget_class->adjust_baseline_request = gtk_container_adjust_baseline_request;
widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation; widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation;
widget_class->adjust_baseline_allocation = gtk_container_adjust_baseline_allocation;
widget_class->get_request_mode = gtk_container_get_request_mode; widget_class->get_request_mode = gtk_container_get_request_mode;
class->add = gtk_container_add_unimplemented; class->add = gtk_container_add_unimplemented;
@@ -1917,6 +1924,28 @@ gtk_container_adjust_size_request (GtkWidget *widget,
minimum_size, natural_size); minimum_size, natural_size);
} }
static void
gtk_container_adjust_baseline_request (GtkWidget *widget,
gint *minimum_baseline,
gint *natural_baseline)
{
GtkContainer *container;
container = GTK_CONTAINER (widget);
if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
{
int border_width;
border_width = container->priv->border_width;
*minimum_baseline += border_width;
*natural_baseline += border_width;
}
parent_class->adjust_baseline_request (widget, minimum_baseline, natural_baseline);
}
static void static void
gtk_container_adjust_size_allocation (GtkWidget *widget, gtk_container_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
@@ -1952,6 +1981,27 @@ gtk_container_adjust_size_allocation (GtkWidget *widget,
allocated_size); allocated_size);
} }
static void
gtk_container_adjust_baseline_allocation (GtkWidget *widget,
gint *baseline)
{
GtkContainer *container;
int border_width;
container = GTK_CONTAINER (widget);
if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
{
border_width = container->priv->border_width;
if (*baseline >= 0)
*baseline -= border_width;
}
parent_class->adjust_baseline_allocation (widget, baseline);
}
typedef struct { typedef struct {
gint hfw; gint hfw;
gint wfh; gint wfh;

View File

@@ -70,7 +70,8 @@ typedef enum
GTK_ALIGN_FILL, GTK_ALIGN_FILL,
GTK_ALIGN_START, GTK_ALIGN_START,
GTK_ALIGN_END, GTK_ALIGN_END,
GTK_ALIGN_CENTER GTK_ALIGN_CENTER,
GTK_ALIGN_BASELINE
} GtkAlign; } GtkAlign;
@@ -125,6 +126,20 @@ typedef enum
GTK_FILL = 1 << 2 GTK_FILL = 1 << 2
} GtkAttachOptions; } GtkAttachOptions;
/**
* GtkBaselinePosition:
* @GTK_BASELINE_POSITION_TOP:
* @GTK_BASELINE_POSITION_CENTER:
* @GTK_BASELINE_POSITION_BOTTOM:
*
*/
typedef enum
{
GTK_BASELINE_POSITION_TOP,
GTK_BASELINE_POSITION_CENTER,
GTK_BASELINE_POSITION_BOTTOM
} GtkBaselinePosition;
/** /**
* GtkButtonBoxStyle: * GtkButtonBoxStyle:
* @GTK_BUTTONBOX_DEFAULT_STYLE: Default packing. * @GTK_BUTTONBOX_DEFAULT_STYLE: Default packing.

View File

@@ -519,6 +519,12 @@ static void gtk_label_get_preferred_height_for_width (GtkWidget
gint width, gint width,
gint *minimum_height, gint *minimum_height,
gint *natural_height); gint *natural_height);
static void gtk_label_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline);
static GtkBuildableIface *buildable_parent_iface = NULL; static GtkBuildableIface *buildable_parent_iface = NULL;
@@ -585,6 +591,7 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->get_preferred_height = gtk_label_get_preferred_height; widget_class->get_preferred_height = gtk_label_get_preferred_height;
widget_class->get_preferred_width_for_height = gtk_label_get_preferred_width_for_height; widget_class->get_preferred_width_for_height = gtk_label_get_preferred_width_for_height;
widget_class->get_preferred_height_for_width = gtk_label_get_preferred_height_for_width; widget_class->get_preferred_height_for_width = gtk_label_get_preferred_height_for_width;
widget_class->get_preferred_height_and_baseline_for_width = gtk_label_get_preferred_height_and_baseline_for_width;
class->move_cursor = gtk_label_move_cursor; class->move_cursor = gtk_label_move_cursor;
class->copy_clipboard = gtk_label_copy_clipboard; class->copy_clipboard = gtk_label_copy_clipboard;
@@ -3434,15 +3441,18 @@ gtk_label_get_request_mode (GtkWidget *widget)
return GTK_SIZE_REQUEST_CONSTANT_SIZE; return GTK_SIZE_REQUEST_CONSTANT_SIZE;
} }
static void static void
get_size_for_allocation (GtkLabel *label, get_size_for_allocation (GtkLabel *label,
GtkOrientation orientation, GtkOrientation orientation,
gint allocation, gint allocation,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
PangoLayout *layout; PangoLayout *layout;
gint text_height; gint text_height, baseline;
layout = gtk_label_get_measuring_layout (label, NULL, allocation * PANGO_SCALE); layout = gtk_label_get_measuring_layout (label, NULL, allocation * PANGO_SCALE);
@@ -3454,6 +3464,16 @@ get_size_for_allocation (GtkLabel *label,
if (natural_size) if (natural_size)
*natural_size = text_height; *natural_size = text_height;
if (minimum_baseline || natural_baseline)
{
baseline = pango_layout_get_baseline (layout) / PANGO_SCALE;
if (minimum_baseline)
*minimum_baseline = baseline;
if (natural_baseline)
*natural_baseline = baseline;
}
g_object_unref (layout); g_object_unref (layout);
} }
@@ -3550,7 +3570,9 @@ static void
gtk_label_get_preferred_size (GtkWidget *widget, gtk_label_get_preferred_size (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkLabel *label = GTK_LABEL (widget); GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = label->priv; GtkLabelPrivate *priv = label->priv;
@@ -3558,6 +3580,12 @@ gtk_label_get_preferred_size (GtkWidget *widget,
PangoRectangle smallest_rect; PangoRectangle smallest_rect;
GtkBorder border; GtkBorder border;
if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
gtk_label_get_preferred_layout_size (label, &smallest_rect, &widest_rect); gtk_label_get_preferred_layout_size (label, &smallest_rect, &widest_rect);
/* Now that we have minimum and natural sizes in pango extents, apply a possible transform */ /* Now that we have minimum and natural sizes in pango extents, apply a possible transform */
@@ -3612,7 +3640,8 @@ gtk_label_get_preferred_size (GtkWidget *widget,
get_size_for_allocation (label, get_size_for_allocation (label,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
smallest_rect.height, smallest_rect.height,
minimum_size, natural_size); minimum_size, natural_size,
NULL, NULL);
} }
else else
@@ -3639,7 +3668,16 @@ gtk_label_get_preferred_size (GtkWidget *widget,
get_size_for_allocation (label, get_size_for_allocation (label,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
widest_rect.width, widest_rect.width,
minimum_size, natural_size); minimum_size, natural_size,
minimum_baseline, natural_baseline);
if (priv->angle == 180)
{
if (minimum_baseline)
*minimum_baseline = *minimum_size - *minimum_baseline;
if (natural_baseline)
*natural_baseline = *natural_size - *natural_baseline;
}
} }
else else
{ {
@@ -3652,6 +3690,12 @@ gtk_label_get_preferred_size (GtkWidget *widget,
*minimum_size += border.top + border.bottom; *minimum_size += border.top + border.bottom;
*natural_size += border.top + border.bottom; *natural_size += border.top + border.bottom;
if (minimum_baseline && *minimum_baseline != -1)
*minimum_baseline += border.top;
if (natural_baseline && *natural_baseline != -1)
*natural_baseline += border.top;
} }
} }
@@ -3660,7 +3704,7 @@ gtk_label_get_preferred_width (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_label_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size); gtk_label_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -3668,7 +3712,7 @@ gtk_label_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size)
{ {
gtk_label_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size); gtk_label_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size, NULL, NULL);
} }
static void static void
@@ -3691,7 +3735,8 @@ gtk_label_get_preferred_width_for_height (GtkWidget *widget,
get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL, get_size_for_allocation (label, GTK_ORIENTATION_VERTICAL,
MAX (1, height - border.top - border.bottom), MAX (1, height - border.top - border.bottom),
minimum_width, natural_width); minimum_width, natural_width,
NULL, NULL);
if (minimum_width) if (minimum_width)
*minimum_width += border.right + border.left; *minimum_width += border.right + border.left;
@@ -3704,15 +3749,17 @@ gtk_label_get_preferred_width_for_height (GtkWidget *widget,
} }
static void static void
gtk_label_get_preferred_height_for_width (GtkWidget *widget, gtk_label_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width, gint width,
gint *minimum_height, gint *minimum_height,
gint *natural_height) gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GtkLabel *label = GTK_LABEL (widget); GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = label->priv; GtkLabelPrivate *priv = label->priv;
if (priv->wrap && (priv->angle == 0 || priv->angle == 180 || priv->angle == 360)) if (width != -1 && priv->wrap && (priv->angle == 0 || priv->angle == 180 || priv->angle == 360))
{ {
GtkBorder border; GtkBorder border;
@@ -3723,7 +3770,13 @@ gtk_label_get_preferred_height_for_width (GtkWidget *widget,
get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL, get_size_for_allocation (label, GTK_ORIENTATION_HORIZONTAL,
MAX (1, width - border.left - border.right), MAX (1, width - border.left - border.right),
minimum_height, natural_height); minimum_height, natural_height,
minimum_baseline, natural_baseline);
if (minimum_baseline && *minimum_baseline >= 0)
*minimum_baseline += border.top;
if (natural_baseline && *natural_baseline >= 0)
*natural_baseline += border.top;
if (minimum_height) if (minimum_height)
*minimum_height += border.top + border.bottom; *minimum_height += border.top + border.bottom;
@@ -3732,7 +3785,18 @@ gtk_label_get_preferred_height_for_width (GtkWidget *widget,
*natural_height += border.top + border.bottom; *natural_height += border.top + border.bottom;
} }
else else
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height); gtk_label_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, minimum_height, natural_height, minimum_baseline, natural_baseline);
}
static void
gtk_label_get_preferred_height_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height)
{
return gtk_label_get_preferred_height_and_baseline_for_width (widget, width,
minimum_height, natural_height,
NULL, NULL);
} }
static void static void
@@ -3827,6 +3891,7 @@ get_layout_location (GtkLabel *label,
gint req_height; gint req_height;
gfloat xalign, yalign; gfloat xalign, yalign;
PangoRectangle logical; PangoRectangle logical;
gint baseline, layout_baseline, baseline_offset;
misc = GTK_MISC (label); misc = GTK_MISC (label);
widget = GTK_WIDGET (label); widget = GTK_WIDGET (label);
@@ -3859,6 +3924,15 @@ get_layout_location (GtkLabel *label,
x = floor (allocation.x + border.left + xalign * (allocation.width - req_width) - logical.x); x = floor (allocation.x + border.left + xalign * (allocation.width - req_width) - logical.x);
baseline_offset = 0;
baseline = gtk_widget_get_allocated_baseline (widget);
if (baseline >= 0 && !priv->have_transform)
{
layout_baseline = pango_layout_get_baseline (priv->layout) / PANGO_SCALE;
baseline_offset = baseline - layout_baseline;
yalign = 0.0; /* Can't support yalign while baseline aligning */
}
/* bgo#315462 - For single-line labels, *do* align the requisition with /* bgo#315462 - For single-line labels, *do* align the requisition with
* respect to the allocation, even if we are under-allocated. For multi-line * respect to the allocation, even if we are under-allocated. For multi-line
* labels, always show the top of the text when they are under-allocated. The * labels, always show the top of the text when they are under-allocated. The
@@ -3873,9 +3947,9 @@ get_layout_location (GtkLabel *label,
* middle". You want to read the first line, at least, to get some context. * middle". You want to read the first line, at least, to get some context.
*/ */
if (pango_layout_get_line_count (priv->layout) == 1) if (pango_layout_get_line_count (priv->layout) == 1)
y = floor (allocation.y + border.top + (allocation.height - req_height) * yalign) - logical.y; y = floor (allocation.y + border.top + (allocation.height - req_height) * yalign) - logical.y + baseline_offset;
else else
y = floor (allocation.y + border.top + MAX ((allocation.height - req_height) * yalign, 0)) - logical.y; y = floor (allocation.y + border.top + MAX ((allocation.height - req_height) * yalign, 0)) - logical.y + baseline_offset;
if (xp) if (xp)
*xp = x; *xp = x;

View File

@@ -98,11 +98,16 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum_size, gint *minimum_size,
gint *natural_size) gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline)
{ {
SizeRequestCache *cache; SizeRequestCache *cache;
GtkWidgetClass *widget_class;
gint min_size = 0; gint min_size = 0;
gint nat_size = 0; gint nat_size = 0;
gint min_baseline = -1;
gint nat_baseline = -1;
gboolean found_in_cache; gboolean found_in_cache;
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE)
@@ -113,7 +118,11 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
orientation, orientation,
for_size, for_size,
&min_size, &min_size,
&nat_size); &nat_size,
&min_baseline,
&nat_baseline);
widget_class = GTK_WIDGET_GET_CLASS (widget);
if (!found_in_cache) if (!found_in_cache)
{ {
@@ -126,7 +135,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (for_size < 0) if (for_size < 0)
{ {
push_recursion_check (widget, orientation, for_size); push_recursion_check (widget, orientation, for_size);
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_size, &nat_size); widget_class->get_preferred_width (widget, &min_size, &nat_size);
pop_recursion_check (widget, orientation); pop_recursion_check (widget, orientation);
} }
else else
@@ -140,7 +149,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
gtk_widget_get_preferred_height (widget, &minimum_height, &natural_height); gtk_widget_get_preferred_height (widget, &minimum_height, &natural_height);
/* convert for_size to unadjusted height (for_size is a proposed allocation) */ /* convert for_size to unadjusted height (for_size is a proposed allocation) */
GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget, widget_class->adjust_size_allocation (widget,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
&minimum_height, &minimum_height,
&natural_height, &natural_height,
@@ -148,7 +157,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
&adjusted_for_size); &adjusted_for_size);
push_recursion_check (widget, orientation, for_size); push_recursion_check (widget, orientation, for_size);
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width_for_height (widget, widget_class->get_preferred_width_for_height (widget,
MAX (adjusted_for_size, minimum_height), MAX (adjusted_for_size, minimum_height),
&min_size, &nat_size); &min_size, &nat_size);
pop_recursion_check (widget, orientation); pop_recursion_check (widget, orientation);
@@ -159,7 +168,9 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (for_size < 0) if (for_size < 0)
{ {
push_recursion_check (widget, orientation, for_size); push_recursion_check (widget, orientation, for_size);
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_size, &nat_size); widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
&min_size, &nat_size,
&min_baseline, &nat_baseline);
pop_recursion_check (widget, orientation); pop_recursion_check (widget, orientation);
} }
else else
@@ -173,7 +184,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
gtk_widget_get_preferred_width (widget, &minimum_width, &natural_width); gtk_widget_get_preferred_width (widget, &minimum_width, &natural_width);
/* convert for_size to unadjusted width (for_size is a proposed allocation) */ /* convert for_size to unadjusted width (for_size is a proposed allocation) */
GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget, widget_class->adjust_size_allocation (widget,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
&minimum_width, &minimum_width,
&natural_width, &natural_width,
@@ -181,9 +192,9 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
&adjusted_for_size); &adjusted_for_size);
push_recursion_check (widget, orientation, for_size); push_recursion_check (widget, orientation, for_size);
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, minimum_width),
MAX (adjusted_for_size, minimum_width), &min_size, &nat_size,
&min_size, &nat_size); &min_baseline, &nat_baseline);
pop_recursion_check (widget, orientation); pop_recursion_check (widget, orientation);
} }
} }
@@ -196,7 +207,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
adjusted_min = min_size; adjusted_min = min_size;
adjusted_natural = nat_size; adjusted_natural = nat_size;
GTK_WIDGET_GET_CLASS (widget)->adjust_size_request (widget, widget_class->adjust_size_request (widget,
orientation, orientation,
&adjusted_min, &adjusted_min,
&adjusted_natural); &adjusted_natural);
@@ -227,11 +238,42 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
nat_size = adjusted_natural; nat_size = adjusted_natural;
} }
if (min_baseline != -1 || nat_baseline != -1)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
g_warning ("%s %p reported a horizontal baseline",
G_OBJECT_TYPE_NAME (widget), widget);
min_baseline = -1;
nat_baseline = -1;
}
else if (min_baseline == -1 || nat_baseline == -1)
{
g_warning ("%s %p reported baseline for only one of min/natural (min: %d, natural: %d)",
G_OBJECT_TYPE_NAME (widget), widget,
min_baseline, nat_baseline);
min_baseline = -1;
nat_baseline = -1;
}
else if (gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE)
{
/* Ignore requested baseline for non-aligned widgets */
min_baseline = -1;
nat_baseline = -1;
}
else
widget_class->adjust_baseline_request (widget,
&min_baseline,
&nat_baseline);
}
_gtk_size_request_cache_commit (cache, _gtk_size_request_cache_commit (cache,
orientation, orientation,
for_size, for_size,
min_size, min_size,
nat_size); nat_size,
min_baseline,
nat_baseline);
} }
if (minimum_size) if (minimum_size)
@@ -240,15 +282,26 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (natural_size) if (natural_size)
*natural_size = nat_size; *natural_size = nat_size;
if (minimum_baseline)
*minimum_baseline = min_baseline;
if (natural_baseline)
*natural_baseline = nat_baseline;
g_assert (min_size <= nat_size); g_assert (min_size <= nat_size);
GTK_NOTE (SIZE_REQUEST, GTK_NOTE (SIZE_REQUEST,
g_print ("[%p] %s\t%s: %d is minimum %d and natural: %d (hit cache: %s)\n", g_print ("[%p] %s\t%s: %d is minimum %d and natural: %d",
widget, G_OBJECT_TYPE_NAME (widget), widget, G_OBJECT_TYPE_NAME (widget),
orientation == GTK_ORIENTATION_HORIZONTAL ? orientation == GTK_ORIENTATION_HORIZONTAL ?
"width for height" : "height for width" , "width for height" : "height for width" ,
for_size, min_size, nat_size, for_size, min_size, nat_size);
found_in_cache ? "yes" : "no")); if (min_baseline != -1 || nat_baseline != -1)
g_print (", baseline %d/%d",
min_baseline, nat_baseline);
g_print (" (hit cache: %s)\n",
found_in_cache ? "yes" : "no")
);
} }
/* This is the main function that checks for a cached size and /* This is the main function that checks for a cached size and
@@ -261,7 +314,9 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum, gint *minimum,
gint *natural) gint *natural,
gint *minimum_baseline,
gint *natural_baseline)
{ {
GHashTable *widgets; GHashTable *widgets;
GHashTableIter iter; GHashTableIter iter;
@@ -274,12 +329,17 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
*minimum = 0; *minimum = 0;
if (natural) if (natural)
*natural = 0; *natural = 0;
if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
return; return;
} }
if (G_LIKELY (!_gtk_widget_get_sizegroups (widget))) if (G_LIKELY (!_gtk_widget_get_sizegroups (widget)))
{ {
gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural); gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural,
minimum_baseline, natural_baseline);
return; return;
} }
@@ -293,7 +353,7 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkWidget *tmp_widget = key; GtkWidget *tmp_widget = key;
gint min_dimension, nat_dimension; gint min_dimension, nat_dimension;
gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension, &nat_dimension); gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension, &nat_dimension, NULL, NULL);
min_result = MAX (min_result, min_dimension); min_result = MAX (min_result, min_dimension);
nat_result = MAX (nat_result, nat_dimension); nat_result = MAX (nat_result, nat_dimension);
@@ -303,6 +363,13 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
g_hash_table_destroy (widgets); g_hash_table_destroy (widgets);
/* Baselines make no sense with sizegroups really */
if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
if (minimum) if (minimum)
*minimum = min_result; *minimum = min_result;
@@ -375,7 +442,8 @@ gtk_widget_get_preferred_width (GtkWidget *widget,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
-1, -1,
minimum_width, minimum_width,
natural_width); natural_width,
NULL, NULL);
} }
@@ -409,7 +477,8 @@ gtk_widget_get_preferred_height (GtkWidget *widget,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
-1, -1,
minimum_height, minimum_height,
natural_height); natural_height,
NULL, NULL);
} }
@@ -446,7 +515,8 @@ gtk_widget_get_preferred_width_for_height (GtkWidget *widget,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
height, height,
minimum_width, minimum_width,
natural_width); natural_width,
NULL, NULL);
} }
/** /**
@@ -481,7 +551,29 @@ gtk_widget_get_preferred_height_for_width (GtkWidget *widget,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
width, width,
minimum_height, minimum_height,
natural_height); natural_height,
NULL, NULL);
}
void
gtk_widget_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (minimum_height != NULL || natural_height != NULL);
g_return_if_fail (width >= -1);
_gtk_widget_compute_size_for_orientation (widget,
GTK_ORIENTATION_VERTICAL,
width,
minimum_height,
natural_height,
minimum_baseline,
natural_baseline);
} }
/** /**

View File

@@ -67,7 +67,9 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint minimum_size, gint minimum_size,
gint natural_size) gint natural_size,
gint minimum_baseline,
gint natural_baseline)
{ {
SizeRequest **cached_sizes; SizeRequest **cached_sizes;
SizeRequest *cached_size; SizeRequest *cached_size;
@@ -78,6 +80,8 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
{ {
cache->cached_size[orientation].minimum_size = minimum_size; cache->cached_size[orientation].minimum_size = minimum_size;
cache->cached_size[orientation].natural_size = natural_size; cache->cached_size[orientation].natural_size = natural_size;
cache->cached_size[orientation].minimum_baseline = minimum_baseline;
cache->cached_size[orientation].natural_baseline = natural_baseline;
cache->flags[orientation].cached_size_valid = TRUE; cache->flags[orientation].cached_size_valid = TRUE;
return; return;
} }
@@ -92,7 +96,9 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
for (i = 0; i < n_sizes; i++) for (i = 0; i < n_sizes; i++)
{ {
if (cached_sizes[i]->cached_size.minimum_size == minimum_size && if (cached_sizes[i]->cached_size.minimum_size == minimum_size &&
cached_sizes[i]->cached_size.natural_size == natural_size) cached_sizes[i]->cached_size.natural_size == natural_size &&
cached_sizes[i]->cached_size.minimum_baseline == minimum_baseline &&
cached_sizes[i]->cached_size.natural_baseline == natural_baseline)
{ {
cached_sizes[i]->lower_for_size = MIN (cached_sizes[i]->lower_for_size, for_size); cached_sizes[i]->lower_for_size = MIN (cached_sizes[i]->lower_for_size, for_size);
cached_sizes[i]->upper_for_size = MAX (cached_sizes[i]->upper_for_size, for_size); cached_sizes[i]->upper_for_size = MAX (cached_sizes[i]->upper_for_size, for_size);
@@ -125,6 +131,8 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
cached_size->upper_for_size = for_size; cached_size->upper_for_size = for_size;
cached_size->cached_size.minimum_size = minimum_size; cached_size->cached_size.minimum_size = minimum_size;
cached_size->cached_size.natural_size = natural_size; cached_size->cached_size.natural_size = natural_size;
cached_size->cached_size.minimum_baseline = minimum_baseline;
cached_size->cached_size.natural_baseline = natural_baseline;
} }
/* looks for a cached size request for this for_size. /* looks for a cached size request for this for_size.
@@ -137,7 +145,9 @@ _gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum, gint *minimum,
gint *natural) gint *natural,
gint *minimum_baseline,
gint *natural_baseline)
{ {
CachedSize *result = NULL; CachedSize *result = NULL;
@@ -168,6 +178,8 @@ _gtk_size_request_cache_lookup (SizeRequestCache *cache,
{ {
*minimum = result->minimum_size; *minimum = result->minimum_size;
*natural = result->natural_size; *natural = result->natural_size;
*minimum_baseline = result->minimum_baseline;
*natural_baseline = result->natural_baseline;
return TRUE; return TRUE;
} }
else else

View File

@@ -41,6 +41,8 @@ G_BEGIN_DECLS
typedef struct { typedef struct {
gint minimum_size; gint minimum_size;
gint natural_size; gint natural_size;
gint minimum_baseline;
gint natural_baseline;
} CachedSize; } CachedSize;
typedef struct typedef struct
@@ -72,12 +74,16 @@ void _gtk_size_request_cache_commit (SizeRequestCach
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint minimum_size, gint minimum_size,
gint natural_size); gint natural_size,
gint minimum_baseline,
gint natural_baseline);
gboolean _gtk_size_request_cache_lookup (SizeRequestCache *cache, gboolean _gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum, gint *minimum,
gint *natural); gint *natural,
gint *minimum_baseline,
gint *natural_baseline);
G_END_DECLS G_END_DECLS

View File

@@ -392,6 +392,7 @@ struct _GtkWidgetPrivate
/* The widget's allocated size */ /* The widget's allocated size */
GtkAllocation allocation; GtkAllocation allocation;
gint allocated_baseline;
/* The widget's requested sizes */ /* The widget's requested sizes */
SizeRequestCache requests; SizeRequestCache requests;
@@ -686,6 +687,12 @@ static void gtk_widget_real_get_width (GtkWidget
static void gtk_widget_real_get_height (GtkWidget *widget, static void gtk_widget_real_get_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline);
static void gtk_widget_queue_tooltip_query (GtkWidget *widget); static void gtk_widget_queue_tooltip_query (GtkWidget *widget);
@@ -694,12 +701,17 @@ static void gtk_widget_real_adjust_size_request (GtkWidget
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
gint *minimum_baseline,
gint *natural_baseline);
static void gtk_widget_real_adjust_size_allocation (GtkWidget *widget, static void gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size, gint *natural_size,
gint *allocated_pos, gint *allocated_pos,
gint *allocated_size); gint *allocated_size);
static void gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
gint *baseline);
static void gtk_widget_set_usize_internal (GtkWidget *widget, static void gtk_widget_set_usize_internal (GtkWidget *widget,
gint width, gint width,
@@ -981,6 +993,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->get_preferred_height = gtk_widget_real_get_height; klass->get_preferred_height = gtk_widget_real_get_height;
klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height; klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height;
klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width; klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width;
klass->get_preferred_height_and_baseline_for_width = gtk_widget_real_get_preferred_height_and_baseline_for_width;
klass->state_changed = NULL; klass->state_changed = NULL;
klass->state_flags_changed = gtk_widget_real_state_flags_changed; klass->state_flags_changed = gtk_widget_real_state_flags_changed;
klass->parent_set = NULL; klass->parent_set = NULL;
@@ -1040,7 +1053,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->get_accessible = gtk_widget_real_get_accessible; klass->get_accessible = gtk_widget_real_get_accessible;
klass->adjust_size_request = gtk_widget_real_adjust_size_request; klass->adjust_size_request = gtk_widget_real_adjust_size_request;
klass->adjust_baseline_request = gtk_widget_real_adjust_baseline_request;
klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation; klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation;
klass->adjust_baseline_allocation = gtk_widget_real_adjust_baseline_allocation;
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_NAME, PROP_NAME,
@@ -5185,23 +5200,10 @@ gtk_widget_invalidate_widget_windows (GtkWidget *widget,
invalidate_predicate, widget); invalidate_predicate, widget);
} }
/**
* gtk_widget_size_allocate:
* @widget: a #GtkWidget
* @allocation: position and size to be allocated to @widget
*
* This function is only used by #GtkContainer subclasses, to assign a size
* and position to their child widgets.
*
* In this function, the allocation may be adjusted. It will be forced
* to a 1x1 minimum size, and the adjust_size_allocation virtual
* method on the child will be used to adjust the allocation. Standard
* adjustments include removing the widget's margins, and applying the
* widget's #GtkWidget:halign and #GtkWidget:valign properties.
**/
void void
gtk_widget_size_allocate (GtkWidget *widget, gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
GtkAllocation *allocation) GtkAllocation *allocation,
gint baseline)
{ {
GtkWidgetPrivate *priv; GtkWidgetPrivate *priv;
GdkRectangle real_allocation; GdkRectangle real_allocation;
@@ -5209,9 +5211,11 @@ gtk_widget_size_allocate (GtkWidget *widget,
GdkRectangle adjusted_allocation; GdkRectangle adjusted_allocation;
gboolean alloc_needed; gboolean alloc_needed;
gboolean size_changed; gboolean size_changed;
gboolean baseline_changed;
gboolean position_changed; gboolean position_changed;
gint natural_width, natural_height, dummy; gint natural_width, natural_height, dummy;
gint min_width, min_height; gint min_width, min_height;
gint old_baseline;
priv = widget->priv; priv = widget->priv;
@@ -5238,17 +5242,27 @@ gtk_widget_size_allocate (GtkWidget *widget,
} }
name = g_type_name (G_OBJECT_TYPE (G_OBJECT (widget))); name = g_type_name (G_OBJECT_TYPE (G_OBJECT (widget)));
g_print ("gtk_widget_size_allocate: %*s%s %d %d\n", g_print ("gtk_widget_size_allocate: %*s%s %d %d",
2 * depth, " ", name, 2 * depth, " ", name,
allocation->width, allocation->height); allocation->width, allocation->height);
if (baseline != -1)
g_print (" baseline: %d", baseline);
g_print ("\n");
} }
#endif /* G_ENABLE_DEBUG */ #endif /* G_ENABLE_DEBUG */
/* Never pass a baseline to a child unless it requested it.
This means containers don't have to manually check for this. */
if (baseline != -1 &&
gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE)
baseline = -1;
alloc_needed = priv->alloc_needed; alloc_needed = priv->alloc_needed;
/* Preserve request/allocate ordering */ /* Preserve request/allocate ordering */
priv->alloc_needed = FALSE; priv->alloc_needed = FALSE;
old_allocation = priv->allocation; old_allocation = priv->allocation;
old_baseline = priv->allocated_baseline;
real_allocation = *allocation; real_allocation = *allocation;
adjusted_allocation = real_allocation; adjusted_allocation = real_allocation;
@@ -5298,6 +5312,9 @@ gtk_widget_size_allocate (GtkWidget *widget,
&natural_height, &natural_height,
&adjusted_allocation.y, &adjusted_allocation.y,
&adjusted_allocation.height); &adjusted_allocation.height);
if (baseline >= 0)
GTK_WIDGET_GET_CLASS (widget)->adjust_baseline_allocation (widget,
&baseline);
if (adjusted_allocation.x < real_allocation.x || if (adjusted_allocation.x < real_allocation.x ||
adjusted_allocation.y < real_allocation.y || adjusted_allocation.y < real_allocation.y ||
@@ -5327,14 +5344,16 @@ gtk_widget_size_allocate (GtkWidget *widget,
real_allocation.width = MAX (real_allocation.width, 1); real_allocation.width = MAX (real_allocation.width, 1);
real_allocation.height = MAX (real_allocation.height, 1); real_allocation.height = MAX (real_allocation.height, 1);
baseline_changed = old_baseline != baseline;
size_changed = (old_allocation.width != real_allocation.width || size_changed = (old_allocation.width != real_allocation.width ||
old_allocation.height != real_allocation.height); old_allocation.height != real_allocation.height);
position_changed = (old_allocation.x != real_allocation.x || position_changed = (old_allocation.x != real_allocation.x ||
old_allocation.y != real_allocation.y); old_allocation.y != real_allocation.y);
if (!alloc_needed && !size_changed && !position_changed) if (!alloc_needed && !size_changed && !position_changed && !baseline_changed)
goto out; goto out;
priv->allocated_baseline = baseline;
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation); g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
/* Size allocation is god... after consulting god, no further requests or allocations are needed */ /* Size allocation is god... after consulting god, no further requests or allocations are needed */
@@ -5368,7 +5387,7 @@ gtk_widget_size_allocate (GtkWidget *widget,
} }
} }
if ((size_changed || position_changed) && priv->parent && if ((size_changed || position_changed || baseline_changed) && priv->parent &&
gtk_widget_get_realized (priv->parent) && _gtk_container_get_reallocate_redraws (GTK_CONTAINER (priv->parent))) gtk_widget_get_realized (priv->parent) && _gtk_container_get_reallocate_redraws (GTK_CONTAINER (priv->parent)))
{ {
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->allocation); cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->allocation);
@@ -5380,6 +5399,28 @@ out:
gtk_widget_pop_verify_invariants (widget); gtk_widget_pop_verify_invariants (widget);
} }
/**
* gtk_widget_size_allocate:
* @widget: a #GtkWidget
* @allocation: position and size to be allocated to @widget
*
* This function is only used by #GtkContainer subclasses, to assign a size
* and position to their child widgets.
*
* In this function, the allocation may be adjusted. It will be forced
* to a 1x1 minimum size, and the adjust_size_allocation virtual
* method on the child will be used to adjust the allocation. Standard
* adjustments include removing the widget's margins, and applying the
* widget's #GtkWidget:halign and #GtkWidget:valign properties.
**/
void
gtk_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
gtk_widget_size_allocate_with_baseline (widget, allocation, -1);
}
/** /**
* gtk_widget_common_ancestor: * gtk_widget_common_ancestor:
* @widget_a: a #GtkWidget * @widget_a: a #GtkWidget
@@ -5601,6 +5642,7 @@ adjust_for_align (GtkAlign align,
{ {
switch (align) switch (align)
{ {
case GTK_ALIGN_BASELINE:
case GTK_ALIGN_FILL: case GTK_ALIGN_FILL:
/* change nothing */ /* change nothing */
break; break;
@@ -5671,6 +5713,18 @@ gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
} }
} }
static void
gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
gint *baseline)
{
const GtkWidgetAuxInfo *aux_info;
aux_info = _gtk_widget_get_aux_info_or_defaults (widget);
if (baseline >= 0)
*baseline -= aux_info->margin.top;
}
static gboolean static gboolean
gtk_widget_real_can_activate_accel (GtkWidget *widget, gtk_widget_real_can_activate_accel (GtkWidget *widget,
guint signal_id) guint signal_id)
@@ -11012,6 +11066,28 @@ gtk_widget_real_adjust_size_request (GtkWidget *widget,
} }
} }
static void
gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
gint *minimum_baseline,
gint *natural_baseline)
{
const GtkWidgetAuxInfo *aux_info;
aux_info =_gtk_widget_get_aux_info_or_defaults (widget);
if (aux_info->height >= 0)
{
/* No baseline support for explicitly set height */
*minimum_baseline = -1;
*natural_baseline = -1;
}
else
{
*minimum_baseline += aux_info->margin.top;
*natural_baseline += aux_info->margin.top;
}
}
/** /**
* _gtk_widget_peek_request_cache: * _gtk_widget_peek_request_cache:
* *
@@ -13162,6 +13238,25 @@ gtk_widget_real_get_width_for_height (GtkWidget *widget,
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width); GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
} }
static void
gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline)
{
if (width == -1)
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
else
GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, width, minimum_height, natural_height);
if (minimum_baseline)
*minimum_baseline = -1;
if (natural_baseline)
*natural_baseline = -1;
}
/** /**
* gtk_widget_get_halign: * gtk_widget_get_halign:
* @widget: a #GtkWidget * @widget: a #GtkWidget
@@ -13203,6 +13298,13 @@ gtk_widget_set_halign (GtkWidget *widget,
g_object_notify (G_OBJECT (widget), "halign"); g_object_notify (G_OBJECT (widget), "halign");
} }
GtkAlign
gtk_widget_get_valign_with_baseline (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_ALIGN_FILL);
return _gtk_widget_get_aux_info_or_defaults (widget)->valign;
}
/** /**
* gtk_widget_get_valign: * gtk_widget_get_valign:
* @widget: a #GtkWidget * @widget: a #GtkWidget
@@ -13214,8 +13316,12 @@ gtk_widget_set_halign (GtkWidget *widget,
GtkAlign GtkAlign
gtk_widget_get_valign (GtkWidget *widget) gtk_widget_get_valign (GtkWidget *widget)
{ {
g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_ALIGN_FILL); GtkAlign align;
return _gtk_widget_get_aux_info_or_defaults (widget)->valign;
align = gtk_widget_get_valign_with_baseline (widget);
if (align == GTK_ALIGN_BASELINE)
return GTK_ALIGN_FILL;
return align;
} }
/** /**
@@ -13992,6 +14098,14 @@ gtk_widget_get_allocated_height (GtkWidget *widget)
return widget->priv->allocation.height; return widget->priv->allocation.height;
} }
int
gtk_widget_get_allocated_baseline (GtkWidget *widget)
{
g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
return widget->priv->allocated_baseline;
}
/** /**
* gtk_widget_get_requisition: * gtk_widget_get_requisition:
* @widget: a #GtkWidget * @widget: a #GtkWidget

View File

@@ -433,14 +433,23 @@ struct _GtkWidgetClass
gboolean (* touch_event) (GtkWidget *widget, gboolean (* touch_event) (GtkWidget *widget,
GdkEventTouch *event); GdkEventTouch *event);
void (* get_preferred_height_and_baseline_for_width) (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline);
void (* adjust_baseline_request)(GtkWidget *widget,
gint *minimum_baseline,
gint *natural_baseline);
void (* adjust_baseline_allocation) (GtkWidget *widget,
gint *baseline);
/*< private >*/ /*< private >*/
GtkWidgetClassPrivate *priv; GtkWidgetClassPrivate *priv;
/* Padding for future expansion */ /* Padding for future expansion */
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
void (*_gtk_reserved5) (void); void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void); void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void); void (*_gtk_reserved7) (void);
@@ -498,6 +507,9 @@ void gtk_widget_size_request (GtkWidget *widget,
GtkRequisition *requisition); GtkRequisition *requisition);
void gtk_widget_size_allocate (GtkWidget *widget, void gtk_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation); GtkAllocation *allocation);
void gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
GtkAllocation *allocation,
gint baseline);
GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget); GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget);
void gtk_widget_get_preferred_width (GtkWidget *widget, void gtk_widget_get_preferred_width (GtkWidget *widget,
@@ -514,6 +526,12 @@ void gtk_widget_get_preferred_width_for_height (GtkWidget *w
gint height, gint height,
gint *minimum_width, gint *minimum_width,
gint *natural_width); gint *natural_width);
void gtk_widget_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
gint width,
gint *minimum_height,
gint *natural_height,
gint *minimum_baseline,
gint *natural_baseline);
void gtk_widget_get_preferred_size (GtkWidget *widget, void gtk_widget_get_preferred_size (GtkWidget *widget,
GtkRequisition *minimum_size, GtkRequisition *minimum_size,
GtkRequisition *natural_size); GtkRequisition *natural_size);
@@ -659,6 +677,7 @@ void gtk_widget_unregister_window (GtkWidget *widget,
int gtk_widget_get_allocated_width (GtkWidget *widget); int gtk_widget_get_allocated_width (GtkWidget *widget);
int gtk_widget_get_allocated_height (GtkWidget *widget); int gtk_widget_get_allocated_height (GtkWidget *widget);
int gtk_widget_get_allocated_baseline (GtkWidget *widget);
void gtk_widget_get_allocation (GtkWidget *widget, void gtk_widget_get_allocation (GtkWidget *widget,
GtkAllocation *allocation); GtkAllocation *allocation);
@@ -756,6 +775,7 @@ GtkAlign gtk_widget_get_halign (GtkWidget *widget);
void gtk_widget_set_halign (GtkWidget *widget, void gtk_widget_set_halign (GtkWidget *widget,
GtkAlign align); GtkAlign align);
GtkAlign gtk_widget_get_valign (GtkWidget *widget); GtkAlign gtk_widget_get_valign (GtkWidget *widget);
GtkAlign gtk_widget_get_valign_with_baseline (GtkWidget *widget);
void gtk_widget_set_valign (GtkWidget *widget, void gtk_widget_set_valign (GtkWidget *widget,
GtkAlign align); GtkAlign align);
gint gtk_widget_get_margin_left (GtkWidget *widget); gint gtk_widget_get_margin_left (GtkWidget *widget);

View File

@@ -69,7 +69,9 @@ void _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint for_size, gint for_size,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size,
gint *minimum_baseline,
gint *natural_baseline);
gboolean _gtk_widget_get_translation_to_window (GtkWidget *widget, gboolean _gtk_widget_get_translation_to_window (GtkWidget *widget,
GdkWindow *window, GdkWindow *window,

View File

@@ -36,6 +36,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testappchooser \ testappchooser \
testappchooserbutton \ testappchooserbutton \
testassistant \ testassistant \
testbaseline \
testbbox \ testbbox \
testboxcss \ testboxcss \
testbuttons \ testbuttons \
@@ -164,6 +165,7 @@ testiconview_DEPENDENCIES = $(TEST_DEPS)
testaccel_DEPENDENCIES = $(TEST_DEPS) testaccel_DEPENDENCIES = $(TEST_DEPS)
testadjustsize_DEPENDENCIES = $(TEST_DEPS) testadjustsize_DEPENDENCIES = $(TEST_DEPS)
testassistant_DEPENDENCIES = $(TEST_DEPS) testassistant_DEPENDENCIES = $(TEST_DEPS)
testbaseline_DEPENDENCIES = $(TEST_DEPS)
testbbox_DEPENDENCIES = $(TEST_DEPS) testbbox_DEPENDENCIES = $(TEST_DEPS)
testbuttons_DEPENDENCIES = $(TEST_DEPS) testbuttons_DEPENDENCIES = $(TEST_DEPS)
testcairo_DEPENDENCIES = $(TEST_DEPS) testcairo_DEPENDENCIES = $(TEST_DEPS)
@@ -354,6 +356,9 @@ testmerge_SOURCES = \
testactions_SOURCES = \ testactions_SOURCES = \
testactions.c testactions.c
testbaseline_SOURCES = \
testbaseline.c
testbbox_SOURCES = \ testbbox_SOURCES = \
testbbox.c testbbox.c

109
tests/testbaseline.c Normal file
View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2006 Nokia Corporation.
* Author: Xan Lopez <xan.lopez@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <gtk/gtk.h>
int
main (int argc,
char **argv)
{
GtkWidget *window, *label, *button;
GtkWidget *vbox, *hbox;
PangoFontDescription *font;
int i, j;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (gtk_main_quit), NULL);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
for (j = 0; j < 5; j++)
{
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
char *aligns[] = { "FILL", "START", "END", "CENTER", "BASELINE" };
label = gtk_label_new (aligns[j]);
gtk_container_add (GTK_CONTAINER (hbox), label);
for (i = 0; i < 3; i++) {
label = gtk_label_new ("A string XYyj,Ö...");
font = pango_font_description_new ();
pango_font_description_set_size (font, 7*(i+1)* 1024);
gtk_widget_override_font (label, font);
gtk_widget_set_valign (label, j);
gtk_container_add (GTK_CONTAINER (hbox), label);
}
}
for (j = 0; j < 2; j++)
{
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
if (j == 0)
label = gtk_label_new ("Baseline:");
else
label = gtk_label_new ("Normal:");
gtk_container_add (GTK_CONTAINER (hbox), label);
for (i = 0; i < 3; i++)
{
button = gtk_button_new_with_label ("│Xyj,Ö");
font = pango_font_description_new ();
pango_font_description_set_size (font, 7*(i+1)* 1024);
gtk_widget_override_font (button, font);
if (j == 0)
gtk_widget_set_valign (button, GTK_ALIGN_BASELINE);
gtk_container_add (GTK_CONTAINER (hbox), button);
}
for (i = 0; i < 3; i++)
{
button = gtk_button_new_with_label ("│Xyj,Ö");
gtk_button_set_image (GTK_BUTTON (button),
gtk_image_new_from_icon_name ("face-sad", GTK_ICON_SIZE_BUTTON));
gtk_button_set_always_show_image (GTK_BUTTON (button), TRUE);
font = pango_font_description_new ();
pango_font_description_set_size (font, 7*(i+1)* 1024);
gtk_widget_override_font (button, font);
if (j == 0)
gtk_widget_set_valign (button, GTK_ALIGN_BASELINE);
gtk_container_add (GTK_CONTAINER (hbox), button);
}
}
gtk_widget_show_all (window);
gtk_main ();
return 0;
}