mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 11:20:12 +00:00
GtkGrid: make attaching more flexible
Allow to attach children at either end of row/column 0. Proposed by Alex Larsson. https://bugzilla.gnome.org/show_bug.cgi?id=657793
This commit is contained in:
parent
f5e758bd60
commit
ef4690d511
207
gtk/gtkgrid.c
207
gtk/gtkgrid.c
@ -363,12 +363,82 @@ gtk_grid_init (GtkGrid *grid)
|
||||
priv->linedata[1].homogeneous = FALSE;
|
||||
}
|
||||
|
||||
static void grid_attach (GtkGrid *grid,
|
||||
GtkWidget *child,
|
||||
gint left,
|
||||
gint top,
|
||||
gint width,
|
||||
gint height);
|
||||
static void
|
||||
grid_attach (GtkGrid *grid,
|
||||
GtkWidget *widget,
|
||||
gint left,
|
||||
gint top,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GtkGridPrivate *priv = grid->priv;
|
||||
GtkGridChild *child;
|
||||
|
||||
child = g_slice_new (GtkGridChild);
|
||||
child->widget = widget;
|
||||
CHILD_LEFT (child) = left;
|
||||
CHILD_TOP (child) = top;
|
||||
CHILD_WIDTH (child) = width;
|
||||
CHILD_HEIGHT (child) = height;
|
||||
|
||||
priv->children = g_list_prepend (priv->children, child);
|
||||
|
||||
gtk_widget_set_parent (widget, GTK_WIDGET (grid));
|
||||
}
|
||||
|
||||
/* Find the position 'touching' existing
|
||||
* children. @orientation and @max determine
|
||||
* from which direction to approach (horizontal
|
||||
* + max = right, vertical + !max = top, etc).
|
||||
* @op_pos, @op_span determine the rows/columns
|
||||
* in which the touching has to happen.
|
||||
*/
|
||||
static gint
|
||||
find_attach_position (GtkGrid *grid,
|
||||
GtkOrientation orientation,
|
||||
gint op_pos,
|
||||
gint op_span,
|
||||
gboolean max)
|
||||
{
|
||||
GtkGridPrivate *priv = grid->priv;
|
||||
GtkGridChild *grid_child;
|
||||
GtkGridChildAttach *attach;
|
||||
GtkGridChildAttach *opposite;
|
||||
GList *list;
|
||||
gint pos;
|
||||
gboolean hit;
|
||||
|
||||
if (max)
|
||||
pos = -G_MAXINT;
|
||||
else
|
||||
pos = G_MAXINT;
|
||||
|
||||
hit = FALSE;
|
||||
|
||||
for (list = priv->children; list; list = list->next)
|
||||
{
|
||||
grid_child = list->data;
|
||||
|
||||
attach = &grid_child->attach[orientation];
|
||||
opposite = &grid_child->attach[1 - orientation];
|
||||
|
||||
/* check if the ranges overlap */
|
||||
if (opposite->pos <= op_pos + op_span && op_pos <= opposite->pos + opposite->span)
|
||||
{
|
||||
hit = TRUE;
|
||||
|
||||
if (max)
|
||||
pos = MAX (pos, attach->pos + attach->span);
|
||||
else
|
||||
pos = MIN (pos, attach->pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hit)
|
||||
pos = 0;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_grid_add (GtkContainer *container,
|
||||
@ -376,28 +446,10 @@ gtk_grid_add (GtkContainer *container,
|
||||
{
|
||||
GtkGrid *grid = GTK_GRID (container);
|
||||
GtkGridPrivate *priv = grid->priv;
|
||||
GtkGridChild *grid_child;
|
||||
GtkGridChildAttach *attach;
|
||||
GtkGridChildAttach *opposite;
|
||||
GList *list;
|
||||
gint pos;
|
||||
gint pos[2] = { 0, 0 };
|
||||
|
||||
pos = 0;
|
||||
for (list = priv->children; list; list = list->next)
|
||||
{
|
||||
grid_child = list->data;
|
||||
|
||||
attach = &grid_child->attach[priv->orientation];
|
||||
opposite = &grid_child->attach[1 - priv->orientation];
|
||||
|
||||
if (opposite->pos <= 0 && opposite->pos + opposite->span > 0)
|
||||
pos = MAX (pos, attach->pos + attach->span);
|
||||
}
|
||||
|
||||
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
grid_attach (grid, child, pos, 0, 1, 1);
|
||||
else
|
||||
grid_attach (grid, child, 0, pos, 1, 1);
|
||||
pos[priv->orientation] = find_attach_position (grid, priv->orientation, 0, 1, TRUE);
|
||||
grid_attach (grid, child, pos[0], pos[1], 1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1365,29 +1417,6 @@ gtk_grid_new (void)
|
||||
return g_object_new (GTK_TYPE_GRID, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
grid_attach (GtkGrid *grid,
|
||||
GtkWidget *widget,
|
||||
gint left,
|
||||
gint top,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
GtkGridPrivate *priv = grid->priv;
|
||||
GtkGridChild *child;
|
||||
|
||||
child = g_slice_new (GtkGridChild);
|
||||
child->widget = widget;
|
||||
CHILD_LEFT (child) = left;
|
||||
CHILD_TOP (child) = top;
|
||||
CHILD_WIDTH (child) = width;
|
||||
CHILD_HEIGHT (child) = height;
|
||||
|
||||
priv->children = g_list_prepend (priv->children, child);
|
||||
|
||||
gtk_widget_set_parent (widget, GTK_WIDGET (grid));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_grid_attach:
|
||||
* @grid: a #GtkGrid
|
||||
@ -1424,7 +1453,8 @@ gtk_grid_attach (GtkGrid *grid,
|
||||
* gtk_grid_attach_next_to:
|
||||
* @grid: a #GtkGrid
|
||||
* @child: the widget to add
|
||||
* @sibling: the child of @grid that @child will be placed next to
|
||||
* @sibling (allow-none): the child of @grid that @child will be placed
|
||||
* next to, or %NULL to place @child at the beginning or end
|
||||
* @side: the side of @sibling that @child is positioned next to
|
||||
* @width: the number of columns that @child will span
|
||||
* @height: the number of rows that @child will span
|
||||
@ -1432,7 +1462,9 @@ gtk_grid_attach (GtkGrid *grid,
|
||||
* Adds a widget to the grid.
|
||||
*
|
||||
* The widget is placed next to @sibling, on the side determined by
|
||||
* @side.
|
||||
* @side. When @sibling is %NULL, the widget is placed in row (for
|
||||
* left or right placement) or column 0 (for top or bottom placement),
|
||||
* at the end indicated by @side.
|
||||
*/
|
||||
void
|
||||
gtk_grid_attach_next_to (GtkGrid *grid,
|
||||
@ -1448,32 +1480,59 @@ gtk_grid_attach_next_to (GtkGrid *grid,
|
||||
g_return_if_fail (GTK_IS_GRID (grid));
|
||||
g_return_if_fail (GTK_IS_WIDGET (child));
|
||||
g_return_if_fail (gtk_widget_get_parent (child) == NULL);
|
||||
g_return_if_fail (gtk_widget_get_parent (sibling) == (GtkWidget*)grid);
|
||||
g_return_if_fail (sibling == NULL || gtk_widget_get_parent (sibling) == (GtkWidget*)grid);
|
||||
g_return_if_fail (width > 0);
|
||||
g_return_if_fail (height > 0);
|
||||
|
||||
grid_sibling = find_grid_child (grid, sibling);
|
||||
|
||||
switch (side)
|
||||
if (sibling)
|
||||
{
|
||||
case GTK_POS_LEFT:
|
||||
left = CHILD_LEFT (grid_sibling) - width;
|
||||
top = CHILD_TOP (grid_sibling);
|
||||
break;
|
||||
case GTK_POS_RIGHT:
|
||||
left = CHILD_LEFT (grid_sibling) + CHILD_WIDTH (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling);
|
||||
break;
|
||||
case GTK_POS_TOP:
|
||||
left = CHILD_LEFT (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling) - height;
|
||||
break;
|
||||
case GTK_POS_BOTTOM:
|
||||
left = CHILD_LEFT (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling) + CHILD_HEIGHT (grid_sibling);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
grid_sibling = find_grid_child (grid, sibling);
|
||||
|
||||
switch (side)
|
||||
{
|
||||
case GTK_POS_LEFT:
|
||||
left = CHILD_LEFT (grid_sibling) - width;
|
||||
top = CHILD_TOP (grid_sibling);
|
||||
break;
|
||||
case GTK_POS_RIGHT:
|
||||
left = CHILD_LEFT (grid_sibling) + CHILD_WIDTH (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling);
|
||||
break;
|
||||
case GTK_POS_TOP:
|
||||
left = CHILD_LEFT (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling) - height;
|
||||
break;
|
||||
case GTK_POS_BOTTOM:
|
||||
left = CHILD_LEFT (grid_sibling);
|
||||
top = CHILD_TOP (grid_sibling) + CHILD_HEIGHT (grid_sibling);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (side)
|
||||
{
|
||||
case GTK_POS_LEFT:
|
||||
left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, TRUE);
|
||||
top = 0;
|
||||
break;
|
||||
case GTK_POS_RIGHT:
|
||||
left = find_attach_position (grid, GTK_ORIENTATION_HORIZONTAL, 0, height, FALSE);
|
||||
top = 0;
|
||||
break;
|
||||
case GTK_POS_TOP:
|
||||
left = 0;
|
||||
top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, TRUE);
|
||||
break;
|
||||
case GTK_POS_BOTTOM:
|
||||
left = 0;
|
||||
top = find_attach_position (grid, GTK_ORIENTATION_VERTICAL, 0, width, FALSE);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
grid_attach (grid, child, left, top, width, height);
|
||||
|
@ -123,6 +123,10 @@ TEST_PROGS += entry
|
||||
entry_SOURCES = entry.c
|
||||
entry_LDADD = $(progs_ldadd)
|
||||
|
||||
TEST_PROGS += grid
|
||||
grid_SOURCES = grid.c
|
||||
grid_LDADD = $(progs_ldadd)
|
||||
|
||||
EXTRA_DIST += \
|
||||
file-chooser-test-dir/empty \
|
||||
file-chooser-test-dir/text.txt
|
||||
|
238
gtk/tests/grid.c
Normal file
238
gtk/tests/grid.c
Normal file
@ -0,0 +1,238 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
/* test that attach_next_to picks the places
|
||||
* we expect it to pick, when there is any choice
|
||||
*/
|
||||
static void
|
||||
test_attach (void)
|
||||
{
|
||||
GtkGrid *g;
|
||||
GtkWidget *child, *sibling, *z, *A, *B;
|
||||
gint left, top, width, height;
|
||||
|
||||
g = (GtkGrid *)gtk_grid_new ();
|
||||
|
||||
child = gtk_label_new ("a");
|
||||
gtk_grid_attach_next_to (g, child, NULL, GTK_POS_LEFT, 1, 1);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 0);
|
||||
g_assert_cmpint (top, ==, 0);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
sibling = child;
|
||||
child = gtk_label_new ("b");
|
||||
gtk_grid_attach_next_to (g, child, sibling, GTK_POS_RIGHT, 2, 2);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 1);
|
||||
g_assert_cmpint (top, ==, 0);
|
||||
g_assert_cmpint (width, ==, 2);
|
||||
g_assert_cmpint (height, ==, 2);
|
||||
|
||||
/* this one should just be ignored */
|
||||
z = gtk_label_new ("z");
|
||||
gtk_grid_attach (g, z, 4, 4, 1, 1);
|
||||
|
||||
child = gtk_label_new ("c");
|
||||
gtk_grid_attach_next_to (g, child, sibling, GTK_POS_BOTTOM, 3, 1);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 0);
|
||||
g_assert_cmpint (top, ==, 1);
|
||||
g_assert_cmpint (width, ==, 3);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
child = gtk_label_new ("u");
|
||||
gtk_grid_attach_next_to (g, child, z, GTK_POS_LEFT, 2, 1);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 2);
|
||||
g_assert_cmpint (top, ==, 4);
|
||||
g_assert_cmpint (width, ==, 2);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
child = gtk_label_new ("v");
|
||||
gtk_grid_attach_next_to (g, child, z, GTK_POS_RIGHT, 2, 1);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 5);
|
||||
g_assert_cmpint (top, ==, 4);
|
||||
g_assert_cmpint (width, ==, 2);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
child = gtk_label_new ("x");
|
||||
gtk_grid_attach_next_to (g, child, z, GTK_POS_TOP, 1, 2);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 4);
|
||||
g_assert_cmpint (top, ==, 2);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 2);
|
||||
|
||||
child = gtk_label_new ("x");
|
||||
gtk_grid_attach_next_to (g, child, z, GTK_POS_TOP, 1, 2);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 4);
|
||||
g_assert_cmpint (top, ==, 2);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 2);
|
||||
|
||||
child = gtk_label_new ("y");
|
||||
gtk_grid_attach_next_to (g, child, z, GTK_POS_BOTTOM, 1, 2);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 4);
|
||||
g_assert_cmpint (top, ==, 5);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 2);
|
||||
|
||||
A = gtk_label_new ("A");
|
||||
gtk_grid_attach (g, A, 10, 10, 1, 1);
|
||||
B = gtk_label_new ("B");
|
||||
gtk_grid_attach (g, B, 10, 12, 1, 1);
|
||||
|
||||
child = gtk_label_new ("D");
|
||||
gtk_grid_attach_next_to (g, child, A, GTK_POS_RIGHT, 1, 3);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 11);
|
||||
g_assert_cmpint (top, ==, 10);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 3);
|
||||
}
|
||||
|
||||
static void
|
||||
test_add (void)
|
||||
{
|
||||
GtkGrid *g;
|
||||
GtkWidget *child;
|
||||
gint left, top, width, height;
|
||||
|
||||
g = (GtkGrid *)gtk_grid_new ();
|
||||
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (g), GTK_ORIENTATION_HORIZONTAL);
|
||||
|
||||
child = gtk_label_new ("a");
|
||||
gtk_container_add (GTK_CONTAINER (g), child);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 0);
|
||||
g_assert_cmpint (top, ==, 0);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
child = gtk_label_new ("b");
|
||||
gtk_container_add (GTK_CONTAINER (g), child);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 1);
|
||||
g_assert_cmpint (top, ==, 0);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
child = gtk_label_new ("c");
|
||||
gtk_container_add (GTK_CONTAINER (g), child);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 2);
|
||||
g_assert_cmpint (top, ==, 0);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (g), GTK_ORIENTATION_VERTICAL);
|
||||
|
||||
child = gtk_label_new ("d");
|
||||
gtk_container_add (GTK_CONTAINER (g), child);
|
||||
gtk_container_child_get (GTK_CONTAINER (g), child,
|
||||
"left-attach", &left,
|
||||
"top-attach", &top,
|
||||
"width", &width,
|
||||
"height", &height,
|
||||
NULL);
|
||||
g_assert_cmpint (left, ==, 0);
|
||||
g_assert_cmpint (top, ==, 1);
|
||||
g_assert_cmpint (width, ==, 1);
|
||||
g_assert_cmpint (height, ==, 1);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
gtk_test_init (&argc, &argv);
|
||||
|
||||
g_test_add_func ("/grid/attach", test_attach);
|
||||
g_test_add_func ("/grid/add", test_add);
|
||||
|
||||
return g_test_run();
|
||||
}
|
Loading…
Reference in New Issue
Block a user