summaryrefslogtreecommitdiff
path: root/gtk/gtkrange.c
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2009-01-20 05:10:27 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2009-01-20 05:10:27 +0000
commit26490a2dd7224eb021bbbc7c2b6051a68ee5c247 (patch)
treeac93a899ee2bc1935fdbd05cc9c784572f6dc605 /gtk/gtkrange.c
parentb6b52376631e52542237b7f229bb67ab57332746 (diff)
downloadgtk+-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.c119
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"