summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2015-12-12 19:41:40 -0500
committerMatthias Clasen <mclasen@redhat.com>2015-12-15 08:41:16 -0500
commit49e24b05b58b13004a76f7e0ef0370ef191c59f4 (patch)
treedc0ec5244c5dddb434443c9e6791aeffda30183d
parent3b264ea55519b260c15e61ff6e59b9c49e7b4fbf (diff)
downloadgtk+-49e24b05b58b13004a76f7e0ef0370ef191c59f4.tar.gz
flowbox: convert to gadgets
-rw-r--r--gtk/gtkflowbox.c998
1 files changed, 554 insertions, 444 deletions
diff --git a/gtk/gtkflowbox.c b/gtk/gtkflowbox.c
index af1c01b28a..2a1baac730 100644
--- a/gtk/gtkflowbox.c
+++ b/gtk/gtkflowbox.c
@@ -818,6 +818,7 @@ struct _GtkFlowBoxPrivate {
GSequence *children;
+ GtkCssGadget *gadget;
GtkFlowBoxFilterFunc filter_func;
gpointer filter_data;
GDestroyNotify filter_destroy;
@@ -1622,13 +1623,45 @@ static void
gtk_flow_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
+ GtkAllocation clip;
+ GdkWindow *window;
+ GtkAllocation child_allocation;
+
+ gtk_widget_set_allocation (widget, allocation);
+
+ window = gtk_widget_get_window (widget);
+ if (window != NULL)
+ gdk_window_move_resize (window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ child_allocation.x = 0;
+ child_allocation.y = 0;
+ child_allocation.width = allocation->width;
+ child_allocation.height = allocation->height;
+
+ gtk_css_gadget_allocate (BOX_PRIV (widget)->gadget,
+ &child_allocation,
+ gtk_widget_get_allocated_baseline (widget),
+ &clip);
+
+ _gtk_widget_set_simple_clip (widget, &clip);
+}
+
+static void
+gtk_flow_box_allocate (GtkCssGadget *gadget,
+ const GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip,
+ gpointer unused)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkFlowBox *box = GTK_FLOW_BOX (widget);
GtkFlowBoxPrivate *priv = BOX_PRIV (box);
GtkAllocation child_allocation;
gint avail_size, avail_other_size, min_items, item_spacing, line_spacing;
GtkAlign item_align;
GtkAlign line_align;
- GdkWindow *window;
GtkRequestedSize *line_sizes = NULL;
GtkRequestedSize *item_sizes = NULL;
gint min_item_size, nat_item_size;
@@ -1641,13 +1674,6 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
gint i, this_line_size;
GSequenceIter *iter;
- gtk_widget_set_allocation (widget, allocation);
- window = gtk_widget_get_window (widget);
- if (window != NULL)
- gdk_window_move_resize (window,
- allocation->x, allocation->y,
- allocation->width, allocation->height);
-
min_items = MAX (1, priv->min_children_per_line);
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
@@ -1672,8 +1698,7 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
if (n_children <= 0)
return;
- /*
- * Deal with ALIGNED/HOMOGENEOUS modes first, start with
+ /* Deal with ALIGNED/HOMOGENEOUS modes first, start with
* initial guesses at item/line sizes
*/
get_max_item_size (box, priv->orientation, &min_item_size, &nat_item_size);
@@ -1688,12 +1713,14 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
line_length++;
/* Its possible we were allocated just less than the natural width of the
- * minimum item flow length */
+ * minimum item flow length
+ */
line_length = MAX (min_items, line_length);
line_length = MIN (line_length, priv->max_children_per_line);
/* Here we just use the largest height-for-width and use that for the height
- * of all lines */
+ * of all lines
+ */
if (priv->homogeneous)
{
n_lines = n_children / line_length;
@@ -1722,8 +1749,8 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
line_size = MIN (line_size, nat_fixed_line_size);
/* Get the real extra pixels incase of GTK_ALIGN_START lines */
- extra_pixels = avail_size - (line_length - 1) * item_spacing - item_size * line_length;
- extra_line_pixels = avail_other_size - (n_lines - 1) * line_spacing - line_size * n_lines;
+ extra_pixels = avail_size - (line_length - 1) * item_spacing - item_size * line_length;
+ extra_line_pixels = avail_other_size - (n_lines - 1) * line_spacing - line_size * n_lines;
}
else
{
@@ -1827,7 +1854,8 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
* Prepare item/line initial offsets and jump into the
* real allocation loop.
*/
- line_offset = item_offset = 0;
+ line_offset = allocation->y;
+ item_offset = allocation->x;
/* prepend extra space to item_offset/line_offset for SPREAD_END */
item_offset += get_offset_pixels (item_align, extra_pixels);
@@ -1891,7 +1919,7 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
}
}
- item_offset = 0;
+ item_offset = allocation->x;
if (item_align == GTK_ALIGN_CENTER)
{
@@ -1975,6 +2003,8 @@ gtk_flow_box_size_allocate (GtkWidget *widget,
g_free (item_sizes);
g_free (line_sizes);
+
+ gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
}
static GtkSizeRequestMode
@@ -2057,499 +2087,558 @@ get_largest_aligned_line_length (GtkFlowBox *box,
*nat_size = max_nat_size;
}
-
static void
gtk_flow_box_get_preferred_width (GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
+ gint *minimum,
+ gint *natural)
{
- GtkFlowBox *box = GTK_FLOW_BOX (widget);
- GtkFlowBoxPrivate *priv = BOX_PRIV (box);
- gint min_item_width, nat_item_width;
- gint min_items, nat_items;
- gint min_width, nat_width;
-
- min_items = MAX (1, priv->min_children_per_line);
- nat_items = MAX (min_items, priv->max_children_per_line);
-
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- min_width = nat_width = 0;
-
- if (!priv->homogeneous)
- {
- /* When not homogeneous; horizontally oriented boxes
- * need enough width for the widest row */
- if (min_items == 1)
- {
- get_max_item_size (box,
- GTK_ORIENTATION_HORIZONTAL,
- &min_item_width,
- &nat_item_width);
-
- min_width += min_item_width;
- nat_width += nat_item_width;
- }
- else
- {
- gint min_line_length, nat_line_length;
-
- get_largest_aligned_line_length (box,
- GTK_ORIENTATION_HORIZONTAL,
- min_items,
- &min_line_length,
- &nat_line_length);
-
- if (nat_items > min_items)
- get_largest_aligned_line_length (box,
- GTK_ORIENTATION_HORIZONTAL,
- nat_items,
- NULL,
- &nat_line_length);
-
- min_width += min_line_length;
- nat_width += nat_line_length;
- }
- }
- else /* In homogeneous mode; horizontally oriented boxs
- * give the same width to all children */
- {
- get_max_item_size (box, GTK_ORIENTATION_HORIZONTAL,
- &min_item_width, &nat_item_width);
-
- min_width += min_item_width * min_items;
- min_width += (min_items -1) * priv->column_spacing;
-
- nat_width += nat_item_width * nat_items;
- nat_width += (nat_items -1) * priv->column_spacing;
- }
- }
- else /* GTK_ORIENTATION_VERTICAL */
- {
- /* Return the width for the minimum height */
- gint min_height, nat_height;
-
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_height, &nat_height);
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_width_for_height (widget,
- min_height,
- &min_width,
- &nat_width);
-
- }
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ minimum, natural,
+ NULL, NULL);
+}
- if (minimum_size)
- *minimum_size = min_width;
+static void
+gtk_flow_box_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ minimum, natural,
+ NULL, NULL);
+}
- if (natural_size)
- *natural_size = nat_width;
+static void
+gtk_flow_box_get_preferred_height_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum,
+ gint *natural)
+{
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_VERTICAL,
+ width,
+ minimum, natural,
+ NULL, NULL);
}
static void
-gtk_flow_box_get_preferred_height (GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
+gtk_flow_box_get_preferred_width_for_height (GtkWidget *widget,
+ gint height,
+ gint *minimum,
+ gint *natural)
{
+ gtk_css_gadget_get_preferred_size (BOX_PRIV (widget)->gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ height,
+ minimum, natural,
+ NULL, NULL);
+}
+
+static void
+gtk_flow_box_measure (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline,
+ gpointer data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkFlowBox *box = GTK_FLOW_BOX (widget);
GtkFlowBoxPrivate *priv = BOX_PRIV (box);
- gint min_item_height, nat_item_height;
- gint min_items, nat_items;
- gint min_height, nat_height;
- min_items = MAX (1, priv->min_children_per_line);
- nat_items = MAX (min_items, priv->max_children_per_line);
-
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- /* Return the height for the minimum width */
- gint min_width, nat_width;
-
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_width, &nat_width);
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget,
- min_width,
- &min_height,
- &nat_height);
- }
- else /* GTK_ORIENTATION_VERTICAL */
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- min_height = nat_height = 0;
-
- if (! priv->homogeneous)
+ if (for_size < 0)
{
- /* When not homogeneous; vertically oriented boxes
- * need enough height for the tallest column */
- if (min_items == 1)
+ gint min_item_width, nat_item_width;
+ gint min_items, nat_items;
+ gint min_width, nat_width;
+
+ min_items = MAX (1, priv->min_children_per_line);
+ nat_items = MAX (min_items, priv->max_children_per_line);
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
{
- get_max_item_size (box, GTK_ORIENTATION_VERTICAL,
- &min_item_height, &nat_item_height);
+ min_width = nat_width = 0;
+
+ if (!priv->homogeneous)
+ {
+ /* When not homogeneous; horizontally oriented boxes
+ * need enough width for the widest row
+ */
+ if (min_items == 1)
+ {
+ get_max_item_size (box,
+ GTK_ORIENTATION_HORIZONTAL,
+ &min_item_width,
+ &nat_item_width);
+
+ min_width += min_item_width;
+ nat_width += nat_item_width;
+ }
+ else
+ {
+ gint min_line_length, nat_line_length;
+
+ get_largest_aligned_line_length (box,
+ GTK_ORIENTATION_HORIZONTAL,
+ min_items,
+ &min_line_length,
+ &nat_line_length);
+
+ if (nat_items > min_items)
+ get_largest_aligned_line_length (box,
+ GTK_ORIENTATION_HORIZONTAL,
+ nat_items,
+ NULL,
+ &nat_line_length);
+
+ min_width += min_line_length;
+ nat_width += nat_line_length;
+ }
+ }
+ else /* In homogeneous mode; horizontally oriented boxs
+ * give the same width to all children */
+ {
+ get_max_item_size (box, GTK_ORIENTATION_HORIZONTAL,
+ &min_item_width, &nat_item_width);
- min_height += min_item_height;
- nat_height += nat_item_height;
+ min_width += min_item_width * min_items;
+ min_width += (min_items -1) * priv->column_spacing;
+
+ nat_width += nat_item_width * nat_items;
+ nat_width += (nat_items -1) * priv->column_spacing;
+ }
}
- else
+ else /* GTK_ORIENTATION_VERTICAL */
{
- gint min_line_length, nat_line_length;
-
- get_largest_aligned_line_length (box,
- GTK_ORIENTATION_VERTICAL,
- min_items,
- &min_line_length,
- &nat_line_length);
+ /* Return the width for the minimum height */
+ gint min_height;
- if (nat_items > min_items)
- get_largest_aligned_line_length (box,
+ gtk_css_gadget_get_preferred_size (gadget,
GTK_ORIENTATION_VERTICAL,
- nat_items,
- NULL,
- &nat_line_length);
-
- min_height += min_line_length;
- nat_height += nat_line_length;
+ -1,
+ &min_height, NULL,
+ NULL, NULL);
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ min_height,
+ &min_width, &nat_width,
+ NULL, NULL);
}
+ *minimum = min_width;
+ *natural = nat_width;
}
else
{
- /* In homogeneous mode; vertically oriented boxes
- * give the same height to all children
- */
- get_max_item_size (box,
- GTK_ORIENTATION_VERTICAL,
- &min_item_height,
- &nat_item_height);
-
- min_height += min_item_height * min_items;
- min_height += (min_items -1) * priv->row_spacing;
-
- nat_height += nat_item_height * nat_items;
- nat_height += (nat_items -1) * priv->row_spacing;
- }
- }
+ gint min_item_height, nat_item_height;
+ gint min_items;
+ gint min_width, nat_width;
+ gint avail_size, n_children;
- if (minimum_size)
- *minimum_size = min_height;
+ min_items = MAX (1, priv->min_children_per_line);
- if (natural_size)
- *natural_size = nat_height;
-}
+ min_width = 0;
+ nat_width = 0;
-static void
-gtk_flow_box_get_preferred_height_for_width (GtkWidget *widget,
- gint width,
- gint *minimum_height,
- gint *natural_height)
-{
- GtkFlowBox *box = GTK_FLOW_BOX (widget);
- GtkFlowBoxPrivate *priv = BOX_PRIV (box);
- gint min_item_width, nat_item_width;
- gint min_items;
- gint min_height, nat_height;
- gint avail_size, n_children;
-
- min_items = MAX (1, priv->min_children_per_line);
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ /* Return the minimum width */
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &min_width, &nat_width,
+ NULL, NULL);
+ }
+ else /* GTK_ORIENTATION_VERTICAL */
+ {
+ gint min_height;
+ gint line_length;
+ gint item_size, extra_pixels;
- min_height = 0;
- nat_height = 0;
+ n_children = get_visible_children (box);
+ if (n_children <= 0)
+ goto out_width;
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- gint min_width, nat_width;
- gint line_length;
- gint item_size, extra_pixels;
+ /* Make sure its no smaller than the minimum */
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ &min_height, NULL,
+ NULL, NULL);
- n_children = get_visible_children (box);
- if (n_children <= 0)
- goto out;
+ avail_size = MAX (for_size, min_height);
+ if (avail_size <= 0)
+ goto out_width;
- /* Make sure its no smaller than the minimum */
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_width, &nat_width);
+ get_max_item_size (box, GTK_ORIENTATION_VERTICAL, &min_item_height, &nat_item_height);
- avail_size = MAX (width, min_width);
- if (avail_size <= 0)
- goto out;
+ /* By default flow at the natural item width */
+ line_length = avail_size / (nat_item_height + priv->row_spacing);
- get_max_item_size (box, GTK_ORIENTATION_HORIZONTAL, &min_item_width, &nat_item_width);
- if (nat_item_width <= 0)
- goto out;
+ /* After the above aproximation, check if we cant fit one more on the line */
+ if (line_length * priv->row_spacing + (line_length + 1) * nat_item_height <= avail_size)
+ line_length++;
- /* By default flow at the natural item width */
- line_length = avail_size / (nat_item_width + priv->column_spacing);
+ /* Its possible we were allocated just less than the natural width of the
+ * minimum item flow length
+ */
+ line_length = MAX (min_items, line_length);
+ line_length = MIN (line_length, priv->max_children_per_line);
- /* After the above aproximation, check if we cant fit one more on the line */
- if (line_length * priv->column_spacing + (line_length + 1) * nat_item_width <= avail_size)
- line_length++;
+ /* Now we need the real item allocation size */
+ item_size = (avail_size - (line_length - 1) * priv->row_spacing) / line_length;
- /* Its possible we were allocated just less than the natural width of the
- * minimum item flow length
- */
- line_length = MAX (min_items, line_length);
- line_length = MIN (line_length, priv->max_children_per_line);
+ /* Cut out the expand space if we're not distributing any */
+ if (gtk_widget_get_valign (widget) != GTK_ALIGN_FILL)
+ {
+ item_size = MIN (item_size, nat_item_height);
+ extra_pixels = 0;
+ }
+ else
+ /* Collect the extra pixels for expand children */
+ extra_pixels = (avail_size - (line_length - 1) * priv->row_spacing) % line_length;
- /* Now we need the real item allocation size */
- item_size = (avail_size - (line_length - 1) * priv->column_spacing) / line_length;
+ if (priv->homogeneous)
+ {
+ gint min_item_width, nat_item_width;
+ gint lines;
+
+ /* Here we just use the largest height-for-width and
+ * add up the size accordingly
+ */
+ get_largest_size_for_opposing_orientation (box,
+ GTK_ORIENTATION_VERTICAL,
+ item_size,
+ &min_item_width,
+ &nat_item_width);
+
+ /* Round up how many lines we need to allocate for */
+ n_children = get_visible_children (box);
+ lines = n_children / line_length;
+ if ((n_children % line_length) > 0)
+ lines++;
+
+ min_width = min_item_width * lines;
+ nat_width = nat_item_width * lines;
+
+ min_width += (lines - 1) * priv->column_spacing;
+ nat_width += (lines - 1) * priv->column_spacing;
+ }
+ else
+ {
+ gint min_line_width, nat_line_width, i;
+ gboolean first_line = TRUE;
+ GtkRequestedSize *item_sizes;
+ GSequenceIter *iter;
+
+ /* First get the size each set of items take to span the line
+ * when aligning the items above and below after flowping.
+ */
+ item_sizes = fit_aligned_item_requests (box,
+ priv->orientation,
+ avail_size,
+ priv->row_spacing,
+ &line_length,
+ priv->max_children_per_line,
+ n_children);
+
+ /* Get the available remaining size */
+ avail_size -= (line_length - 1) * priv->column_spacing;
+ for (i = 0; i < line_length; i++)
+ avail_size -= item_sizes[i].minimum_size;
+
+ if (avail_size > 0)
+ extra_pixels = gtk_distribute_natural_allocation (avail_size, line_length, item_sizes);
+
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);)
+ {
+ iter = get_largest_size_for_line_in_opposing_orientation (box,
+ GTK_ORIENTATION_VERTICAL,
+ iter,
+ line_length,
+ item_sizes,
+ extra_pixels,
+ &min_line_width,
+ &nat_line_width);
+
+ /* Its possible the last line only had invisible widgets */
+ if (nat_line_width > 0)
+ {
+ if (first_line)
+ first_line = FALSE;
+ else
+ {
+ min_width += priv->column_spacing;
+ nat_width += priv->column_spacing;
+ }
+
+ min_width += min_line_width;
+ nat_width += nat_line_width;
+ }
+ }
+ g_free (item_sizes);
+ }
+ }
- /* Cut out the expand space if we're not distributing any */
- if (gtk_widget_get_halign (widget) != GTK_ALIGN_FILL)
- {
- item_size = MIN (item_size, nat_item_width);
- extra_pixels = 0;
+ out_width:
+ *minimum = min_width;
+ *natural = nat_width;
}
- else
- /* Collect the extra pixels for expand children */
- extra_pixels = (avail_size - (line_length - 1) * priv->column_spacing) % line_length;
-
- if (priv->homogeneous)
+ }
+ else
+ {
+ if (for_size < 0)
{
gint min_item_height, nat_item_height;
- gint lines;
+ gint min_items, nat_items;
+ gint min_height, nat_height;
- /* Here we just use the largest height-for-width and
- * add up the size accordingly
- */
- get_largest_size_for_opposing_orientation (box,
- GTK_ORIENTATION_HORIZONTAL,
- item_size,
- &min_item_height,
- &nat_item_height);
-
- /* Round up how many lines we need to allocate for */
- lines = n_children / line_length;
- if ((n_children % line_length) > 0)
- lines++;
-
- min_height = min_item_height * lines;
- nat_height = nat_item_height * lines;
-
- min_height += (lines - 1) * priv->row_spacing;
- nat_height += (lines - 1) * priv->row_spacing;
- }
- else
- {
- gint min_line_height, nat_line_height, i;
- gboolean first_line = TRUE;
- GtkRequestedSize *item_sizes;
- GSequenceIter *iter;
+ min_items = MAX (1, priv->min_children_per_line);
+ nat_items = MAX (min_items, priv->max_children_per_line);
- /* First get the size each set of items take to span the line
- * when aligning the items above and below after flowping.
- */
- item_sizes = fit_aligned_item_requests (box,
- priv->orientation,
- avail_size,
- priv->column_spacing,
- &line_length,
- priv->max_children_per_line,
- n_children);
-
- /* Get the available remaining size */
- avail_size -= (line_length - 1) * priv->column_spacing;
- for (i = 0; i < line_length; i++)
- avail_size -= item_sizes[i].minimum_size;
-
- if (avail_size > 0)
- extra_pixels = gtk_distribute_natural_allocation (avail_size, line_length, item_sizes);
-
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);)
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ /* Return the height for the minimum width */
+ gint min_width;
+
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &min_width, NULL,
+ NULL, NULL);
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_VERTICAL,
+ min_width,
+ &min_height, &nat_height,
+ NULL, NULL);
+ }
+ else /* GTK_ORIENTATION_VERTICAL */
{
- iter = get_largest_size_for_line_in_opposing_orientation (box,
- GTK_ORIENTATION_HORIZONTAL,
- iter,
- line_length,
- item_sizes,
- extra_pixels,
- &min_line_height,
- &nat_line_height);
- /* Its possible the line only had invisible widgets */
- if (nat_line_height > 0)
+ min_height = nat_height = 0;
+
+ if (! priv->homogeneous)
{
- if (first_line)
- first_line = FALSE;
+ /* When not homogeneous; vertically oriented boxes
+ * need enough height for the tallest column
+ */
+ if (min_items == 1)
+ {
+ get_max_item_size (box, GTK_ORIENTATION_VERTICAL,
+ &min_item_height, &nat_item_height);
+
+ min_height += min_item_height;
+ nat_height += nat_item_height;
+ }
else
{
- min_height += priv->row_spacing;
- nat_height += priv->row_spacing;
+ gint min_line_length, nat_line_length;
+
+ get_largest_aligned_line_length (box,
+ GTK_ORIENTATION_VERTICAL,
+ min_items,
+ &min_line_length,
+ &nat_line_length);
+
+ if (nat_items > min_items)
+ get_largest_aligned_line_length (box,
+ GTK_ORIENTATION_VERTICAL,
+ nat_items,
+ NULL,
+ &nat_line_length);
+
+ min_height += min_line_length;
+ nat_height += nat_line_length;
}
- min_height += min_line_height;
- nat_height += nat_line_height;
}
- }
-
- g_free (item_sizes);
- }
- }
- else /* GTK_ORIENTATION_VERTICAL */
- {
- /* Return the minimum height */
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_height, &nat_height);
- }
-
- out:
-
- if (minimum_height)
- *minimum_height = min_height;
-
- if (natural_height)
- *natural_height = nat_height;
-}
+ else
+ {
+ /* In homogeneous mode; vertically oriented boxes
+ * give the same height to all children
+ */
+ get_max_item_size (box,
+ GTK_ORIENTATION_VERTICAL,
+ &min_item_height,
+ &nat_item_height);
-static void
-gtk_flow_box_get_preferred_width_for_height (GtkWidget *widget,
- gint height,
- gint *minimum_width,
- gint *natural_width)
-{
- GtkFlowBox *box = GTK_FLOW_BOX (widget);
- GtkFlowBoxPrivate *priv = BOX_PRIV (box);
- gint min_item_height, nat_item_height;
- gint min_items;
- gint min_width, nat_width;
- gint avail_size, n_children;
+ min_height += min_item_height * min_items;
+ min_height += (min_items -1) * priv->row_spacing;
- min_items = MAX (1, priv->min_children_per_line);
+ nat_height += nat_item_height * nat_items;
+ nat_height += (nat_items -1) * priv->row_spacing;
+ }
+ }
- min_width = 0;
- nat_width = 0;
+ *minimum = min_height;
+ *natural = nat_height;
+ }
+ else
+ {
+ gint min_item_width, nat_item_width;
+ gint min_items;
+ gint min_height, nat_height;
+ gint avail_size, n_children;
- if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- /* Return the minimum width */
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_width, &nat_width);
- }
- else /* GTK_ORIENTATION_VERTICAL */
- {
- gint min_height, nat_height;
- gint line_length;
- gint item_size, extra_pixels;
+ min_items = MAX (1, priv->min_children_per_line);
- n_children = get_visible_children (box);
- if (n_children <= 0)
- goto out;
+ min_height = 0;
+ nat_height = 0;
- /* Make sure its no smaller than the minimum */
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_height, &nat_height);
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gint min_width;
+ gint line_length;
+ gint item_size, extra_pixels;
- avail_size = MAX (height, min_height);
- if (avail_size <= 0)
- goto out;
+ n_children = get_visible_children (box);
+ if (n_children <= 0)
+ goto out_height;
- get_max_item_size (box, GTK_ORIENTATION_VERTICAL, &min_item_height, &nat_item_height);
+ /* Make sure its no smaller than the minimum */
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &min_width, NULL,
+ NULL, NULL);
- /* By default flow at the natural item width */
- line_length = avail_size / (nat_item_height + priv->row_spacing);
+ avail_size = MAX (for_size, min_width);
+ if (avail_size <= 0)
+ goto out_height;
- /* After the above aproximation, check if we cant fit one more on the line */
- if (line_length * priv->row_spacing + (line_length + 1) * nat_item_height <= avail_size)
- line_length++;
+ get_max_item_size (box, GTK_ORIENTATION_HORIZONTAL, &min_item_width, &nat_item_width);
+ if (nat_item_width <= 0)
+ goto out_height;
- /* Its possible we were allocated just less than the natural width of the
- * minimum item flow length
- */
- line_length = MAX (min_items, line_length);
- line_length = MIN (line_length, priv->max_children_per_line);
+ /* By default flow at the natural item width */
+ line_length = avail_size / (nat_item_width + priv->column_spacing);
- /* Now we need the real item allocation size */
- item_size = (avail_size - (line_length - 1) * priv->row_spacing) / line_length;
+ /* After the above aproximation, check if we cant fit one more on the line */
+ if (line_length * priv->column_spacing + (line_length + 1) * nat_item_width <= avail_size)
+ line_length++;
- /* Cut out the expand space if we're not distributing any */
- if (gtk_widget_get_valign (widget) != GTK_ALIGN_FILL)
- {
- item_size = MIN (item_size, nat_item_height);
- extra_pixels = 0;
- }
- else
- /* Collect the extra pixels for expand children */
- extra_pixels = (avail_size - (line_length - 1) * priv->row_spacing) % line_length;
+ /* Its possible we were allocated just less than the natural width of the
+ * minimum item flow length
+ */
+ line_length = MAX (min_items, line_length);
+ line_length = MIN (line_length, priv->max_children_per_line);
- if (priv->homogeneous)
- {
- gint min_item_width, nat_item_width;
- gint lines;
+ /* Now we need the real item allocation size */
+ item_size = (avail_size - (line_length - 1) * priv->column_spacing) / line_length;
- /* Here we just use the largest height-for-width and
- * add up the size accordingly
- */
- get_largest_size_for_opposing_orientation (box,
- GTK_ORIENTATION_VERTICAL,
- item_size,
- &min_item_width,
- &nat_item_width);
-
- /* Round up how many lines we need to allocate for */
- n_children = get_visible_children (box);
- lines = n_children / line_length;
- if ((n_children % line_length) > 0)
- lines++;
-
- min_width = min_item_width * lines;
- nat_width = nat_item_width * lines;
-
- min_width += (lines - 1) * priv->column_spacing;
- nat_width += (lines - 1) * priv->column_spacing;
- }
- else
- {
- gint min_line_width, nat_line_width, i;
- gboolean first_line = TRUE;
- GtkRequestedSize *item_sizes;
- GSequenceIter *iter;
+ /* Cut out the expand space if we're not distributing any */
+ if (gtk_widget_get_halign (widget) != GTK_ALIGN_FILL)
+ {
+ item_size = MIN (item_size, nat_item_width);
+ extra_pixels = 0;
+ }
+ else
+ /* Collect the extra pixels for expand children */
+ extra_pixels = (avail_size - (line_length - 1) * priv->column_spacing) % line_length;
- /* First get the size each set of items take to span the line
- * when aligning the items above and below after flowping.
- */
- item_sizes = fit_aligned_item_requests (box,
- priv->orientation,
- avail_size,
- priv->row_spacing,
- &line_length,
- priv->max_children_per_line,
- n_children);
-
- /* Get the available remaining size */
- avail_size -= (line_length - 1) * priv->column_spacing;
- for (i = 0; i < line_length; i++)
- avail_size -= item_sizes[i].minimum_size;
-
- if (avail_size > 0)
- extra_pixels = gtk_distribute_natural_allocation (avail_size, line_length, item_sizes);
-
- for (iter = g_sequence_get_begin_iter (priv->children);
- !g_sequence_iter_is_end (iter);)
- {
- iter = get_largest_size_for_line_in_opposing_orientation (box,
- GTK_ORIENTATION_VERTICAL,
- iter,
- line_length,
- item_sizes,
- extra_pixels,
- &min_line_width,
- &nat_line_width);
-
- /* Its possible the last line only had invisible widgets */
- if (nat_line_width > 0)
+ if (priv->homogeneous)
{
- if (first_line)
- first_line = FALSE;
- else
+ gint min_item_height, nat_item_height;
+ gint lines;
+
+ /* Here we just use the largest height-for-width and
+ * add up the size accordingly
+ */
+ get_largest_size_for_opposing_orientation (box,
+ GTK_ORIENTATION_HORIZONTAL,
+ item_size,
+ &min_item_height,
+ &nat_item_height);
+
+ /* Round up how many lines we need to allocate for */
+ lines = n_children / line_length;
+ if ((n_children % line_length) > 0)
+ lines++;
+
+ min_height = min_item_height * lines;
+ nat_height = nat_item_height * lines;
+
+ min_height += (lines - 1) * priv->row_spacing;
+ nat_height += (lines - 1) * priv->row_spacing;
+ }
+ else
+ {
+ gint min_line_height, nat_line_height, i;
+ gboolean first_line = TRUE;
+ GtkRequestedSize *item_sizes;
+ GSequenceIter *iter;
+
+ /* First get the size each set of items take to span the line
+ * when aligning the items above and below after flowping.
+ */
+ item_sizes = fit_aligned_item_requests (box,
+ priv->orientation,
+ avail_size,
+ priv->column_spacing,
+ &line_length,
+ priv->max_children_per_line,
+ n_children);
+
+ /* Get the available remaining size */
+ avail_size -= (line_length - 1) * priv->column_spacing;
+ for (i = 0; i < line_length; i++)
+ avail_size -= item_sizes[i].minimum_size;
+
+ if (avail_size > 0)
+ extra_pixels = gtk_distribute_natural_allocation (avail_size, line_length, item_sizes);
+
+ for (iter = g_sequence_get_begin_iter (priv->children);
+ !g_sequence_iter_is_end (iter);)
{
- min_width += priv->column_spacing;
- nat_width += priv->column_spacing;
+ iter = get_largest_size_for_line_in_opposing_orientation (box,
+ GTK_ORIENTATION_HORIZONTAL,
+ iter,
+ line_length,
+ item_sizes,
+ extra_pixels,
+ &min_line_height,
+ &nat_line_height);
+ /* Its possible the line only had invisible widgets */
+ if (nat_line_height > 0)
+ {
+ if (first_line)
+ first_line = FALSE;
+ else
+ {
+ min_height += priv->row_spacing;
+ nat_height += priv->row_spacing;
+ }
+
+ min_height += min_line_height;
+ nat_height += nat_line_height;
+ }
}
- min_width += min_line_width;
- nat_width += nat_line_width;
+ g_free (item_sizes);
}
}
- g_free (item_sizes);
+ else /* GTK_ORIENTATION_VERTICAL */
+ {
+ /* Return the minimum height */
+ gtk_css_gadget_get_preferred_size (gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ &min_height, &nat_height,
+ NULL, NULL);
+ }
+
+ out_height:
+ *minimum = min_height;
+ *natural = nat_height;
}
}
-
- out:
- if (minimum_width)
- *minimum_width = min_width;
-
- if (natural_width)
- *natural_width = nat_width;
}
/* Drawing {{{3 */
@@ -2558,24 +2647,36 @@ static gboolean
gtk_flow_box_draw (GtkWidget *widget,
cairo_t *cr)
{
+ gtk_css_gadget_draw (BOX_PRIV (widget)->gadget, cr);
+
+ return FALSE;
+}
+
+static gboolean
+gtk_flow_box_render (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkFlowBox *box = GTK_FLOW_BOX (widget);
GtkFlowBoxPrivate *priv = BOX_PRIV (box);
- GtkAllocation allocation = { 0, };
- GtkStyleContext* context;
-
- gtk_widget_get_allocation (GTK_WIDGET (box), &allocation);
- context = gtk_widget_get_style_context (GTK_WIDGET (box));
- gtk_render_background (context, cr, 0, 0, allocation.width, allocation.height);
GTK_WIDGET_CLASS (gtk_flow_box_parent_class)->draw (widget, cr);
if (priv->rubberband_first && priv->rubberband_last)
{
+ GtkStyleContext *context;
GSequenceIter *iter, *iter1, *iter2;
GdkRectangle line_rect, rect;
GArray *lines;
gboolean vertical;
+ context = gtk_widget_get_style_context (GTK_WIDGET (box));
+
vertical = priv->orientation == GTK_ORIENTATION_VERTICAL;
cairo_save (cr);
@@ -2644,10 +2745,7 @@ gtk_flow_box_draw (GtkWidget *widget,
cairo_save (cr);
cairo_clip (cr);
- gtk_widget_get_allocation (widget, &allocation);
- gtk_render_background (context, cr,
- 0, 0,
- allocation.width, allocation.height);
+ gtk_render_background (context, cr, x, y, width, height);
cairo_restore (cr);
cairo_append_path (cr, path);
@@ -3688,6 +3786,8 @@ gtk_flow_box_finalize (GObject *obj)
g_clear_object (&priv->bound_model);
}
+ g_clear_object (&priv->gadget);
+
G_OBJECT_CLASS (gtk_flow_box_parent_class)->finalize (obj);
}
@@ -4026,6 +4126,7 @@ static void
gtk_flow_box_init (GtkFlowBox *box)
{
GtkFlowBoxPrivate *priv = BOX_PRIV (box);
+ GtkCssNode *widget_node;
gtk_widget_set_has_window (GTK_WIDGET (box), TRUE);
gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), TRUE);
@@ -4066,6 +4167,15 @@ gtk_flow_box_init (GtkFlowBox *box)
G_CALLBACK (gtk_flow_box_drag_gesture_update), box);
g_signal_connect (priv->drag_gesture, "drag-end",
G_CALLBACK (gtk_flow_box_drag_gesture_end), box);
+
+ widget_node = gtk_widget_get_css_node (GTK_WIDGET (box));
+ priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
+ GTK_WIDGET (box),
+ gtk_flow_box_measure,
+ gtk_flow_box_allocate,
+ gtk_flow_box_render,
+ NULL,
+ NULL);
}
static void