diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2009-01-20 05:10:27 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2009-01-20 05:10:27 +0000 |
commit | 26490a2dd7224eb021bbbc7c2b6051a68ee5c247 (patch) | |
tree | ac93a899ee2bc1935fdbd05cc9c784572f6dc605 /gtk/gtkrange.c | |
parent | b6b52376631e52542237b7f229bb67ab57332746 (diff) | |
download | gtk+-26490a2dd7224eb021bbbc7c2b6051a68ee5c247.tar.gz |
Bug 565656 – Add marks to scales
Bug 565656 – Add marks to scales
* gtk/gtkrange.[hc]: Add internal api to define 'stop values'
that have a little resistance when dragging the slider over it.
* gtk/gtk.symbols:
* gtk/gtkscale.[hc] (gtk_scale_add_mark): New function to add
a 'mark' to a scale, which will draws a tick, plus optionally
some text, and makes the value a stop value.
(gtk_scale_clear_values): Removes all marks.
* tests/testscale.c: Test for marks on scales
* tests/Makefile.am: Integrate it
svn path=/trunk/; revision=22149
Diffstat (limited to 'gtk/gtkrange.c')
-rw-r--r-- | gtk/gtkrange.c | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index e926f70d34..cdf9212839 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -117,6 +117,11 @@ struct _GtkRangeLayout GQuark slider_detail_quark; GQuark stepper_detail_quark; + + gdouble *marks; + gint *mark_pos; + gint n_marks; + gboolean recalc_marks; }; @@ -175,6 +180,7 @@ static gboolean gtk_range_scroll (GtkRange *range, static gboolean gtk_range_update_mouse_location (GtkRange *range); static void gtk_range_calc_layout (GtkRange *range, gdouble adjustment_value); +static void gtk_range_calc_marks (GtkRange *range); static void gtk_range_get_props (GtkRange *range, gint *slider_width, gint *stepper_size, @@ -1216,6 +1222,13 @@ gtk_range_destroy (GtkObject *object) range->adjustment = NULL; } + if (range->layout->n_marks) + { + g_free (range->layout->marks); + g_free (range->layout->mark_pos); + range->layout->n_marks = 0; + } + GTK_OBJECT_CLASS (gtk_range_parent_class)->destroy (object); } @@ -1255,6 +1268,8 @@ gtk_range_size_allocate (GtkWidget *widget, widget->allocation = *allocation; + range->layout->recalc_marks = TRUE; + range->need_recalc = TRUE; gtk_range_calc_layout (range, range->adjustment->value); @@ -1520,6 +1535,7 @@ gtk_range_expose (GtkWidget *widget, expose_area.x -= widget->allocation.x; expose_area.y -= widget->allocation.y; + gtk_range_calc_marks (range); gtk_range_calc_layout (range, range->adjustment->value); sensitive = GTK_WIDGET_IS_SENSITIVE (widget); @@ -2101,6 +2117,10 @@ update_slider_position (GtkRange *range, gint c; gdouble new_value; gboolean handled; + gdouble next_value; + gdouble mark_value; + gdouble mark_delta; + gint i; if (range->orientation == GTK_ORIENTATION_VERTICAL) delta = mouse_y - range->slide_initial_coordinate; @@ -2110,7 +2130,23 @@ update_slider_position (GtkRange *range, c = range->slide_initial_slider_position + delta; new_value = coord_to_value (range, c); - + next_value = coord_to_value (range, c + 1); + mark_delta = fabs (next_value - new_value); + + for (i = 0; i < range->layout->n_marks; i++) + { + mark_value = range->layout->marks[i]; + + if (fabs (range->adjustment->value - mark_value) < 3 * mark_delta) + { + if (fabs (new_value - mark_value) < (range->slider_end - range->slider_start) * 0.5 * mark_delta) + { + new_value = mark_value; + break; + } + } + } + g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_JUMP, new_value, &handled); } @@ -2340,6 +2376,7 @@ gtk_range_adjustment_changed (GtkAdjustment *adjustment, /* create a copy of the layout */ GtkRangeLayout layout = *range->layout; + range->layout->recalc_marks = TRUE; range->need_recalc = TRUE; gtk_range_calc_layout (range, range->adjustment->value); @@ -2409,12 +2446,33 @@ gtk_range_style_set (GtkWidget *widget, } static void +apply_marks (GtkRange *range, + gdouble oldval, + gdouble *newval) +{ + gint i; + gdouble mark; + + for (i = 0; i < range->layout->n_marks; i++) + { + mark = range->layout->marks[i]; + if ((oldval < mark && mark < *newval) || + (oldval > mark && mark > *newval)) + { + *newval = mark; + return; + } + } +} + +static void step_back (GtkRange *range) { gdouble newval; gboolean handled; newval = range->adjustment->value - range->adjustment->step_increment; + apply_marks (range, range->adjustment->value, &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_STEP_BACKWARD, newval, &handled); } @@ -2426,6 +2484,7 @@ step_forward (GtkRange *range) gboolean handled; newval = range->adjustment->value + range->adjustment->step_increment; + apply_marks (range, range->adjustment->value, &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_STEP_FORWARD, newval, &handled); } @@ -2438,6 +2497,7 @@ page_back (GtkRange *range) gboolean handled; newval = range->adjustment->value - range->adjustment->page_increment; + apply_marks (range, range->adjustment->value, &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_PAGE_BACKWARD, newval, &handled); } @@ -2449,6 +2509,7 @@ page_forward (GtkRange *range) gboolean handled; newval = range->adjustment->value + range->adjustment->page_increment; + apply_marks (range, range->adjustment->value, &newval); g_signal_emit (range, signals[CHANGE_VALUE], 0, GTK_SCROLL_PAGE_FORWARD, newval, &handled); } @@ -3337,6 +3398,29 @@ get_area (GtkRange *range, return NULL; } +static void +gtk_range_calc_marks (GtkRange *range) +{ + gint i; + + if (!range->layout->recalc_marks) + return; + + range->layout->recalc_marks = FALSE; + + for (i = 0; i < range->layout->n_marks; i++) + { + range->need_recalc = TRUE; + gtk_range_calc_layout (range, range->layout->marks[i]); + if (range->orientation == GTK_ORIENTATION_HORIZONTAL) + range->layout->mark_pos[i] = range->layout->slider.x + range->layout->slider.width / 2; + else + range->layout->mark_pos[i] = range->layout->slider.y + range->layout->slider.height / 2; + } + + range->need_recalc = TRUE; +} + static gboolean gtk_range_real_change_value (GtkRange *range, GtkScrollType scroll, @@ -3511,5 +3595,38 @@ gtk_range_remove_update_timer (GtkRange *range) } } +void +_gtk_range_set_stop_values (GtkRange *range, + gdouble *values, + gint n_values) +{ + gint i; + + g_free (range->layout->marks); + range->layout->marks = g_new (gdouble, n_values); + + g_free (range->layout->mark_pos); + range->layout->mark_pos = g_new (gint, n_values); + + range->layout->n_marks = n_values; + + for (i = 0; i < n_values; i++) + range->layout->marks[i] = values[i]; + + range->layout->recalc_marks = TRUE; +} + +gint +_gtk_range_get_stop_positions (GtkRange *range, + gint **values) +{ + gtk_range_calc_marks (range); + + if (values) + *values = g_memdup (range->layout->mark_pos, range->layout->n_marks * sizeof (gint)); + + return range->layout->n_marks; +} + #define __GTK_RANGE_C__ #include "gtkaliasdef.c" |