[gtk+] box gadget: Implement cross-axis alignment
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] box gadget: Implement cross-axis alignment
- Date: Fri, 15 Jan 2016 14:44:02 +0000 (UTC)
commit 87171469b7dba8ec8ae3397ed292b9d004ef5e90
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jan 15 06:47:31 2016 -0500
box gadget: Implement cross-axis alignment
So far, the box gadget is always allocating all children the
full size in the cross axis. This behavior corresponds to the
align-items: stretch behavior in
https://www.w3.org/TR/css-flexbox-1/#align-items-property
This commit implements the other modes described there.
While widgets have halign/valign properties that we can use for
this, the API for inserting gadgets has to change to take an
extra align parameter. All callers have been updated to pass
GTK_ALIGN_FILL, since that corresponds to the previous behavior.
https://bugzilla.gnome.org/show_bug.cgi?id=760668
gtk/gtkboxgadget.c | 127 ++++++++++++++++++++++++++++++++++++++++++---
gtk/gtkboxgadgetprivate.h | 5 ++-
gtk/gtknotebook.c | 14 +++---
3 files changed, 131 insertions(+), 15 deletions(-)
---
diff --git a/gtk/gtkboxgadget.c b/gtk/gtkboxgadget.c
index 15fe036..e02c8e3 100644
--- a/gtk/gtkboxgadget.c
+++ b/gtk/gtkboxgadget.c
@@ -45,6 +45,7 @@ typedef struct _GtkBoxGadgetChild GtkBoxGadgetChild;
struct _GtkBoxGadgetChild {
GObject *object;
ComputeExpandFunc compute_expand;
+ GtkAlign align;
};
G_DEFINE_TYPE_WITH_CODE (GtkBoxGadget, gtk_box_gadget, GTK_TYPE_CSS_GADGET,
@@ -59,6 +60,26 @@ gtk_box_gadget_child_is_visible (GObject *child)
return gtk_css_gadget_get_visible (GTK_CSS_GADGET (child));
}
+static GtkAlign
+gtk_box_gadget_child_get_align (GtkBoxGadget *gadget,
+ GtkBoxGadgetChild *child)
+{
+ GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (GTK_BOX_GADGET (gadget));
+ GtkAlign align;
+
+ if (GTK_IS_WIDGET (child->object))
+ {
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ g_object_get (child->object, "valign", &align, NULL);
+ else
+ g_object_get (child->object, "halign", &align, NULL);
+ }
+ else
+ align = child->align;
+
+ return align;
+}
+
static void
gtk_box_gadget_measure_child (GObject *child,
GtkOrientation orientation,
@@ -281,11 +302,69 @@ gtk_box_gadget_allocate (GtkCssGadget *gadget,
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_box_gadget_distribute (GTK_BOX_GADGET (gadget), allocation->width, sizes);
- for (i = 0 ; i < priv->children->len; i++)
+
+ if (baseline < 0)
+ {
+ for (i = 0; i < priv->children->len; i++)
+ {
+ GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+
+ if (gtk_box_gadget_child_get_align (GTK_BOX_GADGET (gadget), child) == GTK_ALIGN_BASELINE)
+ {
+ gint child_min, child_nat;
+ gint child_baseline_min, child_baseline_nat;
+
+ gtk_box_gadget_measure_child (child->object,
+ GTK_ORIENTATION_VERTICAL,
+ sizes[i].minimum_size,
+ &child_min, &child_nat,
+ &child_baseline_min, &child_baseline_nat);
+ baseline = MAX (baseline, child_baseline_min);
+ }
+ }
+ }
+
+ for (i = 0; i < priv->children->len; i++)
{
GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+ gint child_min, child_nat;
+ gint child_baseline_min, child_baseline_nat;
child_allocation.width = sizes[i].minimum_size;
+ gtk_box_gadget_measure_child (child->object,
+ GTK_ORIENTATION_VERTICAL,
+ child_allocation.width,
+ &child_min, &child_nat,
+ &child_baseline_min, &child_baseline_nat);
+ switch (gtk_box_gadget_child_get_align (GTK_BOX_GADGET (gadget), child))
+ {
+ case GTK_ALIGN_FILL:
+ child_allocation.height = allocation->height;
+ child_allocation.y = allocation->y;
+ break;
+ case GTK_ALIGN_START:
+ child_allocation.height = MIN(child_nat, allocation->height);
+ child_allocation.y = allocation->y;
+ break;
+ case GTK_ALIGN_END:
+ child_allocation.height = MIN(child_nat, allocation->height);
+ child_allocation.y = allocation->y + allocation->height - child_allocation.height;
+ break;
+ case GTK_ALIGN_BASELINE:
+ if (child_baseline_min >= 0 && baseline >= 0)
+ {
+ child_allocation.height = MIN(child_nat, allocation->height);
+ child_allocation.y = allocation->y + baseline - child_baseline_min;
+ break;
+ }
+ case GTK_ALIGN_CENTER:
+ child_allocation.height = MIN(child_nat, allocation->height);
+ child_allocation.y = allocation->y + (allocation->height - child_allocation.height) / 2;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
gtk_box_gadget_allocate_child (child->object, &child_allocation, baseline, &child_clip);
if (i == 0)
*out_clip = child_clip;
@@ -297,11 +376,42 @@ gtk_box_gadget_allocate (GtkCssGadget *gadget,
else
{
gtk_box_gadget_distribute (GTK_BOX_GADGET (gadget), allocation->height, sizes);
+
for (i = 0 ; i < priv->children->len; i++)
{
GtkBoxGadgetChild *child = &g_array_index (priv->children, GtkBoxGadgetChild, i);
+ gint child_min, child_nat;
child_allocation.height = sizes[i].minimum_size;
+ gtk_box_gadget_measure_child (child->object,
+ GTK_ORIENTATION_HORIZONTAL,
+ child_allocation.height,
+ &child_min, &child_nat,
+ NULL, NULL);
+
+ switch (gtk_box_gadget_child_get_align (GTK_BOX_GADGET (gadget), child))
+ {
+ case GTK_ALIGN_FILL:
+ child_allocation.width = allocation->width;
+ child_allocation.x = allocation->x;
+ break;
+ case GTK_ALIGN_START:
+ child_allocation.width = MIN(child_nat, allocation->width);
+ child_allocation.x = allocation->x;
+ break;
+ case GTK_ALIGN_END:
+ child_allocation.width = MIN(child_nat, allocation->width);
+ child_allocation.x = allocation->x + allocation->width - child_allocation.width;
+ break;
+ case GTK_ALIGN_BASELINE:
+ case GTK_ALIGN_CENTER:
+ child_allocation.width = MIN(child_nat, allocation->width);
+ child_allocation.x = allocation->x + (allocation->width - child_allocation.width) / 2;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
gtk_box_gadget_allocate_child (child->object, &child_allocation, -1, &child_clip);
if (i == 0)
*out_clip = child_clip;
@@ -438,13 +548,15 @@ static void
gtk_box_gadget_insert_object (GtkBoxGadget *gadget,
int pos,
GObject *object,
- ComputeExpandFunc compute_expand_func)
+ ComputeExpandFunc compute_expand_func,
+ GtkAlign align)
{
GtkBoxGadgetPrivate *priv = gtk_box_gadget_get_instance_private (gadget);
GtkBoxGadgetChild child;
child.object = g_object_ref (object);
child.compute_expand = compute_expand_func;
+ child.align = align;
if (pos < 0 || pos >= priv->children->len)
{
@@ -455,7 +567,6 @@ gtk_box_gadget_insert_object (GtkBoxGadget *gadget,
}
else
{
-
g_array_insert_val (priv->children, pos, child);
gtk_css_node_insert_before (gtk_css_gadget_get_node (GTK_CSS_GADGET (gadget)),
get_css_node (object),
@@ -471,7 +582,8 @@ gtk_box_gadget_insert_widget (GtkBoxGadget *gadget,
gtk_box_gadget_insert_object (gadget,
pos,
G_OBJECT (widget),
- (ComputeExpandFunc) gtk_widget_compute_expand);
+ (ComputeExpandFunc) gtk_widget_compute_expand,
+ GTK_ALIGN_FILL);
}
void
@@ -520,13 +632,15 @@ gtk_box_gadget_insert_gadget (GtkBoxGadget *gadget,
int pos,
GtkCssGadget *cssgadget,
gboolean hexpand,
- gboolean vexpand)
+ gboolean vexpand,
+ GtkAlign align)
{
gtk_box_gadget_insert_object (gadget,
pos,
G_OBJECT (cssgadget),
hexpand ? (vexpand ? (ComputeExpandFunc) gtk_true : only_horizontal)
- : (vexpand ? only_vertical : (ComputeExpandFunc) gtk_false));
+ : (vexpand ? only_vertical : (ComputeExpandFunc) gtk_false),
+ align);
}
void
@@ -535,4 +649,3 @@ gtk_box_gadget_remove_gadget (GtkBoxGadget *gadget,
{
gtk_box_gadget_remove_object (gadget, G_OBJECT (cssgadget));
}
-
diff --git a/gtk/gtkboxgadgetprivate.h b/gtk/gtkboxgadgetprivate.h
index ce64e41..8063fcc 100644
--- a/gtk/gtkboxgadgetprivate.h
+++ b/gtk/gtkboxgadgetprivate.h
@@ -21,6 +21,7 @@
#define __GTK_BOX_GADGET_PRIVATE_H__
#include "gtk/gtkcssgadgetprivate.h"
+#include "gtk/gtkenums.h"
G_BEGIN_DECLS
@@ -65,10 +66,12 @@ void gtk_box_gadget_insert_gadget (GtkBoxGadget
int pos,
GtkCssGadget *cssgadget,
gboolean hexpand,
- gboolean vexpand);
+ gboolean vexpand,
+ GtkAlign align);
void gtk_box_gadget_remove_gadget (GtkBoxGadget *gadget,
GtkCssGadget *cssgadget);
+
G_END_DECLS
#endif /* __GTK_BOX_GADGET_PRIVATE_H__ */
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index 6f61384..203e2a8 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -1312,7 +1312,7 @@ gtk_notebook_init (GtkNotebook *notebook)
NULL,
NULL);
gtk_css_gadget_set_state (priv->stack_gadget, gtk_css_node_get_state (widget_node));
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->stack_gadget, TRUE, TRUE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), -1, priv->stack_gadget, TRUE, TRUE,
GTK_ALIGN_FILL);
priv->header_gadget = gtk_box_gadget_new ("header",
GTK_WIDGET (notebook),
@@ -1321,7 +1321,7 @@ gtk_notebook_init (GtkNotebook *notebook)
gtk_css_gadget_add_class (priv->header_gadget, GTK_STYLE_CLASS_TOP);
gtk_css_gadget_set_state (priv->header_gadget, gtk_css_node_get_state (widget_node));
gtk_css_gadget_set_visible (priv->header_gadget, FALSE);
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE,
GTK_ALIGN_FILL);
priv->tabs_gadget = gtk_css_custom_gadget_new ("tabs",
GTK_WIDGET (notebook),
@@ -1333,7 +1333,7 @@ gtk_notebook_init (GtkNotebook *notebook)
NULL,
NULL);
gtk_css_gadget_set_state (priv->tabs_gadget, gtk_css_node_get_state (widget_node));
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->header_gadget), 0, priv->tabs_gadget, TRUE, TRUE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->header_gadget), 0, priv->tabs_gadget, TRUE, TRUE,
GTK_ALIGN_FILL);
}
static void
@@ -7014,28 +7014,28 @@ gtk_notebook_update_tab_pos (GtkNotebook *notebook)
{
case GTK_POS_TOP:
if (priv->show_tabs)
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE,
GTK_ALIGN_FILL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->header_gadget), GTK_ORIENTATION_HORIZONTAL);
break;
case GTK_POS_BOTTOM:
if (priv->show_tabs)
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE,
GTK_ALIGN_FILL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_VERTICAL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->header_gadget), GTK_ORIENTATION_HORIZONTAL);
break;
case GTK_POS_LEFT:
if (priv->show_tabs)
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 0, priv->header_gadget, FALSE, FALSE,
GTK_ALIGN_FILL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->header_gadget), GTK_ORIENTATION_VERTICAL);
break;
case GTK_POS_RIGHT:
if (priv->show_tabs)
- gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE);
+ gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), 1, priv->header_gadget, FALSE, FALSE,
GTK_ALIGN_FILL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), GTK_ORIENTATION_HORIZONTAL);
gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->header_gadget), GTK_ORIENTATION_VERTICAL);
break;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]