diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-12-12 19:41:40 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2015-12-15 08:41:16 -0500 |
commit | 49e24b05b58b13004a76f7e0ef0370ef191c59f4 (patch) | |
tree | dc0ec5244c5dddb434443c9e6791aeffda30183d | |
parent | 3b264ea55519b260c15e61ff6e59b9c49e7b4fbf (diff) | |
download | gtk+-49e24b05b58b13004a76f7e0ef0370ef191c59f4.tar.gz |
flowbox: convert to gadgets
-rw-r--r-- | gtk/gtkflowbox.c | 998 |
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 |