[libdazzle] multi-paned: expand smaller children first
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdazzle] multi-paned: expand smaller children first
- Date: Thu, 22 Jun 2017 01:15:50 +0000 (UTC)
commit 9ec2ad086141429c146b0e518446ce87e2107683
Author: Christian Hergert <chergert redhat com>
Date: Wed Jun 21 18:14:14 2017 -0700
multi-paned: expand smaller children first
When we have multiple children who expand in the orientation
direction, we want to expand the smaller children first. This
gives us the effect of homogeneity as the allocation size grows.
I'm pretty sure we always want this. If for some reason not, we
can add a property to change the behavior. But I suspect that is
unlikely.
src/widgets/dzl-multi-paned.c | 101 +++++++++++++++++++++++++++++++++++++--
tests/data/test-multi-paned.ui | 1 +
2 files changed, 96 insertions(+), 6 deletions(-)
---
diff --git a/src/widgets/dzl-multi-paned.c b/src/widgets/dzl-multi-paned.c
index 4a7f56b..0cc8484 100644
--- a/src/widgets/dzl-multi-paned.c
+++ b/src/widgets/dzl-multi-paned.c
@@ -1194,13 +1194,28 @@ allocation_stage_drag_overflow (DzlMultiPaned *self,
}
}
+static gint
+sort_children_horizontal (const DzlMultiPanedChild * const *first,
+ const DzlMultiPanedChild * const *second)
+{
+
+ return (*first)->alloc.width - (*second)->alloc.width;
+}
+
+static gint
+sort_children_vertical (const DzlMultiPanedChild * const *first,
+ const DzlMultiPanedChild * const *second)
+{
+ return (*first)->alloc.height - (*second)->alloc.height;
+}
+
static void
allocation_stage_expand (DzlMultiPaned *self,
AllocationState *state)
{
+ g_autoptr(GPtrArray) expanding = NULL;
gint x_adjust = 0;
gint y_adjust = 0;
- gint n_expand = 0;
gint adjust;
g_assert (DZL_IS_MULTI_PANED (self));
@@ -1232,6 +1247,17 @@ allocation_stage_expand (DzlMultiPaned *self,
return;
}
+ /*
+ * First, we need to collect all of the children who are expanding
+ * in the direction matching our orientation. After that, we will
+ * sort them by their allocation size so that we can divy out extra
+ * allocation starting from the smallest. This will give us an effect
+ * of homogeneous size when all children are set to expand and enough
+ * space is available.
+ */
+
+ expanding = g_ptr_array_new ();
+
for (guint i = 0; i < state->n_children; i++)
{
DzlMultiPanedChild *child = state->children [i];
@@ -1241,23 +1267,86 @@ allocation_stage_expand (DzlMultiPaned *self,
if (IS_HORIZONTAL (state->orientation))
{
if (gtk_widget_get_hexpand (child->widget))
- n_expand++;
+ g_ptr_array_add (expanding, child);
}
else
{
if (gtk_widget_get_vexpand (child->widget))
- n_expand++;
+ g_ptr_array_add (expanding, child);
}
}
}
- if (n_expand == 0)
+ if (expanding->len == 0)
goto fill_last;
+ /* Now sort, smallest first, based on size in given orientation. */
+ if (IS_HORIZONTAL (state->orientation))
+ g_ptr_array_sort (expanding, (GCompareFunc) sort_children_horizontal);
+ else
+ g_ptr_array_sort (expanding, (GCompareFunc) sort_children_vertical);
+
+ /*
+ * While we have additional space available to hand out, allocate
+ * as much space as it takes to get to the next item in the array.
+ * If we run out of additional space, that is okay (as long as we
+ * dont hand out more than we have).
+ */
+
+ g_assert (expanding->len > 0);
+
+ for (guint i = 0; i < expanding->len - 1; i++)
+ {
+ DzlMultiPanedChild *child = g_ptr_array_index (expanding, i);
+ DzlMultiPanedChild *next = g_ptr_array_index (expanding, i + 1);
+
+ if (IS_HORIZONTAL (state->orientation))
+ {
+ g_assert (next->alloc.width >= child->alloc.width);
+ adjust = next->alloc.width - child->alloc.width;
+ }
+ else
+ {
+ g_assert (next->alloc.height >= child->alloc.height);
+ adjust = next->alloc.height - child->alloc.height;
+ }
+
+ if (IS_HORIZONTAL (state->orientation))
+ {
+ adjust = MIN (state->avail_width, adjust);
+
+ child->alloc.width += adjust;
+ state->avail_width -= adjust;
+
+ g_assert (state->avail_width >= 0);
+
+ if (state->avail_width == 0)
+ break;
+ }
+ else
+ {
+ adjust = MIN (state->avail_height, adjust);
+
+ child->alloc.height += adjust;
+ state->avail_height -= adjust;
+
+ g_assert (state->avail_height >= 0);
+
+ if (state->avail_height == 0)
+ break;
+ }
+ }
+
+ /*
+ * If we still have more space we can divy out, then do the normal
+ * expansion case now that we are starting with evenly sized
+ * children.
+ */
+
if (IS_HORIZONTAL (state->orientation))
- adjust = state->avail_width / n_expand;
+ adjust = state->avail_width / expanding->len;
else
- adjust = state->avail_height / n_expand;
+ adjust = state->avail_height / expanding->len;
for (guint i = 0; i < state->n_children; i++)
{
diff --git a/tests/data/test-multi-paned.ui b/tests/data/test-multi-paned.ui
index 11e4813..ed7f7fa 100644
--- a/tests/data/test-multi-paned.ui
+++ b/tests/data/test-multi-paned.ui
@@ -33,6 +33,7 @@
<child>
<object class="GtkButton">
<property name="label">Button</property>
+ <property name="expand">true</property>
<property name="visible">true</property>
</object>
</child>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]