[gtk+/native-layout] Created a _gtk_distribute_allocation() helper function for size allocators.
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/native-layout] Created a _gtk_distribute_allocation() helper function for size allocators.
- Date: Sun, 20 Jun 2010 18:23:05 +0000 (UTC)
commit 06a5095dc53510ea1a6137c439a46e62d45fb49e
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Fri Jun 18 19:40:02 2010 -0400
Created a _gtk_distribute_allocation() helper function for size allocators.
Migrated a portion of the GtkBox allocator loop to live in
a private function and be reused for distribution of space along
a single orientation.
gtk/gtkbox.c | 150 ++++---------------------------------------
gtk/gtksizerequest.c | 106 ++++++++++++++++++++++++++++++-
gtk/gtksizerequestprivate.h | 45 +++++++++++++
3 files changed, 164 insertions(+), 137 deletions(-)
---
diff --git a/gtk/gtkbox.c b/gtk/gtkbox.c
index 82289f5..18d6670 100644
--- a/gtk/gtkbox.c
+++ b/gtk/gtkbox.c
@@ -78,6 +78,7 @@
#include "gtkbox.h"
#include "gtkorientable.h"
#include "gtksizerequest.h"
+#include "gtksizerequestprivate.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkalias.h"
@@ -110,21 +111,6 @@ struct _GtkBoxPrivate
#define GTK_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_BOX, GtkBoxPrivate))
-typedef struct _GtkBoxDesiredSizes GtkBoxDesiredSizes;
-typedef struct _GtkBoxSpreading GtkBoxSpreading;
-
-struct _GtkBoxDesiredSizes
-{
- gint minimum_size;
- gint natural_size;
-};
-
-struct _GtkBoxSpreading
-{
- GtkBoxChild *child;
- gint index;
-};
-
static void gtk_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
@@ -375,30 +361,6 @@ count_expand_children (GtkBox *box, gint *visible_children, gint *expand_childre
}
}
-static gint
-gtk_box_compare_gap (gconstpointer p1,
- gconstpointer p2,
- gpointer data)
-{
- GtkBoxDesiredSizes *sizes = data;
- const GtkBoxSpreading *c1 = p1;
- const GtkBoxSpreading *c2 = p2;
-
- const gint d1 = MAX (sizes[c1->index].natural_size -
- sizes[c1->index].minimum_size,
- 0);
- const gint d2 = MAX (sizes[c2->index].natural_size -
- sizes[c2->index].minimum_size,
- 0);
-
- gint delta = (d2 - d1);
-
- if (0 == delta)
- delta = (c2->index - c1->index);
-
- return delta;
-}
-
static void
gtk_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
@@ -419,8 +381,7 @@ gtk_box_size_allocate (GtkWidget *widget,
gint border_width = GTK_CONTAINER (box)->border_width;
GtkTextDirection direction = gtk_widget_get_direction (widget);
GtkAllocation child_allocation;
- GtkBoxSpreading *spreading = g_newa (GtkBoxSpreading, nvis_children);
- GtkBoxDesiredSizes *sizes = g_newa (GtkBoxDesiredSizes, nvis_children);
+ GtkRequestedSize *sizes = g_newa (GtkRequestedSize, nvis_children);
GtkPackType packing;
@@ -476,9 +437,8 @@ gtk_box_size_allocate (GtkWidget *widget,
size -= sizes[i].minimum_size;
size -= child->padding * 2;
-
- spreading[i].index = i;
- spreading[i].child = child;
+
+ sizes[i].data = child;
i += 1;
}
@@ -498,47 +458,8 @@ gtk_box_size_allocate (GtkWidget *widget,
}
else
{
-
- /* Distribute the container's extra space c_gap. We want to assign
- * this space such that the sum of extra space assigned to children
- * (c^i_gap) is equal to c_cap. The case that there's not enough
- * space for all children to take their natural size needs some
- * attention. The goals we want to achieve are:
- *
- * a) Maximize number of children taking their natural size.
- * b) The allocated size of children should be a continuous
- * function of c_gap. That is, increasing the container size by
- * one pixel should never make drastic changes in the distribution.
- * c) If child i takes its natural size and child j doesn't,
- * child j should have received at least as much gap as child i.
- *
- * The following code distributes the additional space by following
- * this rules.
- */
-
- /* Sort descending by gap and position. */
- g_qsort_with_data (spreading,
- nvis_children, sizeof (GtkBoxSpreading),
- gtk_box_compare_gap, sizes);
-
- /* Distribute available space.
- * This master piece of a loop was conceived by Behdad Esfahbod.
- */
- for (i = nvis_children - 1; size > 0 && i >= 0; --i)
- {
- /* Divide remaining space by number of remaining children.
- * Sort order and reducing remaining space by assigned space
- * ensures that space is distributed equally.
- */
- gint glue = (size + i) / (i + 1);
- gint gap = sizes[spreading[i].index].natural_size
- - sizes[spreading[i].index].minimum_size;
-
- extra = MIN (glue, gap);
- sizes[spreading[i].index].minimum_size += extra;
-
- size -= extra;
- }
+ /* Bring children up to size first */
+ size = _gtk_distribute_allocation (size, nvis_children, sizes);
/* Calculate space which hasn't distributed yet,
* and is available for expanding children.
@@ -975,12 +896,10 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
if (nvis_children > 0)
{
- GtkBoxSpreading *spreading = g_newa (GtkBoxSpreading, nvis_children);
- GtkBoxDesiredSizes *sizes = g_newa (GtkBoxDesiredSizes, nvis_children);
- GtkPackType packing;
- gint size;
- gint extra, i;
- gint child_size, child_minimum, child_natural;
+ GtkRequestedSize *sizes = g_newa (GtkRequestedSize, nvis_children);
+ GtkPackType packing;
+ gint size, extra, i;
+ gint child_size, child_minimum, child_natural;
size = avail_size - border_width * 2 - (nvis_children - 1) * box->spacing;
@@ -1016,9 +935,8 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
size -= sizes[i].minimum_size;
size -= child->padding * 2;
-
- spreading[i].index = i;
- spreading[i].child = child;
+
+ sizes[i].data = child;
i += 1;
}
@@ -1034,48 +952,8 @@ gtk_box_compute_size_for_opposing_orientation (GtkBox *box,
}
else
{
-
- /* Distribute the container's extra space c_gap. We want to assign
- * this space such that the sum of extra space assigned to children
- * (c^i_gap) is equal to c_cap. The case that there's not enough
- * space for all children to take their natural size needs some
- * attention. The goals we want to achieve are:
- *
- * a) Maximize number of children taking their natural size.
- * b) The allocated size of children should be a continuous
- * function of c_gap. That is, increasing the container size by
- * one pixel should never make drastic changes in the distribution.
- * c) If child i takes its natural size and child j doesn't,
- * child j should have received at least as much gap as child i.
- *
- * The following code distributes the additional space by following
- * this rules.
- */
-
- /* Sort descending by gap and position. */
-
- g_qsort_with_data (spreading,
- nvis_children, sizeof (GtkBoxSpreading),
- gtk_box_compare_gap, sizes);
-
- /* Distribute available space.
- * This master piece of a loop was conceived by Behdad Esfahbod.
- */
- for (i = nvis_children - 1; size > 0 && i >= 0; --i)
- {
- /* Divide remaining space by number of remaining children.
- * Sort order and reducing remaining space by assigned space
- * ensures that space is distributed equally.
- */
- gint glue = (size + i) / (i + 1);
- gint gap = sizes[spreading[i].index].natural_size
- - sizes[spreading[i].index].minimum_size;
-
- extra = MIN (glue, gap);
- sizes[spreading[i].index].minimum_size += extra;
-
- size -= extra;
- }
+ /* Bring children up to size first */
+ size = _gtk_distribute_allocation (size, nvis_children, sizes);
/* Calculate space which hasn't distributed yet,
* and is available for expanding children.
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index dd00e11..d3026bf 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -94,6 +94,7 @@
#include <config.h>
#include "gtksizerequest.h"
+#include "gtksizerequestprivate.h"
#include "gtksizegroup.h"
#include "gtkprivate.h"
#include "gtkintl.h"
@@ -119,6 +120,11 @@ typedef struct {
guint8 cached_height_age;
} SizeRequestCache;
+typedef struct {
+ gpointer data;
+ gint index;
+} AllocationSpreading;
+
static GQuark quark_cache = 0;
@@ -352,7 +358,7 @@ compute_size_for_orientation (GtkSizeRequest *request,
}
/**
- * gtk_size_request_is_height_for_width:
+ * gtk_size_request_get_request_mode:
* @widget: a #GtkSizeRequest instance
*
* Gets whether the widget prefers a height-for-width layout
@@ -535,6 +541,104 @@ gtk_size_request_get_size (GtkSizeRequest *widget,
}
+static gint
+compare_gap (gconstpointer p1,
+ gconstpointer p2,
+ gpointer data)
+{
+ GtkRequestedSize *sizes = data;
+ const guint *c1 = p1;
+ const guint *c2 = p2;
+
+ const gint d1 = MAX (sizes[*c1].natural_size -
+ sizes[*c1].minimum_size,
+ 0);
+ const gint d2 = MAX (sizes[*c2].natural_size -
+ sizes[*c2].minimum_size,
+ 0);
+
+ gint delta = (d2 - d1);
+
+ if (0 == delta)
+ delta = (*c2 - *c1);
+
+ return delta;
+}
+
+/**
+ * _gtk_distribute_allocation:
+ * @extra_space: Extra space to redistribute among children after subtracting
+ * minimum sizes and any child padding from the overall allocation
+ * @n_requested_sizes: Number of requests to fit into the allocation
+ * @sizes: An array of structs with a client pointer and a minimum/natural size
+ * in the orientation of the allocation.
+ *
+ * Distributes @extra_space to child @sizes by bringing up smaller
+ * children up to natural size first.
+ *
+ * The remaining space will be added to the @minimum_size member of the
+ * GtkRequestedSize struct. If all sizes reach their natural size then
+ * the remaining space is returned.
+ *
+ * Returns: The remainder of @extra_space after redistributing space
+ * to @sizes if any.
+ */
+gint
+_gtk_distribute_allocation (gint extra_space,
+ guint n_requested_sizes,
+ GtkRequestedSize *sizes)
+{
+ guint *spreading = g_newa (guint, n_requested_sizes);
+ gint i;
+
+ for (i = 0; i < n_requested_sizes; i++)
+ spreading[i] = i;
+
+ /* Distribute the container's extra space c_gap. We want to assign
+ * this space such that the sum of extra space assigned to children
+ * (c^i_gap) is equal to c_cap. The case that there's not enough
+ * space for all children to take their natural size needs some
+ * attention. The goals we want to achieve are:
+ *
+ * a) Maximize number of children taking their natural size.
+ * b) The allocated size of children should be a continuous
+ * function of c_gap. That is, increasing the container size by
+ * one pixel should never make drastic changes in the distribution.
+ * c) If child i takes its natural size and child j doesn't,
+ * child j should have received at least as much gap as child i.
+ *
+ * The following code distributes the additional space by following
+ * these rules.
+ */
+
+ /* Sort descending by gap and position. */
+ g_qsort_with_data (spreading,
+ n_requested_sizes, sizeof (guint),
+ compare_gap, sizes);
+
+ /* Distribute available space.
+ * This master piece of a loop was conceived by Behdad Esfahbod.
+ */
+ for (i = n_requested_sizes - 1; extra_space > 0 && i >= 0; --i)
+ {
+ /* Divide remaining space by number of remaining children.
+ * Sort order and reducing remaining space by assigned space
+ * ensures that space is distributed equally.
+ */
+ gint glue = (extra_space + i) / (i + 1);
+ gint gap = sizes[(spreading[i])].natural_size
+ - sizes[(spreading[i])].minimum_size;
+
+ gint extra = MIN (glue, gap);
+
+ sizes[spreading[i]].minimum_size += extra;
+
+ extra_space -= extra;
+ }
+
+ return extra_space;
+}
+
#define __GTK_SIZE_REQUEST_C__
#include "gtkaliasdef.c"
diff --git a/gtk/gtksizerequestprivate.h b/gtk/gtksizerequestprivate.h
new file mode 100644
index 0000000..d980c98
--- /dev/null
+++ b/gtk/gtksizerequestprivate.h
@@ -0,0 +1,45 @@
+/* gtksizerequestprivate.h
+ * Copyright (C) 2010 Openismus GmbH
+ *
+ * Author:
+ * Tristan Van Berkom <tristan van berkom gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#ifndef __GTK_SIZE_REQUEST_PRIVATE_H__
+#define __GTK_SIZE_REQUEST_PRIVATE_H__
+
+#include <gtk/gtksizerequest.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkRequestedSize GtkRequestedSize;
+
+struct _GtkRequestedSize
+{
+ gpointer data;
+ gint minimum_size;
+ gint natural_size;
+};
+
+gint _gtk_distribute_allocation (gint extra_space,
+ guint n_requested_sizes,
+ GtkRequestedSize *sizes);
+
+G_END_DECLS
+
+#endif /* __GTK_SIZE_REQUEST_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]