#include <math.h>
#include <stdlib.h>
-#include "gdk/gdkkeysyms.h"
#include "gtkscale.h"
#include "gtkiconfactory.h"
#include "gtkicontheme.h"
#include "gtkmarshalers.h"
#include "gtkbindings.h"
#include "gtkorientable.h"
+#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtkbuildable.h"
/**
* SECTION:gtkscale
- * @Short_description: Base class for #GtkHScale and #GtkVScale
+ * @Short_description: Base class for GtkHScale and GtkVScale
* @Title: GtkScale
*
- * A #GtkScale is a slider control used to select a numeric value.
+ * A GtkScale is a slider control used to select a numeric value.
* To use it, you'll probably want to investigate the methods on
- * its base class, #GtkRange, in addition to the methods for #GtkScale itself.
+ * its base class, #GtkRange, in addition to the methods for GtkScale itself.
* To set the value of a scale, you would normally use gtk_range_set_value().
* To detect changes to the value, you would normally use the
- * #GtkRange::value_changed signal.
+ * #GtkRange::value-changed signal.
+ *
+ * Note that using the same upper and lower bounds for the #GtkScale (through
+ * the #GtkRange methods) will hide the slider itself. This is useful for
+ * applications that want to show an undeterminate value on the scale, without
+ * changing the layout of the application (such as movie or music players).
*
* <refsect2 id="GtkScale-BUILDER-UI"><title>GtkScale as GtkBuildable</title>
* GtkScale supports a custom <marks> element, which
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static void gtk_scale_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_scale_style_set (GtkWidget *widget,
- GtkStyle *previous);
+static void gtk_scale_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
+static void gtk_scale_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
+static void gtk_scale_style_updated (GtkWidget *widget);
static void gtk_scale_get_range_border (GtkRange *range,
GtkBorder *border);
static void gtk_scale_get_mark_label_size (GtkScale *scale,
static void gtk_scale_finalize (GObject *object);
static void gtk_scale_screen_changed (GtkWidget *widget,
GdkScreen *old_screen);
-static gboolean gtk_scale_expose (GtkWidget *widget,
- GdkEventExpose *event);
+static gboolean gtk_scale_draw (GtkWidget *widget,
+ cairo_t *cr);
static void gtk_scale_real_get_layout_offsets (GtkScale *scale,
gint *x,
gint *y);
gobject_class->get_property = gtk_scale_get_property;
gobject_class->finalize = gtk_scale_finalize;
- widget_class->style_set = gtk_scale_style_set;
+ widget_class->style_updated = gtk_scale_style_updated;
widget_class->screen_changed = gtk_scale_screen_changed;
- widget_class->expose_event = gtk_scale_expose;
- widget_class->size_request = gtk_scale_size_request;
+ widget_class->draw = gtk_scale_draw;
+ widget_class->get_preferred_width = gtk_scale_get_preferred_width;
+ widget_class->get_preferred_height = gtk_scale_get_preferred_height;
range_class->slider_detail = "Xscale";
range_class->get_range_border = gtk_scale_get_range_border;
{
GtkScalePrivate *priv;
GtkRange *range = GTK_RANGE (scale);
+ GtkStyleContext *context;
scale->priv = G_TYPE_INSTANCE_GET_PRIVATE (scale,
GTK_TYPE_SCALE,
priv->draw_value = TRUE;
priv->value_pos = GTK_POS_TOP;
priv->digits = 1;
- _gtk_range_set_round_digits (range, priv->digits);
+ 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);
+
+ context = gtk_widget_get_style_context (GTK_WIDGET (scale));
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_SCALE);
}
static void
/**
* gtk_scale_new:
* @orientation: the scale's orientation.
- * @adjustment: the #GtkAdjustment which sets the range of the scale, or
- * %NULL to create a new adjustment.
+ * @adjustment: (allow-none): the #GtkAdjustment which sets the range
+ * of the scale, or %NULL to create a new adjustment.
*
* Creates a new #GtkScale.
*
gdouble max,
gdouble step)
{
- GtkObject *adj;
+ GtkAdjustment *adj;
gint digits;
g_return_val_if_fail (min < max, NULL);
{
priv->digits = digits;
if (priv->draw_value)
- _gtk_range_set_round_digits (range, digits);
+ gtk_range_set_round_digits (range, digits);
_gtk_scale_clear_layout (scale);
gtk_widget_queue_resize (GTK_WIDGET (scale));
{
priv->draw_value = draw_value;
if (draw_value)
- _gtk_range_set_round_digits (GTK_RANGE (scale), priv->digits);
+ gtk_range_set_round_digits (GTK_RANGE (scale), priv->digits);
else
- _gtk_range_set_round_digits (GTK_RANGE (scale), -1);
+ gtk_range_set_round_digits (GTK_RANGE (scale), -1);
_gtk_scale_clear_layout (scale);
}
static void
-gtk_scale_style_set (GtkWidget *widget,
- GtkStyle *previous)
+gtk_scale_style_updated (GtkWidget *widget)
{
gint slider_length;
GtkRange *range;
_gtk_scale_clear_layout (GTK_SCALE (widget));
- GTK_WIDGET_CLASS (gtk_scale_parent_class)->style_set (widget, previous);
+ GTK_WIDGET_CLASS (gtk_scale_parent_class)->style_updated (widget);
}
static void
}
static void
-gtk_scale_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
+gtk_scale_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
{
- GtkRange *range = GTK_RANGE (widget);
- gint n1, w1, h1, n2, w2, h2;
- gint slider_length;
-
- GTK_WIDGET_CLASS (gtk_scale_parent_class)->size_request (widget, requisition);
+ GTK_WIDGET_CLASS (gtk_scale_parent_class)->get_preferred_width (widget, minimum, natural);
- gtk_widget_style_get (widget, "slider-length", &slider_length, NULL);
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)) == GTK_ORIENTATION_HORIZONTAL)
+ {
+ gint n1, w1, h1, n2, w2, h2;
+ gint slider_length;
+ gint w;
+ gtk_widget_style_get (widget, "slider-length", &slider_length, NULL);
- if (gtk_orientable_get_orientation (GTK_ORIENTABLE (range)) == GTK_ORIENTATION_HORIZONTAL)
- {
gtk_scale_get_mark_label_size (GTK_SCALE (widget), GTK_POS_TOP, &n1, &w1, &h1, &n2, &w2, &h2);
w1 = (n1 - 1) * w1 + MAX (w1, slider_length);
w2 = (n2 - 1) * w2 + MAX (w2, slider_length);
- requisition->width = MAX (requisition->width, MAX (w1, w2));
+ w = MAX (w1, w2);
+
+ *minimum = MAX (*minimum, w);
+ *natural = MAX (*natural, w);
}
- else
+}
+
+static void
+gtk_scale_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GTK_WIDGET_CLASS (gtk_scale_parent_class)->get_preferred_height (widget, minimum, natural);
+
+
+ if (gtk_orientable_get_orientation (GTK_ORIENTABLE (widget)) == GTK_ORIENTATION_VERTICAL)
{
+ gint n1, w1, h1, n2, w2, h2;
+ gint slider_length;
+ gint h;
+
+ gtk_widget_style_get (widget, "slider-length", &slider_length, NULL);
+
gtk_scale_get_mark_label_size (GTK_SCALE (widget), GTK_POS_LEFT, &n1, &w1, &h1, &n2, &w2, &h2);
h1 = (n1 - 1) * h1 + MAX (h1, slider_length);
h2 = (n2 - 1) * h1 + MAX (h2, slider_length);
- requisition->height = MAX (requisition->height, MAX (h1, h2));
+ h = MAX (h1, h2);
+
+ *minimum = MAX (*minimum, h);
+ *natural = MAX (*natural, h);
}
}
}
static gboolean
-gtk_scale_expose (GtkWidget *widget,
- GdkEventExpose *event)
+gtk_scale_draw (GtkWidget *widget,
+ cairo_t *cr)
{
GtkScale *scale = GTK_SCALE (widget);
GtkScalePrivate *priv = scale->priv;
GtkRange *range = GTK_RANGE (scale);
- GtkStateType state_type;
- GtkStyle *style;
- GdkWindow *window;
+ GtkStateFlags state = 0;
+ GtkStyleContext *context;
gint n_marks;
gint *marks;
gint focus_padding;
gint value_spacing;
gint min_sep = 4;
- style = gtk_widget_get_style (widget);
+ context = gtk_widget_get_style_context (widget);
gtk_widget_style_get (widget,
"focus-padding", &focus_padding,
"slider-width", &slider_width,
/* We need to chain up _first_ so the various geometry members of
* GtkRange struct are updated.
*/
- GTK_WIDGET_CLASS (gtk_scale_parent_class)->expose_event (widget, event);
+ GTK_WIDGET_CLASS (gtk_scale_parent_class)->draw (widget, cr);
- window = gtk_widget_get_window (widget);
-
- state_type = GTK_STATE_NORMAL;
if (!gtk_widget_is_sensitive (widget))
- state_type = GTK_STATE_INSENSITIVE;
+ state |= GTK_STATE_FLAG_INSENSITIVE;
if (priv->marks)
{
- GtkAllocation allocation;
GtkOrientation orientation;
GdkRectangle range_rect;
gint i;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range));
n_marks = _gtk_range_get_stop_positions (range, &marks);
layout = gtk_widget_create_pango_layout (widget, NULL);
- gtk_widget_get_allocation (widget, &allocation);
gtk_range_get_range_rect (range, &range_rect);
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- min_pos_before = min_pos_after = allocation.x;
- else
- min_pos_before = min_pos_after = allocation.y;
+ min_pos_before = min_pos_after = 0;
+
for (m = priv->marks, i = 0; m; m = m->next, i++)
{
GtkScaleMark *mark = m->data;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- x1 = allocation.x + marks[i];
+ x1 = marks[i];
if (mark->position == GTK_POS_TOP)
{
- y1 = allocation.y + range_rect.y;
+ y1 = range_rect.y;
y2 = y1 - slider_width / 2;
min_pos = min_pos_before;
- max_pos = allocation.x + find_next_pos (widget, m, marks + i, GTK_POS_TOP, 1) - min_sep;
+ max_pos = find_next_pos (widget, m, marks + i, GTK_POS_TOP, 1) - min_sep;
}
else
{
- y1 = allocation.y + range_rect.y + range_rect.height;
+ y1 = range_rect.y + range_rect.height;
y2 = y1 + slider_width / 2;
min_pos = min_pos_after;
- max_pos = allocation.x + find_next_pos (widget, m, marks + i, GTK_POS_TOP, 0) - min_sep;
+ max_pos = find_next_pos (widget, m, marks + i, GTK_POS_TOP, 0) - min_sep;
}
- gtk_paint_vline (style, window, state_type,
- NULL, widget, "scale-mark", y1, y2, x1);
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_MARK);
+ gtk_style_context_set_state (context, state);
+
+ gtk_render_line (context, cr,
+ x1, y1, x1, y2);
if (mark->markup)
{
x3 = min_pos;
if (x3 + logical_rect.width > max_pos)
x3 = max_pos - logical_rect.width;
- if (x3 < allocation.x)
- x3 = allocation.x;
+ if (x3 < 0)
+ x3 = 0;
if (mark->position == GTK_POS_TOP)
{
y3 = y2 - value_spacing - logical_rect.height;
min_pos_after = x3 + logical_rect.width + min_sep;
}
- gtk_paint_layout (style, window, state_type,
- FALSE, NULL, widget, "scale-mark",
- x3, y3, layout);
+ gtk_render_layout (context, cr,
+ x3, y3, layout);
}
+
+ gtk_style_context_restore (context);
}
else
{
if (mark->position == GTK_POS_LEFT)
{
- x1 = allocation.x + range_rect.x;
- x2 = allocation.x + range_rect.x - slider_width / 2;
+ x1 = range_rect.x;
+ x2 = range_rect.x - slider_width / 2;
min_pos = min_pos_before;
- max_pos = allocation.y + find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 1) - min_sep;
+ max_pos = find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 1) - min_sep;
}
else
{
- x1 = allocation.x + range_rect.x + range_rect.width;
- x2 = allocation.x + range_rect.x + range_rect.width + slider_width / 2;
+ x1 = range_rect.x + range_rect.width;
+ x2 = range_rect.x + range_rect.width + slider_width / 2;
min_pos = min_pos_after;
- max_pos = allocation.y + find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 0) - min_sep;
+ max_pos = find_next_pos (widget, m, marks + i, GTK_POS_LEFT, 0) - min_sep;
}
- y1 = allocation.y + marks[i];
+ y1 = marks[i];
+
+ gtk_style_context_save (context);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_MARK);
+ gtk_style_context_set_state (context, state);
- gtk_paint_hline (style, window, state_type,
- NULL, widget, "range-mark", x1, x2, y1);
+ gtk_render_line (context, cr,
+ x1, y1, x2, y1);
if (mark->markup)
{
y3 = min_pos;
if (y3 + logical_rect.height > max_pos)
y3 = max_pos - logical_rect.height;
- if (y3 < allocation.y)
- y3 = allocation.y;
+ if (y3 < 0)
+ y3 = 0;
if (mark->position == GTK_POS_LEFT)
{
x3 = x2 - value_spacing - logical_rect.width;
min_pos_after = y3 + logical_rect.height + min_sep;
}
- gtk_paint_layout (style, window, state_type,
- FALSE, NULL, widget, "scale-mark",
- x3, y3, layout);
+ gtk_render_layout (context, cr,
+ x3, y3, layout);
}
+
+ gtk_style_context_restore (context);
}
}
if (priv->draw_value)
{
GtkOrientation orientation;
+ GtkAllocation allocation;
+
PangoLayout *layout;
gint x, y;
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (range));
layout = gtk_scale_get_layout (scale);
gtk_scale_get_layout_offsets (scale, &x, &y);
+ gtk_widget_get_allocation (widget, &allocation);
- gtk_paint_layout (style,
- window,
- state_type,
- FALSE,
- NULL,
- widget,
- orientation == GTK_ORIENTATION_HORIZONTAL ?
- "hscale" : "vscale",
- x, y,
- layout);
-
+ gtk_render_layout (context, cr,
+ x - allocation.x,
+ y - allocation.y,
+ layout);
}
return FALSE;
* gtk_scale_get_layout:
* @scale: A #GtkScale
*
- * Gets the #PangoLayout used to display the scale.
- * The returned object is owned by the scale so does
- * not need to be freed by the caller.
+ * Gets the #PangoLayout used to display the scale. The returned
+ * object is owned by the scale so does not need to be freed by
+ * the caller.
+ *
+ * Return value: (transfer none): the #PangoLayout for this scale,
+ * or %NULL if the #GtkScale:draw-value property is %FALSE.
*
- * Return value: the #PangoLayout for this scale, or %NULL
- * if the #GtkScale:draw-value property is %FALSE.
- *
* Since: 2.4
*/
PangoLayout *
/**
* gtk_scale_get_layout_offsets:
* @scale: a #GtkScale
- * @x: (allow-none): location to store X offset of layout, or %NULL
- * @y: (allow-none): location to store Y offset of layout, or %NULL
+ * @x: (out) (allow-none): location to store X offset of layout, or %NULL
+ * @y: (out) (allow-none): location to store Y offset of layout, or %NULL
*
* Obtains the coordinates where the scale will draw the
* #PangoLayout representing the text in the scale. Remember