diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2016-02-28 21:13:54 -0800 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2016-02-28 21:49:54 -0800 |
commit | 27fc7a1f1d3c45636a79034e3b86e95cdb589b52 (patch) | |
tree | e3f74986c6a2b45ab61841a11009b62c6b7c7d1f | |
parent | 1b15b2391b6da9639d1bc3e90ddfaa686acdc9ba (diff) | |
download | gtk+-wip/cosimoc/range-gadget.tar.gz |
scale: add gadgets for indicator/label in scale markswip/cosimoc/range-gadget
This will allow us to theme them indepdendently, and specify a size for
the indicator from the theme.
-rw-r--r-- | gtk/gtkscale.c | 280 | ||||
-rw-r--r-- | gtk/theme/Adwaita/_common.scss | 10 | ||||
-rw-r--r-- | gtk/theme/Adwaita/gtk-contained-dark.css | 8 | ||||
-rw-r--r-- | gtk/theme/Adwaita/gtk-contained.css | 8 |
4 files changed, 209 insertions, 97 deletions
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c index 4adc0220da..3caecb7037 100644 --- a/gtk/gtkscale.c +++ b/gtk/gtkscale.c @@ -140,6 +140,8 @@ struct _GtkScaleMark int stop_position; gchar *markup; GtkCssGadget *gadget; + GtkCssGadget *indicator_gadget; + GtkCssGadget *label_gadget; GtkPositionType position; /* always GTK_POS_TOP or GTK_POS_BOTTOM */ }; @@ -257,6 +259,81 @@ gtk_scale_notify (GObject *object, G_OBJECT_CLASS (gtk_scale_parent_class)->notify (object, pspec); } +static void +gtk_scale_allocate_mark (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer user_data) +{ + GtkWidget *widget = gtk_css_gadget_get_owner (gadget); + GtkScaleMark *mark = user_data; + GtkAllocation indicator_alloc, widget_alloc; + int indicator_width, indicator_height; + GtkOrientation orientation; + + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)); + gtk_widget_get_allocation (widget, &widget_alloc); + gtk_css_gadget_get_preferred_size (mark->indicator_gadget, + GTK_ORIENTATION_HORIZONTAL, -1, + &indicator_width, NULL, + NULL, NULL); + gtk_css_gadget_get_preferred_size (mark->indicator_gadget, + GTK_ORIENTATION_VERTICAL, -1, + &indicator_height, NULL, + NULL, NULL); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + indicator_alloc.x = mark->stop_position + widget_alloc.x - indicator_width / 2; + if (mark->position == GTK_POS_TOP) + indicator_alloc.y = allocation->y + allocation->height - indicator_height; + else + indicator_alloc.y = allocation->y; + indicator_alloc.width = indicator_width; + indicator_alloc.height = indicator_height; + } + else + { + if (mark->position == GTK_POS_TOP) + indicator_alloc.x = allocation->x + allocation->width - indicator_width; + else + indicator_alloc.x = allocation->x; + indicator_alloc.y = mark->stop_position + widget_alloc.y - indicator_height / 2; + indicator_alloc.width = indicator_width; + indicator_alloc.height = indicator_height; + } + + gtk_css_gadget_allocate (mark->indicator_gadget, + &indicator_alloc, baseline, + out_clip); + + if (mark->label_gadget) + { + GtkAllocation label_alloc, label_clip; + + label_alloc = *allocation; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + label_alloc.height = allocation->height - indicator_alloc.height; + if (mark->position == GTK_POS_BOTTOM) + label_alloc.y = indicator_alloc.y + indicator_alloc.height; + } + else + { + label_alloc.width = allocation->width - indicator_alloc.width; + if (mark->position == GTK_POS_BOTTOM) + label_alloc.x = indicator_alloc.x + indicator_alloc.width; + } + + gtk_css_gadget_allocate (mark->label_gadget, + &label_alloc, baseline, + &label_clip); + gdk_rectangle_union (out_clip, &label_clip, out_clip); + } +} + static gint find_next_pos (GtkWidget *widget, GSList *list, @@ -1255,14 +1332,14 @@ gtk_scale_screen_changed (GtkWidget *widget, } static void -gtk_scale_measure_mark (GtkCssGadget *gadget, - GtkOrientation orientation, - gint for_size, - gint *minimum, - gint *natural, - gint *minimum_baseline, - gint *natural_baseline, - gpointer user_data) +gtk_scale_measure_mark_label (GtkCssGadget *gadget, + GtkOrientation orientation, + gint for_size, + gint *minimum, + gint *natural, + gint *minimum_baseline, + gint *natural_baseline, + gpointer user_data) { GtkWidget *widget = gtk_css_gadget_get_owner (gadget); GtkScaleMark *mark = user_data; @@ -1288,6 +1365,36 @@ gtk_scale_measure_mark (GtkCssGadget *gadget, } static void +gtk_scale_measure_mark (GtkCssGadget *gadget, + GtkOrientation orientation, + gint for_size, + gint *minimum, + gint *natural, + gint *minimum_baseline, + gint *natural_baseline, + gpointer user_data) +{ + GtkScaleMark *mark = user_data; + + gtk_css_gadget_get_preferred_size (mark->indicator_gadget, + orientation, -1, + minimum, natural, + NULL, NULL); + + if (mark->label_gadget) + { + int label_min, label_nat; + + gtk_css_gadget_get_preferred_size (mark->label_gadget, + orientation, -1, + &label_min, &label_nat, + NULL, NULL); + *minimum += label_min; + *natural += label_nat; + } +} + +static void gtk_scale_measure_marks (GtkCssGadget *gadget, GtkOrientation orientation, gint for_size, @@ -1397,100 +1504,57 @@ gtk_scale_get_preferred_height (GtkWidget *widget, } static gboolean -gtk_scale_render_mark (GtkCssGadget *gadget, - cairo_t *cr, - int x, - int y, - int width, - int height, - gpointer user_data) +gtk_scale_render_mark_indicator (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer user_data) { GtkWidget *widget = gtk_css_gadget_get_owner (gadget); - GtkScale *scale = GTK_SCALE (widget); - GtkScaleMark *mark = user_data; - GtkOrientation orientation; - GtkAllocation slider_alloc; - GtkCssGadget *slider_gadget; GtkStyleContext *context; - PangoLayout *layout; - - slider_gadget = gtk_range_get_slider_gadget (GTK_RANGE (scale)); - gtk_css_gadget_get_content_allocation (slider_gadget, - &slider_alloc, NULL); - - orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (scale)); + GtkOrientation orientation; + orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)); context = gtk_widget_get_style_context (widget); gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget)); - layout = gtk_widget_create_pango_layout (widget, NULL); - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - int y1, y2; - - if (mark->position == GTK_POS_TOP) - { - y1 = y + height; - y2 = y + height - slider_alloc.height / 4; - } - else - { - y1 = y; - y2 = y + slider_alloc.height / 4; - } - - gtk_render_line (context, cr, - mark->stop_position, y1, - mark->stop_position, y2); - - if (mark->markup) - { - int y3; - - pango_layout_set_markup (layout, mark->markup, -1); - - if (mark->position == GTK_POS_TOP) - y3 = y; - else - y3 = y2; - - gtk_render_layout (context, cr, x, y3, layout); - } - } + gtk_render_line (context, cr, + x + width / 2, y, + x + width / 2, y + height); else - { - int x1, x2; + gtk_render_line (context, cr, + x, y + height / 2, + x + width, y + height / 2); - if (mark->position == GTK_POS_TOP) - { - x1 = x + width; - x2 = x + width - slider_alloc.width / 4; - } - else - { - x1 = x; - x2 = x + slider_alloc.width / 4; - } + gtk_style_context_restore (context); - gtk_render_line (context, cr, - x1, mark->stop_position, - x2, mark->stop_position); + return FALSE; +} - if (mark->markup) - { - int x3; +static gboolean +gtk_scale_render_mark_label (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer user_data) +{ + GtkWidget *widget = gtk_css_gadget_get_owner (gadget); + GtkScaleMark *mark = user_data; + GtkStyleContext *context; + PangoLayout *layout; - pango_layout_set_markup (layout, mark->markup, -1); + context = gtk_widget_get_style_context (widget); + gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget)); - if (mark->position == GTK_POS_TOP) - x3 = x; - else - x3 = x2; + layout = gtk_widget_create_pango_layout (widget, NULL); + pango_layout_set_markup (layout, mark->markup, -1); - gtk_render_layout (context, cr, x3, y, layout); - } - } + gtk_render_layout (context, cr, x, y, layout); gtk_style_context_restore (context); g_object_unref (layout); @@ -1499,6 +1563,24 @@ gtk_scale_render_mark (GtkCssGadget *gadget, } static gboolean +gtk_scale_render_mark (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer user_data) +{ + GtkScaleMark *mark = user_data; + + gtk_css_gadget_draw (mark->indicator_gadget, cr); + if (mark->label_gadget) + gtk_css_gadget_draw (mark->label_gadget, cr); + + return FALSE; +} + +static gboolean gtk_scale_render_marks (GtkCssGadget *gadget, cairo_t *cr, int x, @@ -1778,6 +1860,8 @@ gtk_scale_mark_free (gpointer data) { GtkScaleMark *mark = data; + g_clear_object (&mark->label_gadget); + g_object_unref (mark->indicator_gadget); g_object_unref (mark->gadget); g_free (mark->markup); g_free (mark); @@ -1853,7 +1937,7 @@ gtk_scale_add_mark (GtkScale *scale, priv = scale->priv; widget_node = gtk_widget_get_css_node (GTK_WIDGET (scale)); - mark = g_new (GtkScaleMark, 1); + mark = g_new0 (GtkScaleMark, 1); mark->value = value; mark->markup = g_strdup (markup); if (position == GTK_POS_LEFT || @@ -1905,11 +1989,29 @@ gtk_scale_add_mark (GtkScale *scale, gtk_css_custom_gadget_new ("mark", GTK_WIDGET (scale), NULL, NULL, gtk_scale_measure_mark, - NULL, + gtk_scale_allocate_mark, gtk_scale_render_mark, mark, NULL); gtk_css_gadget_set_state (mark->gadget, gtk_css_node_get_state (marks_node)); + mark->indicator_gadget = + gtk_css_custom_gadget_new ("indicator", + GTK_WIDGET (scale), mark->gadget, NULL, + NULL, + NULL, + gtk_scale_render_mark_indicator, + mark, NULL); + if (mark->markup) + mark->label_gadget = + gtk_css_custom_gadget_new ("label", + GTK_WIDGET (scale), mark->gadget, + mark->position == GTK_POS_TOP ? + NULL : mark->indicator_gadget, + gtk_scale_measure_mark_label, + NULL, + gtk_scale_render_mark_label, + mark, NULL); + m = g_slist_find (priv->marks, mark); m = m->next; while (m) diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss index 5adbd2a1c1..2a0608739d 100644 --- a/gtk/theme/Adwaita/_common.scss +++ b/gtk/theme/Adwaita/_common.scss @@ -2578,8 +2578,14 @@ scale { } marks { color: gtkalpha(currentColor, 0.4); } - &.horizontal marks { min-height: 8px; } - &.vertical marks { min-width: 8px; } + &.horizontal mark indicator { + min-height: 8px; + min-width: 1px; + } + &.vertical mark indicator { + min-height: 1px; + min-width: 8px; + } // *WARNING* scale with marks madness following diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css index f56f6b50ee..5025b1704c 100644 --- a/gtk/theme/Adwaita/gtk-contained-dark.css +++ b/gtk/theme/Adwaita/gtk-contained-dark.css @@ -2757,9 +2757,11 @@ scale { -gtk-icon-shadow: none; } scale marks { color: alpha(currentColor,0.4); } - scale.horizontal marks { - min-height: 8px; } - scale.vertical marks { + scale.horizontal mark indicator { + min-height: 8px; + min-width: 1px; } + scale.vertical mark indicator { + min-height: 1px; min-width: 8px; } scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > trough > slider { margin: -9px; diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css index 3662aff95c..e35f5be8d7 100644 --- a/gtk/theme/Adwaita/gtk-contained.css +++ b/gtk/theme/Adwaita/gtk-contained.css @@ -2788,9 +2788,11 @@ scale { -gtk-icon-shadow: none; } scale marks { color: alpha(currentColor,0.4); } - scale.horizontal marks { - min-height: 8px; } - scale.vertical marks { + scale.horizontal mark indicator { + min-height: 8px; + min-width: 1px; } + scale.vertical mark indicator { + min-height: 1px; min-width: 8px; } scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > trough > slider { margin: -9px; |