diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2016-01-19 07:22:33 -0200 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2016-02-29 10:45:12 -0800 |
commit | 413b9d5b3c10e9b296b09a99f34558d0bf36a72c (patch) | |
tree | 737bd907dc695018e8d62092d3d8a2a227cd573a /gtk/gtkrange.c | |
parent | e9fe46ea5f1a90991154d7564d28123fb25ec567 (diff) | |
download | gtk+-413b9d5b3c10e9b296b09a99f34558d0bf36a72c.tar.gz |
range: continue porting to GtkGadgets
This commit rewrites a lot of the GtkRange internals to make full use
of the gadget structure.
Diffstat (limited to 'gtk/gtkrange.c')
-rw-r--r-- | gtk/gtkrange.c | 1267 |
1 files changed, 492 insertions, 775 deletions
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index aa102b2c21..ca5253e5ca 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -32,6 +32,7 @@ #include "gtkrangeprivate.h" #include "gtkadjustmentprivate.h" +#include "gtkboxgadgetprivate.h" #include "gtkbuiltiniconprivate.h" #include "gtkcsscustomgadgetprivate.h" #include "gtkcolorscaleprivate.h" @@ -96,19 +97,12 @@ struct _GtkRangePrivate GtkSensitivityType lower_sensitivity; GtkSensitivityType upper_sensitivity; - GdkRectangle range_rect; /* Area of entire stepper + trough assembly in widget->window coords */ - /* These are in widget->window coordinates */ - GdkRectangle stepper_a; - GdkRectangle stepper_b; - GdkRectangle stepper_c; - GdkRectangle stepper_d; - GdkRectangle trough; /* The trough rectangle is the area the thumb can slide in, not the entire range_rect */ - GdkRectangle slider; GdkWindow *event_window; /* Steppers are: < > ---- < > * a b c d */ + GtkCssGadget *gadget; GtkCssGadget *stepper_a_gadget; GtkCssGadget *stepper_b_gadget; GtkCssGadget *stepper_c_gadget; @@ -265,23 +259,7 @@ static gboolean gtk_range_scroll (GtkRange *range, static void gtk_range_update_mouse_location (GtkRange *range); static void gtk_range_calc_slider (GtkRange *range); static void gtk_range_calc_stepper_sensitivity (GtkRange *range); -static void gtk_range_calc_layout (GtkRange *range); static void gtk_range_calc_marks (GtkRange *range); -static void gtk_range_get_props (GtkRange *range, - gint *slider_width, - gint *stepper_size, - gint *trough_border, - gint *stepper_spacing); -static void gtk_range_calc_request (GtkRange *range, - gint slider_width, - gint stepper_size, - gint trough_border, - gint stepper_spacing, - GdkRectangle *range_rect, - GtkBorder *border, - gint *n_steppers_p, - gboolean *has_steppers_ab, - gboolean *has_steppers_cd); static void gtk_range_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data); static void gtk_range_adjustment_changed (GtkAdjustment *adjustment, @@ -300,12 +278,25 @@ static void gtk_range_state_flags_changed (GtkWidget *widget, GtkStateFlags previous_state); static void gtk_range_measure_trough (GtkCssGadget *gadget, GtkOrientation orientation, - int for_size, - int *minimum, - int *natural, - int *minimum_baseline, - int *natural_baseline, - gpointer data); + gint for_size, + gint *minimum, + gint *natural, + gint *minimum_baseline, + gint *natural_baseline, + gpointer user_data); +static void gtk_range_allocate_trough (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer data); +static gboolean gtk_range_render_trough (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer user_data); + G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkRange, gtk_range, GTK_TYPE_WIDGET, G_ADD_PRIVATE (GtkRange) @@ -640,6 +631,31 @@ gtk_range_class_init (GtkRangeClass *class) } static void +gtk_range_sync_orientation (GtkRange *range) +{ + GtkRangePrivate *priv = range->priv; + GtkOrientation orientation; + int trough_pos = 0; + + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range)); + _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range)); + gtk_box_gadget_set_orientation (GTK_BOX_GADGET (priv->gadget), orientation); + gtk_box_gadget_remove_gadget (GTK_BOX_GADGET (priv->gadget), priv->trough_gadget); + + if (priv->stepper_a_gadget) + trough_pos++; + if (priv->stepper_b_gadget) + trough_pos++; + + if (orientation == GTK_ORIENTATION_VERTICAL) + gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), trough_pos, + priv->trough_gadget, FALSE, TRUE, GTK_ALIGN_CENTER); + else + gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), trough_pos, + priv->trough_gadget, TRUE, FALSE, GTK_ALIGN_CENTER); +} + +static void gtk_range_set_property (GObject *object, guint prop_id, const GValue *value, @@ -654,8 +670,7 @@ gtk_range_set_property (GObject *object, if (priv->orientation != g_value_get_enum (value)) { priv->orientation = g_value_get_enum (value); - - _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range)); + gtk_range_sync_orientation (range); gtk_widget_queue_resize (GTK_WIDGET (range)); g_object_notify_by_pspec (object, pspec); } @@ -765,19 +780,19 @@ gtk_range_init (GtkRange *range) priv->fill_level = G_MAXDOUBLE; priv->timer = NULL; - _gtk_orientable_set_style_classes (GTK_ORIENTABLE (range)); - widget_node = gtk_widget_get_css_node (GTK_WIDGET (range)); + priv->gadget = gtk_box_gadget_new_for_node (widget_node, GTK_WIDGET (range)); + priv->trough_gadget = gtk_css_custom_gadget_new ("trough", GTK_WIDGET (range), NULL, NULL, gtk_range_measure_trough, - NULL, - NULL, + gtk_range_allocate_trough, + gtk_range_render_trough, NULL, NULL); gtk_css_gadget_set_state (priv->trough_gadget, gtk_css_node_get_state (widget_node)); - gtk_css_node_set_parent (gtk_css_gadget_get_node (priv->trough_gadget), widget_node); + gtk_range_sync_orientation (range); priv->slider_gadget = gtk_builtin_icon_new ("slider", GTK_WIDGET (range), @@ -1072,7 +1087,7 @@ gtk_range_set_slider_size_fixed (GtkRange *range, priv->slider_size_fixed = size_fixed ? TRUE : FALSE; if (priv->adjustment && gtk_widget_get_mapped (GTK_WIDGET (range))) - gtk_range_calc_slider (range); + gtk_css_gadget_queue_allocate (priv->slider_gadget); } } @@ -1146,6 +1161,45 @@ gtk_range_get_min_slider_size (GtkRange *range) return range->priv->min_slider_size; } +/* Returns the gadget rect in widget coordinates */ +static void +measure_one_gadget_alloc (GtkRange *range, + GtkCssGadget *gadget, + gboolean use_content, + GtkAllocation *allocation_out) +{ + GtkAllocation widget_alloc; + + g_assert (allocation_out != NULL); + + gtk_widget_get_allocation (GTK_WIDGET (range), &widget_alloc); + + if (use_content) + gtk_css_gadget_get_content_allocation (gadget, + allocation_out, NULL); + else + gtk_css_gadget_get_margin_allocation (gadget, + allocation_out, NULL); + + allocation_out->x -= widget_alloc.x; + allocation_out->y -= widget_alloc.y; +} + +static void +measure_one_gadget (GtkCssGadget *gadget, + int *width_out, + int *height_out) +{ + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_HORIZONTAL, -1, + width_out, NULL, + NULL, NULL); + gtk_css_gadget_get_preferred_size (gadget, + GTK_ORIENTATION_VERTICAL, -1, + height_out, NULL, + NULL, NULL); +} + /** * gtk_range_get_range_rect: * @range: a #GtkRange @@ -1169,9 +1223,7 @@ gtk_range_get_range_rect (GtkRange *range, priv = range->priv; - gtk_range_calc_layout (range); - - *range_rect = priv->range_rect; + measure_one_gadget_alloc (range, priv->gadget, FALSE, range_rect); } /** @@ -1195,26 +1247,27 @@ gtk_range_get_slider_range (GtkRange *range, gint *slider_end) { GtkRangePrivate *priv; + GtkAllocation slider_alloc; g_return_if_fail (GTK_IS_RANGE (range)); priv = range->priv; - gtk_range_calc_layout (range); + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); if (priv->orientation == GTK_ORIENTATION_VERTICAL) { if (slider_start) - *slider_start = priv->slider.y; + *slider_start = slider_alloc.y; if (slider_end) - *slider_end = priv->slider.y + priv->slider.height; + *slider_end = slider_alloc.y + slider_alloc.height; } else { if (slider_start) - *slider_start = priv->slider.x; + *slider_start = slider_alloc.x; if (slider_end) - *slider_end = priv->slider.x + priv->slider.width; + *slider_end = slider_alloc.x + slider_alloc.width; } } @@ -1636,6 +1689,7 @@ gtk_range_destroy (GtkWidget *widget) g_clear_object (&priv->multipress_gesture); g_clear_object (&priv->long_press_gesture); + g_clear_object (&priv->gadget); g_clear_object (&priv->trough_gadget); g_clear_object (&priv->fill_gadget); g_clear_object (&priv->highlight_gadget); @@ -1672,84 +1726,91 @@ gtk_range_destroy (GtkWidget *widget) static void gtk_range_measure_trough (GtkCssGadget *gadget, GtkOrientation orientation, - int for_size, - int *minimum, - int *natural, - int *minimum_baseline, - int *natural_baseline, - gpointer data) + gint for_size, + gint *minimum, + gint *natural, + gint *minimum_baseline, + gint *natural_baseline, + gpointer user_data) { GtkWidget *widget = gtk_css_gadget_get_owner (gadget); GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; - gint slider_width, stepper_size, trough_border; - gint stepper_spacing; - gint n_steppers, n_steppers_ab, n_steppers_cd; - GtkBorder border; - GdkRectangle range_rect; - - gtk_widget_style_get (widget, - "slider-width", &slider_width, - "trough-border", &trough_border, - "stepper-size", &stepper_size, - "stepper-spacing", &stepper_spacing, - NULL); - - border.left = 0; - border.right = 0; - border.top = 0; - border.bottom = 0; - - if (GTK_RANGE_GET_CLASS (range)->get_range_border) - GTK_RANGE_GET_CLASS (range)->get_range_border (range, &border); + gint min, nat; - n_steppers_ab = 0; - n_steppers_cd = 0; + *minimum = *natural = 0; - if (priv->stepper_a_gadget) - n_steppers_ab += 1; - if (priv->stepper_b_gadget) - n_steppers_ab += 1; - if (priv->stepper_c_gadget) - n_steppers_cd += 1; - if (priv->stepper_d_gadget) - n_steppers_cd += 1; + if (priv->fill_gadget) + { + gtk_css_gadget_get_preferred_size (priv->fill_gadget, + orientation, for_size, + &min, &nat, + NULL, NULL); + *minimum = MAX (*minimum, min); + *natural = MAX (*natural, nat); + } - n_steppers = n_steppers_ab + n_steppers_cd; + if (priv->highlight_gadget) + { + gtk_css_gadget_get_preferred_size (priv->highlight_gadget, + orientation, for_size, + &min, &nat, + NULL, NULL); + *minimum = MAX (*minimum, min); + *natural = MAX (*natural, nat); + } +} - range_rect.x = 0; - range_rect.y = 0; +static void +gtk_range_size_request (GtkWidget *widget, + GtkOrientation orientation, + gint *minimum, + gint *natural) +{ + GtkRange *range = GTK_RANGE (widget); + GtkRangePrivate *priv = range->priv; + GtkBorder border = { 0 }; + gint box_min, box_nat, slider_min, slider_nat; - /* We never expand to fill available space in the small dimension - * (i.e. vertical scrollbars are always a fixed width) - */ - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - { - range_rect.width = trough_border * 2 + slider_width; - range_rect.height = stepper_size * n_steppers + trough_border * 2 + priv->min_slider_size; + /* First, measure everything */ + gtk_css_gadget_get_preferred_size (priv->gadget, + orientation, + -1, + &box_min, &box_nat, + NULL, NULL); + gtk_css_gadget_get_preferred_size (priv->slider_gadget, + orientation, + -1, + &slider_min, &slider_nat, + NULL, NULL); - if (n_steppers_ab > 0) - range_rect.height += stepper_spacing; + if (GTK_RANGE_GET_CLASS (range)->get_range_border) + GTK_RANGE_GET_CLASS (range)->get_range_border (range, &border); - if (n_steppers_cd > 0) - range_rect.height += stepper_spacing; + if (priv->orientation != orientation) + { + /* If we're measuring opposite orientation, return the maximum size */ + *minimum = MAX (box_min, slider_min); + *natural = MAX (box_nat, slider_nat); } else { - range_rect.width = stepper_size * n_steppers + trough_border * 2 + priv->min_slider_size; - range_rect.height = trough_border * 2 + slider_width; - - if (n_steppers_ab > 0) - range_rect.width += stepper_spacing; - - if (n_steppers_cd > 0) - range_rect.width += stepper_spacing; + /* Otherwise, we report the box size */ + *minimum = box_min; + *natural = box_nat; } + /* Finally, add the border */ if (orientation == GTK_ORIENTATION_HORIZONTAL) - *minimum = *natural = range_rect.width + border.left + border.right; + { + *minimum += border.left + border.right; + *natural += border.left + border.right; + } else - *minimum = *natural = range_rect.height + border.top + border.bottom; + { + *minimum += border.top + border.bottom; + *natural += border.top + border.bottom; + } } static void @@ -1757,11 +1818,8 @@ gtk_range_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { - gtk_css_gadget_get_preferred_size (GTK_RANGE (widget)->priv->trough_gadget, - GTK_ORIENTATION_HORIZONTAL, - -1, - minimum, natural, - NULL, NULL); + gtk_range_size_request (widget, GTK_ORIENTATION_HORIZONTAL, + minimum, natural); } static void @@ -1769,49 +1827,92 @@ gtk_range_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { - gtk_css_gadget_get_preferred_size (GTK_RANGE (widget)->priv->trough_gadget, - GTK_ORIENTATION_VERTICAL, - -1, - minimum, natural, - NULL, NULL); + gtk_range_size_request (widget, GTK_ORIENTATION_VERTICAL, + minimum, natural); } static void -gtk_range_allocate_trough (GtkRange *range, - GtkAllocation *out_clip) +gtk_range_allocate_highlight (GtkRange *range, + GtkAllocation *out_clip) { GtkRangePrivate *priv = range->priv; - GtkWidget *widget = GTK_WIDGET (range); - GtkAllocation widget_alloc; - GtkAllocation trough_alloc = priv->range_rect; - gint stepper_size; - gint stepper_spacing; + int baseline; + GtkAllocation trough_alloc, highlight_alloc, slider_alloc; + int highlight_min; - gtk_widget_style_get (widget, - "stepper-size", &stepper_size, - "stepper-spacing", &stepper_spacing, - NULL); + g_assert (priv->has_origin); - gtk_widget_get_allocation (widget, &widget_alloc); - trough_alloc.x += widget_alloc.x; - trough_alloc.y += widget_alloc.y; + /* Note: the highlight is allocated on top of the trough, not inside */ + gtk_css_gadget_get_border_allocation (priv->trough_gadget, + &trough_alloc, &baseline); + gtk_css_gadget_get_content_allocation (priv->slider_gadget, + &slider_alloc, NULL); - gtk_css_gadget_allocate (priv->trough_gadget, - &trough_alloc, - gtk_widget_get_allocated_baseline (widget), + gtk_css_gadget_get_preferred_size (priv->highlight_gadget, + priv->orientation, -1, + &highlight_min, NULL, + NULL, NULL); + + highlight_alloc = trough_alloc; + + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (!should_invert (range)) + { + highlight_alloc.x = trough_alloc.x; + highlight_alloc.width = slider_alloc.x + slider_alloc.width / 2 - trough_alloc.x; + } + else + { + highlight_alloc.x = slider_alloc.x + slider_alloc.width / 2; + highlight_alloc.width = trough_alloc.x + trough_alloc.width - highlight_alloc.x; + } + + highlight_alloc.width = MAX (highlight_min, highlight_alloc.width); + } + else + { + if (!should_invert (range)) + { + highlight_alloc.y = trough_alloc.y; + highlight_alloc.height = slider_alloc.y + slider_alloc.height / 2 - trough_alloc.y; + } + else + { + highlight_alloc.y = slider_alloc.y + slider_alloc.height / 2; + highlight_alloc.height = trough_alloc.y + trough_alloc.height - highlight_alloc.y; + } + + highlight_alloc.height = MAX (highlight_min, highlight_alloc.height); + } + + gtk_css_gadget_allocate (priv->highlight_gadget, + &highlight_alloc, + baseline, out_clip); +} + +static void +gtk_range_allocate_trough (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer data) +{ + GtkWidget *widget = gtk_css_gadget_get_owner (gadget); + GtkRange *range = GTK_RANGE (widget); + GtkRangePrivate *priv = range->priv; if (priv->show_fill_level && gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) != 0) { - gdouble level; - gdouble fill = 0.0; - GtkAllocation content_alloc, fill_alloc, fill_clip; + gdouble level, fill; + GtkAllocation gadget_alloc, fill_alloc, fill_clip; - gtk_css_gadget_get_content_allocation (priv->trough_gadget, - &content_alloc, NULL); - fill_alloc = content_alloc; + /* Note: the fill is allocated on top of the trough, not inside */ + gtk_css_gadget_get_border_allocation (gadget, &gadget_alloc, NULL); + fill_alloc = gadget_alloc; level = CLAMP (priv->fill_level, gtk_adjustment_get_lower (priv->adjustment), @@ -1828,151 +1929,187 @@ gtk_range_allocate_trough (GtkRange *range, fill_alloc.width *= fill; if (should_invert (range)) - fill_alloc.x += content_alloc.width - fill_alloc.width; + fill_alloc.x += gadget_alloc.width - fill_alloc.width; } else { fill_alloc.height *= fill; if (should_invert (range)) - fill_alloc.y += content_alloc.height - (fill_alloc.height * fill); + fill_alloc.y += gadget_alloc.height - (fill_alloc.height * fill); } gtk_css_gadget_allocate (priv->fill_gadget, &fill_alloc, - gtk_widget_get_allocated_baseline (widget), + baseline, &fill_clip); gdk_rectangle_union (out_clip, &fill_clip, out_clip); } +} - if (priv->has_origin) - { - GtkAllocation content_alloc, highlight_alloc, highlight_clip, slider_alloc; - - gtk_css_gadget_get_content_allocation (priv->trough_gadget, - &content_alloc, NULL); - gtk_css_gadget_get_content_allocation (priv->slider_gadget, - &slider_alloc, NULL); - highlight_alloc = content_alloc; +/* Clamp dimensions and border inside allocation, such that we prefer + * to take space from border not dimensions in all directions, and prefer to + * give space to border over dimensions in one direction. + */ +static void +clamp_dimensions (GtkAllocation *allocation, + int *width, + int *height, + GtkBorder *border, + gboolean border_expands_horizontally) +{ + gint extra, shortage; - if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) + /* Width */ + extra = allocation->width - border->left - border->right - *width; + if (extra > 0) + { + if (border_expands_horizontally) { - if (!should_invert (range)) - { - highlight_alloc.x = content_alloc.x; - highlight_alloc.width = slider_alloc.x + slider_alloc.width / 2 - content_alloc.x; - } - else - { - highlight_alloc.x = slider_alloc.x + slider_alloc.width / 2; - highlight_alloc.width = content_alloc.x + content_alloc.width - highlight_alloc.x; - } + border->left += extra / 2; + border->right += extra / 2 + extra % 2; } else { - if (!should_invert (range)) - { - highlight_alloc.y = content_alloc.y; - highlight_alloc.height = slider_alloc.y + slider_alloc.height / 2 - content_alloc.y; - } - else - { - highlight_alloc.y = slider_alloc.y + slider_alloc.height / 2; - highlight_alloc.height = content_alloc.y + content_alloc.height - highlight_alloc.y; - } + *width += extra; + } + } + + /* See if we can fit rect, if not kill the border */ + shortage = *width - allocation->width; + if (shortage > 0) + { + *width = allocation->width; + /* lose the border */ + border->left = 0; + border->right = 0; + } + else + { + /* See if we can fit rect with borders */ + shortage = *width + border->left + border->right - allocation->width; + if (shortage > 0) + { + /* Shrink borders */ + border->left -= shortage / 2; + border->right -= shortage / 2 + shortage % 2; } + } - gtk_css_gadget_allocate (priv->highlight_gadget, - &highlight_alloc, - gtk_widget_get_allocated_baseline (widget), - &highlight_clip); - gdk_rectangle_union (out_clip, &highlight_clip, out_clip); + /* Height */ + extra = allocation->height - border->top - border->bottom - *height; + if (extra > 0) + { + if (border_expands_horizontally) + { + /* don't expand border vertically */ + *height += extra; + } + else + { + border->top += extra / 2; + border->bottom += extra / 2 + extra % 2; + } + } + + /* See if we can fit rect, if not kill the border */ + shortage = *height - allocation->height; + if (shortage > 0) + { + *height = allocation->height; + /* lose the border */ + border->top = 0; + border->bottom = 0; + } + else + { + /* See if we can fit rect with borders */ + shortage = *height + border->top + border->bottom - allocation->height; + if (shortage > 0) + { + /* Shrink borders */ + border->top -= shortage / 2; + border->bottom -= shortage / 2 + shortage % 2; + } } } static void +gtk_range_allocate_box (GtkRange *range, + GtkAllocation *out_clip) +{ + GtkRangePrivate *priv = range->priv; + GtkWidget *widget = GTK_WIDGET (range); + GtkBorder border = { 0 }; + GtkAllocation box_alloc, widget_alloc; + int box_min_width, box_min_height; + + gtk_widget_get_allocation (widget, &widget_alloc); + + if (GTK_RANGE_GET_CLASS (range)->get_range_border) + GTK_RANGE_GET_CLASS (range)->get_range_border (range, &border); + + measure_one_gadget (priv->gadget, &box_min_width, &box_min_height); + + if (priv->orientation == GTK_ORIENTATION_VERTICAL) + clamp_dimensions (&widget_alloc, &box_min_width, &box_min_height, &border, TRUE); + else + clamp_dimensions (&widget_alloc, &box_min_width, &box_min_height, &border, FALSE); + + box_alloc.x = border.left + widget_alloc.x; + box_alloc.y = border.top + widget_alloc.y; + box_alloc.width = box_min_width; + box_alloc.height = box_min_height; + + gtk_css_gadget_allocate (priv->gadget, + &box_alloc, + gtk_widget_get_allocated_baseline (widget), + out_clip); + + /* TODO: we should compute a proper clip from get_range_border(), + * but this will at least give us outset shadows. + */ + gdk_rectangle_union (out_clip, &widget_alloc, out_clip); +} + +static void gtk_range_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; - GtkAllocation clip, trough_clip, slider_clip, stepper_clip; - GtkAllocation slider_alloc, stepper_alloc; - gint baseline; + GtkAllocation clip, slider_alloc, slider_clip, highlight_clip; gtk_widget_set_allocation (widget, allocation); - baseline = gtk_widget_get_allocated_baseline (widget); if (gtk_widget_get_realized (widget)) gdk_window_move_resize (priv->event_window, allocation->x, allocation->y, allocation->width, allocation->height); + /* Box */ + gtk_range_allocate_box (range, &clip); + + /* Slider and highlight */ gtk_range_calc_marks (range); - gtk_range_calc_layout (range); + gtk_range_calc_stepper_sensitivity (range); - slider_alloc = priv->slider; + gtk_range_compute_slider_position (range, + gtk_adjustment_get_value (priv->adjustment), + &slider_alloc); slider_alloc.x += allocation->x; slider_alloc.y += allocation->y; gtk_css_gadget_allocate (priv->slider_gadget, &slider_alloc, - baseline, + gtk_widget_get_allocated_baseline (widget), &slider_clip); + gdk_rectangle_union (&clip, &slider_clip, &clip); - gtk_range_allocate_trough (range, &trough_clip); - gdk_rectangle_union (&trough_clip, &slider_clip, &clip); - - if (priv->stepper_a_gadget) - { - stepper_alloc = priv->stepper_a; - stepper_alloc.x += allocation->x; - stepper_alloc.y += allocation->y; - - gtk_css_gadget_allocate (priv->stepper_a_gadget, - &stepper_alloc, - baseline, - &stepper_clip); - gdk_rectangle_union (&clip, &stepper_clip, &clip); - } - - if (priv->stepper_b_gadget) - { - stepper_alloc = priv->stepper_b; - stepper_alloc.x += allocation->x; - stepper_alloc.y += allocation->y; - - gtk_css_gadget_allocate (priv->stepper_b_gadget, - &stepper_alloc, - baseline, - &stepper_clip); - gdk_rectangle_union (&clip, &stepper_clip, &clip); - } - - if (priv->stepper_c_gadget) - { - stepper_alloc = priv->stepper_c; - stepper_alloc.x += allocation->x; - stepper_alloc.y += allocation->y; - - gtk_css_gadget_allocate (priv->stepper_c_gadget, - &stepper_alloc, - baseline, - &stepper_clip); - gdk_rectangle_union (&clip, &stepper_clip, &clip); - } - - if (priv->stepper_d_gadget) + if (priv->has_origin) { - stepper_alloc = priv->stepper_d; - stepper_alloc.x += allocation->x; - stepper_alloc.y += allocation->y; - - gtk_css_gadget_allocate (priv->stepper_d_gadget, - &stepper_alloc, - baseline, - &stepper_clip); - gdk_rectangle_union (&clip, &stepper_clip, &clip); + gtk_range_allocate_highlight (range, &highlight_clip); + gdk_rectangle_union (&clip, &highlight_clip, &clip); } gtk_widget_set_clip (widget, &clip); @@ -2113,6 +2250,30 @@ gtk_range_state_flags_changed (GtkWidget *widget, } static gboolean +gtk_range_render_trough (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer user_data) +{ + GtkWidget *widget = gtk_css_gadget_get_owner (gadget); + GtkRange *range = GTK_RANGE (widget); + GtkRangePrivate *priv = range->priv; + + if (priv->show_fill_level && + gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) - + gtk_adjustment_get_lower (priv->adjustment) != 0) + gtk_css_gadget_draw (priv->fill_gadget, cr); + + if (priv->has_origin) + gtk_css_gadget_draw (priv->highlight_gadget, cr); + + return gtk_widget_has_visible_focus (widget); +} + +static gboolean gtk_range_draw (GtkWidget *widget, cairo_t *cr) { @@ -2120,9 +2281,6 @@ gtk_range_draw (GtkWidget *widget, GtkRangePrivate *priv = range->priv; gboolean draw_trough = TRUE; gboolean draw_slider = TRUE; - GtkStyleContext *context; - - context = gtk_widget_get_style_context (widget); if (GTK_IS_SCALE (widget) && gtk_adjustment_get_upper (priv->adjustment) == gtk_adjustment_get_lower (priv->adjustment)) @@ -2137,25 +2295,7 @@ gtk_range_draw (GtkWidget *widget, } if (draw_trough) - { - gtk_css_gadget_draw (priv->trough_gadget, cr); - - if (priv->show_fill_level && - gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) - - gtk_adjustment_get_lower (priv->adjustment) != 0) - gtk_css_gadget_draw (priv->fill_gadget, cr); - - if (priv->has_origin) - gtk_css_gadget_draw (priv->highlight_gadget, cr); - } - - if (!(gtk_widget_get_state_flags (widget) & GTK_STATE_FLAG_INSENSITIVE) && - gtk_widget_has_visible_focus (widget)) - gtk_render_focus (context, cr, - priv->range_rect.x, - priv->range_rect.y, - priv->range_rect.width, - priv->range_rect.height); + gtk_css_gadget_draw (priv->trough_gadget, cr); if (draw_slider) gtk_css_gadget_draw (priv->slider_gadget, cr); @@ -2310,18 +2450,22 @@ coord_to_value (GtkRange *range, gint trough_length; gint trough_start; gint slider_length; + GtkAllocation slider_alloc, trough_alloc; + + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); + measure_one_gadget_alloc (range, priv->trough_gadget, TRUE, &trough_alloc); if (priv->orientation == GTK_ORIENTATION_VERTICAL) { - trough_length = priv->trough.height; - trough_start = priv->trough.y; - slider_length = priv->slider.height; + trough_length = trough_alloc.height; + trough_start = trough_alloc.y; + slider_length = slider_alloc.height; } else { - trough_length = priv->trough.width; - trough_start = priv->trough.x; - slider_length = priv->slider.width; + trough_length = trough_alloc.width; + trough_start = trough_alloc.x; + slider_length = slider_alloc.width; } if (trough_length == slider_length) @@ -2346,10 +2490,13 @@ gtk_range_key_press (GtkWidget *widget, GdkDevice *device; GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = range->priv; + GtkAllocation slider_alloc; device = gdk_event_get_device ((GdkEvent *) event); device = gdk_device_get_associated_device (device); + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); + if (gtk_gesture_is_active (priv->drag_gesture) && device == gtk_gesture_get_device (priv->drag_gesture) && event->keyval == GDK_KEY_Escape && @@ -2364,9 +2511,9 @@ gtk_range_key_press (GtkWidget *widget, event->keyval == GDK_KEY_Shift_R)) { if (priv->orientation == GTK_ORIENTATION_VERTICAL) - priv->slide_initial_slider_position = priv->slider.y; + priv->slide_initial_slider_position = slider_alloc.y; else - priv->slide_initial_slider_position = priv->slider.x; + priv->slide_initial_slider_position = slider_alloc.x; update_zoom_state (range, !priv->zoom); return GDK_EVENT_STOP; @@ -2382,20 +2529,22 @@ gtk_range_long_press_gesture_pressed (GtkGestureLongPress *gesture, GtkRange *range) { GtkRangePrivate *priv = range->priv; + GtkAllocation slider_alloc; gtk_range_update_mouse_location (range); + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); if (priv->mouse_location == MOUSE_SLIDER && !priv->zoom) { if (priv->orientation == GTK_ORIENTATION_VERTICAL) { - priv->slide_initial_slider_position = priv->slider.y; - priv->slide_initial_coordinate_delta = y - priv->slider.y; + priv->slide_initial_slider_position = slider_alloc.y; + priv->slide_initial_coordinate_delta = y - slider_alloc.y; } else { - priv->slide_initial_slider_position = priv->slider.x; - priv->slide_initial_coordinate_delta = x - priv->slider.x; + priv->slide_initial_slider_position = slider_alloc.x; + priv->slide_initial_coordinate_delta = x - slider_alloc.x; } update_zoom_state (range, TRUE); @@ -2419,6 +2568,7 @@ gtk_range_multipress_gesture_pressed (GtkGestureMultiPress *gesture, gboolean shift_pressed; guint button; GdkModifierType state_mask; + GtkAllocation slider_alloc; if (!gtk_widget_has_focus (widget)) gtk_widget_grab_focus (widget); @@ -2436,6 +2586,7 @@ gtk_range_multipress_gesture_pressed (GtkGestureMultiPress *gesture, priv->mouse_y = y; gtk_range_update_mouse_location (range); + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); g_object_get (gtk_widget_get_settings (widget), "gtk-primary-button-warps-slider", &primary_warps, @@ -2453,23 +2604,19 @@ gtk_range_multipress_gesture_pressed (GtkGestureMultiPress *gesture, if (priv->mouse_location == MOUSE_SLIDER) { - GdkRectangle slider; - /* Shift-click in the slider = fine adjustment */ if (shift_pressed) update_zoom_state (range, TRUE); - slider = priv->slider; - if (priv->orientation == GTK_ORIENTATION_VERTICAL) { - priv->slide_initial_slider_position = slider.y; - priv->slide_initial_coordinate_delta = y - slider.y; + priv->slide_initial_slider_position = slider_alloc.y; + priv->slide_initial_coordinate_delta = y - slider_alloc.y; } else { - priv->slide_initial_slider_position = slider.x; - priv->slide_initial_coordinate_delta = x - slider.x; + priv->slide_initial_slider_position = slider_alloc.x; + priv->slide_initial_coordinate_delta = x - slider_alloc.x; } range_grab_add (range, MOUSE_SLIDER); @@ -2514,8 +2661,8 @@ gtk_range_multipress_gesture_pressed (GtkGestureMultiPress *gesture, slider_low_value = coord_to_value (range, priv->orientation == GTK_ORIENTATION_VERTICAL ? - y - priv->slider.height : - x - priv->slider.width); + y - slider_alloc.height : + x - slider_alloc.width); /* compute new value for warped slider */ new_value = slider_low_value + (slider_high_value - slider_low_value) / 2; @@ -2614,11 +2761,15 @@ update_slider_position (GtkRange *range, gdouble zoom; gint slider_start, slider_end; gint i; + GtkAllocation slider_alloc, trough_alloc; + + measure_one_gadget_alloc (range, priv->slider_gadget, FALSE, &slider_alloc); + measure_one_gadget_alloc (range, priv->trough_gadget, FALSE, &trough_alloc); if (priv->zoom) { zoom = MIN(1.0, (priv->orientation == GTK_ORIENTATION_VERTICAL ? - priv->trough.height : priv->trough.width) / + trough_alloc.height : trough_alloc.width) / (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment))); @@ -2633,9 +2784,9 @@ update_slider_position (GtkRange *range, if (priv->slide_initial_slider_position == -1) { if (priv->orientation == GTK_ORIENTATION_VERTICAL) - priv->slide_initial_slider_position = (zoom * (mouse_y - priv->slide_initial_coordinate_delta) - priv->slider.y) / (zoom - 1.0); + priv->slide_initial_slider_position = (zoom * (mouse_y - priv->slide_initial_coordinate_delta) - slider_alloc.y) / (zoom - 1.0); else - priv->slide_initial_slider_position = (zoom * (mouse_x - priv->slide_initial_coordinate_delta) - priv->slider.x) / (zoom - 1.0); + priv->slide_initial_slider_position = (zoom * (mouse_x - priv->slide_initial_coordinate_delta) - slider_alloc.x) / (zoom - 1.0); } if (priv->orientation == GTK_ORIENTATION_VERTICAL) @@ -3198,37 +3349,6 @@ gtk_range_move_slider (GtkRange *range, gtk_widget_error_bell (GTK_WIDGET (range)); } -static void -gtk_range_get_props (GtkRange *range, - gint *slider_width, - gint *stepper_size, - gint *trough_border, - gint *stepper_spacing) -{ - GtkWidget *widget = GTK_WIDGET (range); - gint tmp_slider_width, tmp_stepper_size, tmp_trough_border; - gint tmp_stepper_spacing; - - gtk_widget_style_get (widget, - "slider-width", &tmp_slider_width, - "trough-border", &tmp_trough_border, - "stepper-size", &tmp_stepper_size, - "stepper-spacing", &tmp_stepper_spacing, - NULL); - - if (slider_width) - *slider_width = tmp_slider_width; - - if (trough_border) - *trough_border = tmp_trough_border; - - if (stepper_size) - *stepper_size = tmp_stepper_size; - - if (stepper_spacing) - *stepper_spacing = tmp_stepper_spacing; -} - #define POINT_IN_RECT(xcoord, ycoord, rect) \ ((xcoord) >= (rect).x && \ (xcoord) < ((rect).x + (rect).width) && \ @@ -3254,17 +3374,21 @@ gtk_range_update_mouse_location (GtkRange *range) if (priv->grab_location != MOUSE_OUTSIDE) priv->mouse_location = priv->grab_location; - else if (POINT_IN_RECT (x, y, priv->stepper_a)) + else if (priv->stepper_a_gadget && + gtk_css_gadget_content_box_contains_point (priv->stepper_a_gadget, x, y)) priv->mouse_location = MOUSE_STEPPER_A; - else if (POINT_IN_RECT (x, y, priv->stepper_b)) + else if (priv->stepper_b_gadget && + gtk_css_gadget_content_box_contains_point (priv->stepper_b_gadget, x, y)) priv->mouse_location = MOUSE_STEPPER_B; - else if (POINT_IN_RECT (x, y, priv->stepper_c)) + else if (priv->stepper_c_gadget && + gtk_css_gadget_content_box_contains_point (priv->stepper_c_gadget, x, y)) priv->mouse_location = MOUSE_STEPPER_C; - else if (POINT_IN_RECT (x, y, priv->stepper_d)) + else if (priv->stepper_d_gadget && + gtk_css_gadget_content_box_contains_point (priv->stepper_d_gadget, x, y)) priv->mouse_location = MOUSE_STEPPER_D; - else if (POINT_IN_RECT (x, y, priv->slider)) + else if (gtk_css_gadget_content_box_contains_point (priv->slider_gadget, x, y)) priv->mouse_location = MOUSE_SLIDER; - else if (POINT_IN_RECT (x, y, priv->trough)) + else if (gtk_css_gadget_content_box_contains_point (priv->trough_gadget, x, y)) priv->mouse_location = MOUSE_TROUGH; else if (POINT_IN_RECT (x, y, allocation)) priv->mouse_location = MOUSE_WIDGET; @@ -3286,189 +3410,17 @@ gtk_range_update_mouse_location (GtkRange *range) } } -/* Clamp rect, border inside widget->allocation, such that we prefer - * to take space from border not rect in all directions, and prefer to - * give space to border over rect in one direction. - */ -static void -clamp_dimensions (GtkWidget *widget, - GdkRectangle *rect, - GtkBorder *border, - gboolean border_expands_horizontally) -{ - GtkAllocation allocation; - gint extra, shortage; - - g_return_if_fail (rect->x == 0); - g_return_if_fail (rect->y == 0); - g_return_if_fail (rect->width >= 0); - g_return_if_fail (rect->height >= 0); - - gtk_widget_get_allocation (widget, &allocation); - - /* Width */ - - extra = allocation.width - border->left - border->right - rect->width; - if (extra > 0) - { - if (border_expands_horizontally) - { - border->left += extra / 2; - border->right += extra / 2 + extra % 2; - } - else - { - rect->width += extra; - } - } - - /* See if we can fit rect, if not kill the border */ - shortage = rect->width - allocation.width; - if (shortage > 0) - { - rect->width = allocation.width; - /* lose the border */ - border->left = 0; - border->right = 0; - } - else - { - /* See if we can fit rect with borders */ - shortage = rect->width + border->left + border->right - allocation.width; - if (shortage > 0) - { - /* Shrink borders */ - border->left -= shortage / 2; - border->right -= shortage / 2 + shortage % 2; - } - } - - /* Height */ - - extra = allocation.height - border->top - border->bottom - rect->height; - if (extra > 0) - { - if (border_expands_horizontally) - { - /* don't expand border vertically */ - rect->height += extra; - } - else - { - border->top += extra / 2; - border->bottom += extra / 2 + extra % 2; - } - } - - /* See if we can fit rect, if not kill the border */ - shortage = rect->height - allocation.height; - if (shortage > 0) - { - rect->height = allocation.height; - /* lose the border */ - border->top = 0; - border->bottom = 0; - } - else - { - /* See if we can fit rect with borders */ - shortage = rect->height + border->top + border->bottom - allocation.height; - if (shortage > 0) - { - /* Shrink borders */ - border->top -= shortage / 2; - border->bottom -= shortage / 2 + shortage % 2; - } - } -} - -static void -gtk_range_calc_request (GtkRange *range, - gint slider_width, - gint stepper_size, - gint trough_border, - gint stepper_spacing, - GdkRectangle *range_rect, - GtkBorder *border, - gint *n_steppers_p, - gboolean *has_steppers_ab, - gboolean *has_steppers_cd) -{ - GtkRangePrivate *priv = range->priv; - gint n_steppers; - gint n_steppers_ab; - gint n_steppers_cd; - - border->left = 0; - border->right = 0; - border->top = 0; - border->bottom = 0; - - if (GTK_RANGE_GET_CLASS (range)->get_range_border) - GTK_RANGE_GET_CLASS (range)->get_range_border (range, border); - - n_steppers_ab = 0; - n_steppers_cd = 0; - - if (priv->stepper_a_gadget) - n_steppers_ab += 1; - if (priv->stepper_b_gadget) - n_steppers_ab += 1; - if (priv->stepper_c_gadget) - n_steppers_cd += 1; - if (priv->stepper_d_gadget) - n_steppers_cd += 1; - - n_steppers = n_steppers_ab + n_steppers_cd; - - range_rect->x = 0; - range_rect->y = 0; - - /* We never expand to fill available space in the small dimension - * (i.e. vertical scrollbars are always a fixed width) - */ - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - { - range_rect->width = + trough_border * 2 + slider_width; - range_rect->height = stepper_size * n_steppers + trough_border * 2 + priv->min_slider_size; - - if (n_steppers_ab > 0) - range_rect->height += stepper_spacing; - - if (n_steppers_cd > 0) - range_rect->height += stepper_spacing; - } - else - { - range_rect->width = stepper_size * n_steppers + trough_border * 2 + priv->min_slider_size; - range_rect->height = trough_border * 2 + slider_width; - - if (n_steppers_ab > 0) - range_rect->width += stepper_spacing; - - if (n_steppers_cd > 0) - range_rect->width += stepper_spacing; - } - - if (n_steppers_p) - *n_steppers_p = n_steppers; - - if (has_steppers_ab) - *has_steppers_ab = (n_steppers_ab > 0); - - if (has_steppers_cd) - *has_steppers_cd = (n_steppers_cd > 0); -} - static void gtk_range_compute_slider_position (GtkRange *range, gdouble adjustment_value, GdkRectangle *slider_rect) { GtkRangePrivate *priv = range->priv; - gint trough_border; + GtkAllocation trough_content_alloc; + int slider_width, slider_height; - gtk_range_get_props (range, NULL, NULL, &trough_border, NULL); + measure_one_gadget (priv->slider_gadget, &slider_width, &slider_height); + measure_one_gadget_alloc (range, priv->trough_gadget, TRUE, &trough_content_alloc); if (priv->orientation == GTK_ORIENTATION_VERTICAL) { @@ -3477,12 +3429,19 @@ gtk_range_compute_slider_position (GtkRange *range, /* Slider fits into the trough, with stepper_spacing on either side, * and the size/position based on the adjustment or fixed, depending. */ - slider_rect->x = priv->trough.x + trough_border; - slider_rect->width = priv->trough.width - trough_border * 2; + slider_rect->x = trough_content_alloc.x + (int) floor ((trough_content_alloc.width - slider_width) / 2); + slider_rect->width = slider_width; /* Compute slider position/length */ - top = priv->trough.y; - bottom = priv->trough.y + priv->trough.height; + top = trough_content_alloc.y; + bottom = top + trough_content_alloc.height; + + /* Scale slider half extends over the trough edge */ + if (GTK_IS_SCALE (range)) + { + top -= priv->min_slider_size / 2; + bottom += priv->min_slider_size / 2; + } /* slider height is the fraction (page_size / * total_adjustment_range) times the trough height in pixels @@ -3498,7 +3457,7 @@ gtk_range_compute_slider_position (GtkRange *range, priv->slider_size_fixed) height = priv->min_slider_size; - height = MIN (height, priv->trough.height); + height = MIN (height, trough_content_alloc.height); y = top; @@ -3521,12 +3480,19 @@ gtk_range_compute_slider_position (GtkRange *range, /* Slider fits into the trough, with stepper_spacing on either side, * and the size/position based on the adjustment or fixed, depending. */ - slider_rect->y = priv->trough.y + trough_border; - slider_rect->height = priv->trough.height - trough_border * 2; + slider_rect->y = trough_content_alloc.y + (int) floor ((trough_content_alloc.height - slider_height) / 2); + slider_rect->height = slider_height; /* Compute slider position/length */ - left = priv->trough.x; - right = priv->trough.x + priv->trough.width; + left = trough_content_alloc.x; + right = left + trough_content_alloc.width; + + /* Scale slider half extends over the trough edge */ + if (GTK_IS_SCALE (range)) + { + left -= priv->min_slider_size / 2; + right += priv->min_slider_size / 2; + } /* slider width is the fraction (page_size / * total_adjustment_range) times the trough width in pixels @@ -3542,8 +3508,8 @@ gtk_range_compute_slider_position (GtkRange *range, priv->slider_size_fixed) width = priv->min_slider_size; - width = MIN (width, priv->trough.width); - + width = MIN (width, trough_content_alloc.width); + x = left; if (gtk_adjustment_get_upper (priv->adjustment) - gtk_adjustment_get_lower (priv->adjustment) - gtk_adjustment_get_page_size (priv->adjustment) != 0) @@ -3564,7 +3530,6 @@ static void gtk_range_calc_slider (GtkRange *range) { GtkRangePrivate *priv = range->priv; - GdkRectangle new_slider; gboolean visible; if (GTK_IS_SCALE (range) && @@ -3573,22 +3538,10 @@ gtk_range_calc_slider (GtkRange *range) else visible = TRUE; - gtk_range_compute_slider_position (range, - gtk_adjustment_get_value (priv->adjustment), - &new_slider); - - if (gdk_rectangle_equal (&priv->slider, &new_slider) && - visible == gtk_css_gadget_get_visible (priv->slider_gadget)) - return; - gtk_css_gadget_set_visible (priv->slider_gadget, visible); gtk_range_queue_draw_location (range, MOUSE_SLIDER); - priv->slider = new_slider; - - gtk_range_queue_draw_location (range, MOUSE_SLIDER); - if (priv->has_origin) gtk_range_queue_draw_location (range, MOUSE_TROUGH); @@ -3652,244 +3605,6 @@ gtk_range_calc_stepper_sensitivity (GtkRange *range) } static void -gtk_range_calc_layout (GtkRange *range) -{ - GtkRangePrivate *priv = range->priv; - gint slider_width, stepper_size, trough_border, stepper_spacing; - GtkBorder border; - gint n_steppers; - gboolean has_steppers_ab; - gboolean has_steppers_cd; - GdkRectangle range_rect; - GtkWidget *widget; - - /* If we have a too-small allocation, we prefer the steppers over - * the trough/slider, probably the steppers are a more useful - * feature in small spaces. - * - * Also, we prefer to draw the range itself rather than the border - * areas if there's a conflict, since the borders will be decoration - * not controls. Though this depends on subclasses cooperating by - * not drawing on priv->range_rect. - */ - - widget = GTK_WIDGET (range); - - gtk_range_get_props (range, - &slider_width, &stepper_size, - &trough_border, - &stepper_spacing); - - gtk_range_calc_request (range, - slider_width, stepper_size, - trough_border, stepper_spacing, - &range_rect, &border, &n_steppers, - &has_steppers_ab, &has_steppers_cd); - - /* We never expand to fill available space in the small dimension - * (i.e. vertical scrollbars are always a fixed width) - */ - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - { - clamp_dimensions (widget, &range_rect, &border, TRUE); - } - else - { - clamp_dimensions (widget, &range_rect, &border, FALSE); - } - - range_rect.x = border.left; - range_rect.y = border.top; - - priv->range_rect = range_rect; - - if (priv->orientation == GTK_ORIENTATION_VERTICAL) - { - gint stepper_width, stepper_height; - - /* Steppers are the width of the range, and stepper_size in - * height, or if we don't have enough height, divided equally - * among available space. - */ - stepper_width = range_rect.width - trough_border * 2; - - if (stepper_width < 1) - stepper_width = range_rect.width; /* screw the trough border */ - - if (n_steppers == 0) - stepper_height = 0; /* avoid divide by n_steppers */ - else - stepper_height = MIN (stepper_size, (range_rect.height / n_steppers)); - - /* Stepper A */ - - priv->stepper_a.x = range_rect.x + trough_border; - priv->stepper_a.y = range_rect.y + trough_border; - - if (priv->stepper_a_gadget) - { - priv->stepper_a.width = stepper_width; - priv->stepper_a.height = stepper_height; - } - else - { - priv->stepper_a.width = 0; - priv->stepper_a.height = 0; - } - - /* Stepper B */ - - priv->stepper_b.x = priv->stepper_a.x; - priv->stepper_b.y = priv->stepper_a.y + priv->stepper_a.height; - - if (priv->stepper_b_gadget) - { - priv->stepper_b.width = stepper_width; - priv->stepper_b.height = stepper_height; - } - else - { - priv->stepper_b.width = 0; - priv->stepper_b.height = 0; - } - - /* Stepper D */ - - if (priv->stepper_d_gadget) - { - priv->stepper_d.width = stepper_width; - priv->stepper_d.height = stepper_height; - } - else - { - priv->stepper_d.width = 0; - priv->stepper_d.height = 0; - } - - priv->stepper_d.x = priv->stepper_a.x; - priv->stepper_d.y = range_rect.y + range_rect.height - priv->stepper_d.height - trough_border; - - /* Stepper C */ - - if (priv->stepper_c_gadget) - { - priv->stepper_c.width = stepper_width; - priv->stepper_c.height = stepper_height; - } - else - { - priv->stepper_c.width = 0; - priv->stepper_c.height = 0; - } - - priv->stepper_c.x = priv->stepper_a.x; - priv->stepper_c.y = priv->stepper_d.y - priv->stepper_c.height; - - /* Now the trough is the remaining space between steppers B and C, - * if any, minus spacing - */ - priv->trough.x = range_rect.x; - priv->trough.y = priv->stepper_b.y + priv->stepper_b.height + stepper_spacing * has_steppers_ab; - priv->trough.width = range_rect.width; - priv->trough.height = priv->stepper_c.y - priv->trough.y - stepper_spacing * has_steppers_cd; - } - else - { - gint stepper_width, stepper_height; - - /* Steppers are the height of the range, and stepper_size in - * width, or if we don't have enough width, divided equally - * among available space. - */ - stepper_height = range_rect.height - trough_border * 2; - - if (stepper_height < 1) - stepper_height = range_rect.height; /* screw the trough border */ - - if (n_steppers == 0) - stepper_width = 0; /* avoid divide by n_steppers */ - else - stepper_width = MIN (stepper_size, (range_rect.width / n_steppers)); - - /* Stepper A */ - - priv->stepper_a.x = range_rect.x + trough_border; - priv->stepper_a.y = range_rect.y + trough_border; - - if (priv->stepper_a_gadget) - { - priv->stepper_a.width = stepper_width; - priv->stepper_a.height = stepper_height; - } - else - { - priv->stepper_a.width = 0; - priv->stepper_a.height = 0; - } - - /* Stepper B */ - - priv->stepper_b.x = priv->stepper_a.x + priv->stepper_a.width; - priv->stepper_b.y = priv->stepper_a.y; - - if (priv->stepper_b_gadget) - { - priv->stepper_b.width = stepper_width; - priv->stepper_b.height = stepper_height; - } - else - { - priv->stepper_b.width = 0; - priv->stepper_b.height = 0; - } - - /* Stepper D */ - - if (priv->stepper_d_gadget) - { - priv->stepper_d.width = stepper_width; - priv->stepper_d.height = stepper_height; - } - else - { - priv->stepper_d.width = 0; - priv->stepper_d.height = 0; - } - - priv->stepper_d.x = range_rect.x + range_rect.width - priv->stepper_d.width - trough_border; - priv->stepper_d.y = priv->stepper_a.y; - - - /* Stepper C */ - - if (priv->stepper_c_gadget) - { - priv->stepper_c.width = stepper_width; - priv->stepper_c.height = stepper_height; - } - else - { - priv->stepper_c.width = 0; - priv->stepper_c.height = 0; - } - - priv->stepper_c.x = priv->stepper_d.x - priv->stepper_c.width; - priv->stepper_c.y = priv->stepper_a.y; - - /* Now the trough is the remaining space between steppers B and C, - * if any - */ - priv->trough.x = priv->stepper_b.x + priv->stepper_b.width + stepper_spacing * has_steppers_ab; - priv->trough.y = range_rect.y; - priv->trough.width = priv->stepper_c.x - priv->trough.x - stepper_spacing * has_steppers_cd; - priv->trough.height = range_rect.height; - } - - gtk_range_calc_slider (range); - gtk_range_calc_stepper_sensitivity (range); -} - -static void gtk_range_queue_draw_location (GtkRange *range, MouseLocation location) { @@ -4166,13 +3881,13 @@ sync_stepper_gadget (GtkRange *range, GtkCssGadget **gadget_ptr, const gchar *class, GtkCssImageBuiltinType image_type, - GtkCssGadget *before, - GtkCssGadget *after) + int position) { GtkWidget *widget; GtkCssGadget *gadget; - GtkCssNode *widget_node, *node; + GtkCssNode *widget_node; gboolean has_stepper; + GtkRangePrivate *priv = range->priv; has_stepper = (*gadget_ptr != NULL); if (has_stepper == should_have_stepper) @@ -4193,12 +3908,8 @@ sync_stepper_gadget (GtkRange *range, gtk_css_gadget_add_class (gadget, class); gtk_css_gadget_set_state (gadget, gtk_css_node_get_state (widget_node)); - node = gtk_css_gadget_get_node (gadget); - if (before) - gtk_css_node_insert_before (widget_node, node, gtk_css_gadget_get_node (before)); - else - gtk_css_node_insert_after (widget_node, node, gtk_css_gadget_get_node (after)); - + gtk_box_gadget_insert_gadget (GTK_BOX_GADGET (priv->gadget), position, + gadget, FALSE, FALSE, GTK_ALIGN_FILL); *gadget_ptr = gadget; } @@ -4210,38 +3921,44 @@ _gtk_range_set_steppers (GtkRange *range, gboolean has_d) { GtkRangePrivate *priv = range->priv; + int pos = 0; sync_stepper_gadget (range, has_a, &priv->stepper_a_gadget, "up", priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_CSS_IMAGE_BUILTIN_ARROW_UP : GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT, - priv->stepper_b_gadget ? priv->stepper_b_gadget : priv->trough_gadget, - NULL); + pos); + if (has_a) + pos++; sync_stepper_gadget (range, has_b, &priv->stepper_b_gadget, "down", priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN : GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT, - priv->trough_gadget, - NULL); + pos); + if (has_b) + pos++; + + /* account for the trough in the box */ + pos++; sync_stepper_gadget (range, has_c, &priv->stepper_c_gadget, "up", priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_CSS_IMAGE_BUILTIN_ARROW_UP : GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT, - NULL, - priv->trough_gadget); + pos); + if (has_c) + pos++; sync_stepper_gadget (range, has_d, &priv->stepper_d_gadget, "down", priv->orientation == GTK_ORIENTATION_VERTICAL ? GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN : GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT, - NULL, - priv->stepper_c_gadget ? priv->stepper_c_gadget : priv->trough_gadget); + pos); gtk_widget_queue_resize (GTK_WIDGET (range)); } |