Commit eb4a6856 authored by Matthias Clasen's avatar Matthias Clasen

GtkScale: Fix marks for inverted scales

Problem pointed out by Stefan Sauer in bug 667598. The solution
here is different from his patch. We always draw marks in increasing
direction, and flip the marks and stop positions to match.
parent fa7207dc
......@@ -85,7 +85,7 @@ struct _GtkScalePrivate
{
PangoLayout *layout;
GList *marks;
GSList *marks;
gint digits;
......@@ -166,6 +166,44 @@ G_DEFINE_TYPE_WITH_CODE (GtkScale, gtk_scale, GTK_TYPE_RANGE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_scale_buildable_interface_init))
static gint
compare_marks (gconstpointer a, gconstpointer b, gpointer data)
{
gboolean inverted = GPOINTER_TO_INT (data);
gint val;
const GtkScaleMark *ma, *mb;
val = inverted ? -1 : 1;
ma = a; mb = b;
return (ma->value > mb->value) ? val : ((ma->value < mb->value) ? -val : 0);
}
static void
gtk_scale_notify (GObject *object,
GParamSpec *pspec)
{
if (strcmp (pspec->name, "orientation") == 0)
{
GtkOrientation orientation;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (object));
gtk_range_set_flippable (GTK_RANGE (object),
orientation == GTK_ORIENTATION_HORIZONTAL);
}
else if (strcmp (pspec->name, "inverted") == 0)
{
GtkScale *scale = GTK_SCALE (object);
scale->priv->marks = g_slist_sort_with_data (scale->priv->marks,
compare_marks,
GINT_TO_POINTER (gtk_range_get_inverted (GTK_RANGE (scale))));
}
else if (G_OBJECT_CLASS (gtk_scale_parent_class)->notify)
G_OBJECT_CLASS (gtk_scale_parent_class)->notify (object, pspec);
}
#define add_slider_binding(binding_set, keyval, mask, scroll) \
gtk_binding_entry_add_signal (binding_set, keyval, mask, \
......@@ -186,6 +224,7 @@ gtk_scale_class_init (GtkScaleClass *class)
gobject_class->set_property = gtk_scale_set_property;
gobject_class->get_property = gtk_scale_get_property;
gobject_class->notify = gtk_scale_notify;
gobject_class->finalize = gtk_scale_finalize;
widget_class->style_updated = gtk_scale_style_updated;
......@@ -408,17 +447,6 @@ gtk_scale_class_init (GtkScaleClass *class)
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SCALE_ACCESSIBLE);
}
static void
gtk_scale_orientation_notify (GtkRange *range,
const GParamSpec *pspec)
{
GtkOrientation orientation;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range));
gtk_range_set_flippable (range,
orientation == GTK_ORIENTATION_HORIZONTAL);
}
static void
gtk_scale_init (GtkScale *scale)
{
......@@ -442,10 +470,8 @@ gtk_scale_init (GtkScale *scale)
priv->digits = 1;
gtk_range_set_round_digits (range, priv->digits);
gtk_scale_orientation_notify (range, NULL);
g_signal_connect (scale, "notify::orientation",
G_CALLBACK (gtk_scale_orientation_notify),
NULL);
gtk_range_set_flippable (range,
gtk_orientable_get_orientation (GTK_ORIENTABLE (range))== GTK_ORIENTATION_HORIZONTAL);
context = gtk_widget_get_style_context (GTK_WIDGET (scale));
gtk_style_context_add_class (context, GTK_STYLE_CLASS_SCALE);
......@@ -930,7 +956,7 @@ gtk_scale_get_mark_label_size (GtkScale *scale,
GtkScalePrivate *priv = scale->priv;
PangoLayout *layout;
PangoRectangle logical_rect;
GList *m;
GSList *m;
gint w, h;
*count1 = *count2 = 0;
......@@ -1054,12 +1080,12 @@ gtk_scale_get_preferred_height (GtkWidget *widget,
static gint
find_next_pos (GtkWidget *widget,
GList *list,
GSList *list,
gint *marks,
GtkPositionType pos)
{
GtkAllocation allocation;
GList *m;
GSList *m;
gint i;
for (m = list->next, i = 1; m; m = m->next, i++)
......@@ -1111,12 +1137,27 @@ gtk_scale_draw (GtkWidget *widget,
gint x1, x2, x3, y1, y2, y3;
PangoLayout *layout;
PangoRectangle logical_rect;
GList *m;
GSList *m;
gint min_pos_before, min_pos_after;
gint min_pos, max_pos;
gint n_marks;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range));
_gtk_range_get_stop_positions (range, &marks);
n_marks = _gtk_range_get_stop_positions (range, &marks);
/* We always draw the marks in increasing direction, so flip
* the stop positions to match the marks (which we flip in
* gtk_scale_notify)
*/
if (gtk_range_get_inverted (range))
{
for (i = 0; i < n_marks / 2; i++)
{
x1 = marks[i];
marks[i] = marks[n_marks - 1 - i];
marks[n_marks - 1 - i] = x1;
}
}
layout = gtk_widget_create_pango_layout (widget, NULL);
gtk_range_get_range_rect (range, &range_rect);
......@@ -1484,8 +1525,10 @@ _gtk_scale_clear_layout (GtkScale *scale)
}
static void
gtk_scale_mark_free (GtkScaleMark *mark)
gtk_scale_mark_free (gpointer data)
{
GtkScaleMark *mark = data;
g_free (mark->markup);
g_free (mark);
}
......@@ -1508,8 +1551,7 @@ gtk_scale_clear_marks (GtkScale *scale)
priv = scale->priv;
g_list_foreach (priv->marks, (GFunc)gtk_scale_mark_free, NULL);
g_list_free (priv->marks);
g_slist_free_full (priv->marks, gtk_scale_mark_free);
priv->marks = NULL;
context = gtk_widget_get_style_context (GTK_WIDGET (scale));
......@@ -1521,16 +1563,6 @@ gtk_scale_clear_marks (GtkScale *scale)
gtk_widget_queue_resize (GTK_WIDGET (scale));
}
static gint
compare_marks (gpointer a, gpointer b)
{
GtkScaleMark *ma, *mb;
ma = a; mb = b;
return (ma->value > mb->value) ? 1 : ((ma->value < mb->value) ? -1 : 0);
}
/**
* gtk_scale_add_mark:
* @scale: a #GtkScale
......@@ -1563,7 +1595,7 @@ gtk_scale_add_mark (GtkScale *scale,
{
GtkScalePrivate *priv;
GtkScaleMark *mark;
GList *m;
GSList *m;
gdouble *values;
gint n, i;
GtkStyleContext *context;
......@@ -1582,14 +1614,14 @@ gtk_scale_add_mark (GtkScale *scale,
else
mark->position = GTK_POS_BOTTOM;
priv->marks = g_list_insert_sorted (priv->marks, mark,
(GCompareFunc) compare_marks);
priv->marks = g_slist_insert_sorted (priv->marks, mark,
(GCompareFunc) compare_marks);
#define MARKS_ABOVE 1
#define MARKS_BELOW 2
all_pos = 0;
n = g_list_length (priv->marks);
n = g_slist_length (priv->marks);
values = g_new (gdouble, n);
for (m = priv->marks, i = 0; m; m = m->next, i++)
{
......@@ -1636,7 +1668,7 @@ typedef struct
{
GtkScale *scale;
GtkBuilder *builder;
GList *marks;
GSList *marks;
} MarksSubparserData;
typedef struct
......@@ -1752,7 +1784,7 @@ marks_start_element (GMarkupParseContext *context,
mark->context = g_strdup (msg_context);
mark->translatable = translatable;
parser_data->marks = g_list_prepend (parser_data->marks, mark);
parser_data->marks = g_slist_prepend (parser_data->marks, mark);
}
else
{
......@@ -1834,7 +1866,7 @@ gtk_scale_buildable_custom_finished (GtkBuildable *buildable,
if (strcmp (tagname, "marks") == 0)
{
GList *m;
GSList *m;
gchar *markup;
marks_data = (MarksSubparserData *)user_data;
......@@ -1855,7 +1887,7 @@ gtk_scale_buildable_custom_finished (GtkBuildable *buildable,
mark_data_free (mdata);
}
g_list_free (marks_data->marks);
g_slist_free (marks_data->marks);
g_slice_free (MarksSubparserData, marks_data);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment