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
This commit is contained in:
119
gtk/gtkrange.c
119
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);
|
||||
|
||||
@ -2408,6 +2445,26 @@ gtk_range_style_set (GtkWidget *widget,
|
||||
GTK_WIDGET_CLASS (gtk_range_parent_class)->style_set (widget, previous_style);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2415,6 +2472,7 @@ step_back (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_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"
|
||||
|
||||
Reference in New Issue
Block a user