forked from AuroraMiddleware/gtk
Make GtkFrame allocate its label considering natural size requests
Also like the GtkExpander, the label widget is allocated the minimum height for its allocated width and the remaining space is given to the child, test case included.
This commit is contained in:
parent
c9579f3ca4
commit
208ba9bb50
131
gtk/gtkframe.c
131
gtk/gtkframe.c
@ -47,6 +47,7 @@ struct _GtkFramePriv
|
||||
/* Properties */
|
||||
|
||||
GtkAllocation child_allocation;
|
||||
GtkAllocation label_allocation;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -99,6 +100,15 @@ static void gtk_frame_get_width (GtkSizeRequest *widget
|
||||
static void gtk_frame_get_height (GtkSizeRequest *widget,
|
||||
gint *minimum_size,
|
||||
gint *natural_size);
|
||||
static void gtk_frame_get_height_for_width (GtkSizeRequest *layout,
|
||||
gint width,
|
||||
gint *minimum_height,
|
||||
gint *natural_height);
|
||||
static void gtk_frame_get_width_for_height (GtkSizeRequest *layout,
|
||||
gint width,
|
||||
gint *minimum_height,
|
||||
gint *natural_height);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFrame, gtk_frame, GTK_TYPE_BIN,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||
@ -597,24 +607,21 @@ gtk_frame_paint (GtkWidget *widget,
|
||||
|
||||
if (priv->label_widget)
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
gfloat xalign;
|
||||
gint height_extra;
|
||||
gint x2;
|
||||
|
||||
gtk_widget_get_child_requisition (priv->label_widget, &child_requisition);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
xalign = priv->label_xalign;
|
||||
else
|
||||
xalign = 1 - priv->label_xalign;
|
||||
|
||||
height_extra = MAX (0, child_requisition.height - widget->style->ythickness)
|
||||
- priv->label_yalign * child_requisition.height;
|
||||
height_extra = MAX (0, priv->label_allocation.height - widget->style->ythickness)
|
||||
- priv->label_yalign * priv->label_allocation.height;
|
||||
y -= height_extra;
|
||||
height += height_extra;
|
||||
|
||||
x2 = widget->style->xthickness + (priv->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_SIDE_PAD;
|
||||
x2 = widget->style->xthickness + (priv->child_allocation.width - priv->label_allocation.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_SIDE_PAD;
|
||||
|
||||
/* If the label is completely over or under the frame we can omit the gap */
|
||||
if (priv->label_yalign == 0.0 || priv->label_yalign == 1.0)
|
||||
@ -628,7 +635,7 @@ gtk_frame_paint (GtkWidget *widget,
|
||||
area, widget, "frame",
|
||||
x, y, width, height,
|
||||
GTK_POS_TOP,
|
||||
x2, child_requisition.width + 2 * LABEL_PAD);
|
||||
x2, priv->label_allocation.width + 2 * LABEL_PAD);
|
||||
}
|
||||
else
|
||||
gtk_paint_shadow (widget->style, widget->window,
|
||||
@ -688,25 +695,32 @@ gtk_frame_size_allocate (GtkWidget *widget,
|
||||
|
||||
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
|
||||
{
|
||||
GtkRequisition child_requisition;
|
||||
GtkAllocation child_allocation;
|
||||
gint nat_width, width, height;
|
||||
gfloat xalign;
|
||||
|
||||
gtk_widget_get_child_requisition (priv->label_widget, &child_requisition);
|
||||
|
||||
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||
xalign = priv->label_xalign;
|
||||
else
|
||||
xalign = 1 - priv->label_xalign;
|
||||
|
||||
child_allocation.x = priv->child_allocation.x + LABEL_SIDE_PAD +
|
||||
(priv->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_PAD;
|
||||
child_allocation.width = MIN (child_requisition.width, new_allocation.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD);
|
||||
gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget), NULL, &nat_width);
|
||||
width = new_allocation.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD;
|
||||
width = MIN (width, nat_width);
|
||||
|
||||
child_allocation.y = priv->child_allocation.y - MAX (child_requisition.height, widget->style->ythickness);
|
||||
child_allocation.height = child_requisition.height;
|
||||
gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget), width,
|
||||
&height, NULL);
|
||||
|
||||
gtk_widget_size_allocate (priv->label_widget, &child_allocation);
|
||||
|
||||
priv->label_allocation.x = priv->child_allocation.x + LABEL_SIDE_PAD +
|
||||
(new_allocation.width - width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_PAD;
|
||||
|
||||
priv->label_allocation.width = width;
|
||||
|
||||
|
||||
priv->label_allocation.y = priv->child_allocation.y - MAX (height, widget->style->ythickness);
|
||||
priv->label_allocation.height = height;
|
||||
|
||||
gtk_widget_size_allocate (priv->label_widget, &priv->label_allocation);
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,20 +741,31 @@ gtk_frame_real_compute_child_allocation (GtkFrame *frame,
|
||||
GtkFramePriv *priv = frame->priv;
|
||||
GtkWidget *widget = GTK_WIDGET (frame);
|
||||
GtkAllocation *allocation = &widget->allocation;
|
||||
GtkRequisition child_requisition;
|
||||
gint top_margin;
|
||||
guint border_width;
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (frame));
|
||||
|
||||
if (priv->label_widget)
|
||||
{
|
||||
gtk_widget_get_child_requisition (priv->label_widget, &child_requisition);
|
||||
top_margin = MAX (child_requisition.height, widget->style->ythickness);
|
||||
gint nat_width, width, height;
|
||||
|
||||
gtk_size_request_get_width (GTK_SIZE_REQUEST (priv->label_widget), NULL, &nat_width);
|
||||
|
||||
width = widget->allocation.width;
|
||||
width -= 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD;
|
||||
width -= (border_width + GTK_WIDGET (widget)->style->xthickness) * 2;
|
||||
|
||||
width = MIN (width, nat_width);
|
||||
|
||||
gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget), width,
|
||||
&height, NULL);
|
||||
|
||||
top_margin = MAX (height, widget->style->ythickness);
|
||||
}
|
||||
else
|
||||
top_margin = widget->style->ythickness;
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (frame));
|
||||
|
||||
child_allocation->x = border_width + widget->style->xthickness;
|
||||
child_allocation->width = MAX(1, (gint)allocation->width - child_allocation->x * 2);
|
||||
|
||||
@ -846,9 +871,67 @@ gtk_frame_get_height (GtkSizeRequest *widget,
|
||||
gtk_frame_get_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gtk_frame_get_height_for_width (GtkSizeRequest *request,
|
||||
gint width,
|
||||
gint *minimum_height,
|
||||
gint *natural_height)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (request);
|
||||
GtkWidget *child;
|
||||
GtkFrame *frame = GTK_FRAME (widget);
|
||||
GtkFramePriv *priv = frame->priv;
|
||||
GtkBin *bin = GTK_BIN (widget);
|
||||
gint child_min, child_nat, label_width;
|
||||
gint minimum, natural;
|
||||
guint border_width;
|
||||
|
||||
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
|
||||
minimum = (border_width + GTK_WIDGET (widget)->style->ythickness) * 2;
|
||||
natural = (border_width + GTK_WIDGET (widget)->style->ythickness) * 2;
|
||||
|
||||
width -= (border_width + GTK_WIDGET (widget)->style->xthickness) * 2;
|
||||
label_width = width - 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD;
|
||||
|
||||
if (priv->label_widget && gtk_widget_get_visible (priv->label_widget))
|
||||
{
|
||||
gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
|
||||
label_width, &child_min, &child_nat);
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
}
|
||||
|
||||
child = gtk_bin_get_child (bin);
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
{
|
||||
gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (priv->label_widget),
|
||||
width, &child_min, &child_nat);
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
}
|
||||
|
||||
if (minimum_height)
|
||||
*minimum_height = minimum;
|
||||
|
||||
if (natural_height)
|
||||
*natural_height = natural;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_frame_get_width_for_height (GtkSizeRequest *widget,
|
||||
gint height,
|
||||
gint *minimum_width,
|
||||
gint *natural_width)
|
||||
{
|
||||
gtk_size_request_get_width (widget, minimum_width, natural_width);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_frame_size_request_init (GtkSizeRequestIface *iface)
|
||||
{
|
||||
iface->get_width = gtk_frame_get_width;
|
||||
iface->get_height = gtk_frame_get_height;
|
||||
iface->get_width = gtk_frame_get_width;
|
||||
iface->get_height = gtk_frame_get_height;
|
||||
iface->get_height_for_width = gtk_frame_get_height_for_width;
|
||||
iface->get_width_for_height = gtk_frame_get_width_for_height;
|
||||
}
|
||||
|
@ -615,6 +615,49 @@ TestInterface interfaces[] = {
|
||||
"</interface>",
|
||||
NULL
|
||||
},
|
||||
|
||||
{
|
||||
"Wrapping Frame Label",
|
||||
"This test demonstrates how the frame label can fill to its natural width "
|
||||
"and also trade height for width.",
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<interface>"
|
||||
" <requires lib=\"gtk+\" version=\"2.20\"/>"
|
||||
" <!-- interface-naming-policy project-wide -->"
|
||||
" <object class=\"GtkWindow\" id=\"window\">"
|
||||
" <property name=\"default_width\">400</property>"
|
||||
" <property name=\"default_height\">150</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkFrame\" id=\"frame1\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"border_width\">8</property>"
|
||||
" <property name=\"label_xalign\">0</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkAlignment\" id=\"alignment1\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"left_padding\">12</property>"
|
||||
" <child>"
|
||||
" <object class=\"GtkLabel\" id=\"label2\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"label\" translatable=\"yes\">some content</property>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" <child type=\"label\">"
|
||||
" <object class=\"GtkLabel\" id=\"label1\">"
|
||||
" <property name=\"visible\">True</property>"
|
||||
" <property name=\"label\" translatable=\"yes\">A frame label that's a little long and wraps</property>"
|
||||
" <property name=\"use_markup\">True</property>"
|
||||
" <property name=\"wrap\">True</property>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
" </child>"
|
||||
" </object>"
|
||||
"</interface>",
|
||||
NULL
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user