2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-volumebar-range
27 * @short_description: This widget is an "workhorse" for #HildonVolumebar
28 * widget. It is not designed to be used as a standalone widget.
30 * Purpose of this widget is to act as an "container" for GtkScale
31 * widget. #HildonVolumebarRange changes some event parameters so
32 * that #HildonVolumebar can meet its specifications.
34 * Currently #HildonVolumebarRange models range of [0..100].
38 #include "hildon-volumebar-range.h"
39 #include <gtk/gtkrange.h>
40 #include <gdk/gdkkeysyms.h>
42 #define VOLUMEBAR_RANGE_INITIAL_VALUE 50.0
44 #define VOLUMEBAR_RANGE_MINIMUM_VALUE 0.0
46 #define VOLUMEBAR_RANGE_MAXIMUM_VALUE 100.0
48 #define VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE 5.0
50 #define VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE 5.0
52 #define VOLUMEBAR_RANGE_PAGE_SIZE_VALUE 0.0
54 #define CHANGE_THRESHOLD 0.001
56 static GtkScaleClass* parent_class;
59 hildon_volumebar_range_class_init (HildonVolumebarRangeClass*
63 hildon_volumebar_range_init (HildonVolumebarRange*
67 hildon_volumebar_range_set_property (GObject *object,
73 hildon_volumebar_range_get_property (GObject *object,
79 hildon_volumebar_range_button_press_event (GtkWidget *widget,
80 GdkEventButton *event);
83 hildon_volumebar_range_button_release_event (GtkWidget *widget,
84 GdkEventButton *event);
87 hildon_volumebar_range_keypress (GtkWidget *widget,
97 * hildon_volumebar_range_get_type:
99 * Initializes and returns the type of a hildon volumebar range.
101 * @Returns: GType of #HildonVolumebarRange
104 hildon_volumebar_range_get_type (void)
106 static GType volumerange_type = 0;
108 if (!volumerange_type) {
109 static const GTypeInfo volumerange_info = {
110 sizeof (HildonVolumebarRangeClass),
111 NULL, /* base_init */
112 NULL, /* base_finalize */
113 (GClassInitFunc) hildon_volumebar_range_class_init,
114 NULL, /* class_finalize */
115 NULL, /* class_data */
116 sizeof (HildonVolumebarRange),
118 (GInstanceInitFunc) hildon_volumebar_range_init,
120 volumerange_type = g_type_register_static (GTK_TYPE_SCALE,
121 "HildonVolumebarRange",
122 &volumerange_info, 0);
125 return volumerange_type;
129 hildon_volumebar_range_class_init (HildonVolumebarRangeClass *volumerange_class)
131 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (volumerange_class);
132 GObjectClass *object_class = G_OBJECT_CLASS (volumerange_class);
134 parent_class = g_type_class_peek_parent (volumerange_class);
136 widget_class->button_press_event =
137 hildon_volumebar_range_button_press_event;
138 widget_class->button_release_event =
139 hildon_volumebar_range_button_release_event;
140 widget_class->key_press_event = hildon_volumebar_range_keypress;
142 object_class->set_property = hildon_volumebar_range_set_property;
143 object_class->get_property = hildon_volumebar_range_get_property;
146 * HildonVolumebarRange:level:
148 * Current volume level.
150 g_object_class_install_property (object_class,
152 g_param_spec_double ("level",
154 "Current volume level",
155 VOLUMEBAR_RANGE_MINIMUM_VALUE,
156 VOLUMEBAR_RANGE_MAXIMUM_VALUE,
157 VOLUMEBAR_RANGE_INITIAL_VALUE,
163 hildon_volumebar_range_init (HildonVolumebarRange *volumerange)
165 /* stepper_a = "less", stepper_d = "more" */
166 GTK_RANGE (volumerange)->has_stepper_a = TRUE;
167 GTK_RANGE (volumerange)->has_stepper_d = TRUE;
171 hildon_volumebar_range_set_property (GObject *object,
176 HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE (object);
180 hildon_volumebar_range_set_level (range, g_value_get_double (value));
184 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191 hildon_volumebar_range_get_property (GObject *object,
196 HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE (object);
201 g_value_set_double (value, hildon_volumebar_range_get_level(range));
205 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
211 hildon_volumebar_range_keypress (GtkWidget *widget,
214 /* Accept arrow keys only if they match the orientation of the widget */
215 if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL)
217 if (event->keyval == GDK_Up || event->keyval == GDK_Down) {
223 if (event->keyval == GDK_Left || event->keyval == GDK_Right) {
228 return ((GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget,
233 hildon_volumebar_range_new (GtkOrientation orientation)
235 GtkAdjustment * adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (VOLUMEBAR_RANGE_INITIAL_VALUE,
236 VOLUMEBAR_RANGE_MINIMUM_VALUE,
237 VOLUMEBAR_RANGE_MAXIMUM_VALUE,
238 VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE,
239 VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE,
240 VOLUMEBAR_RANGE_PAGE_SIZE_VALUE));
242 HildonVolumebarRange *self =
243 g_object_new(HILDON_TYPE_VOLUMEBAR_RANGE,
244 "adjustment", adjustment,
247 GTK_RANGE (self)->orientation = orientation;
249 /* Default vertical range is upside down for purposes of this widget */
250 gtk_range_set_inverted (GTK_RANGE (self),
251 (orientation == GTK_ORIENTATION_VERTICAL));
253 return GTK_WIDGET(self);
257 hildon_volumebar_range_get_level (HildonVolumebarRange *self)
259 g_return_val_if_fail (HILDON_IS_VOLUMEBAR_RANGE(self), -1.0);
261 return gtk_adjustment_get_value (gtk_range_get_adjustment(GTK_RANGE (self)));
265 hildon_volumebar_range_set_level (HildonVolumebarRange * self,
268 GtkAdjustment *adjustment;
270 g_return_if_fail (HILDON_IS_VOLUMEBAR_RANGE (self));
272 adjustment = gtk_range_get_adjustment (GTK_RANGE (self));
274 /* Check that value has actually changed. Note that it's not safe to
275 * just compare if floats are equivalent or not */
276 if (ABS (gtk_adjustment_get_value (adjustment) - level) > CHANGE_THRESHOLD) {
277 gtk_adjustment_set_value(adjustment, level);
282 hildon_volumebar_range_button_press_event (GtkWidget *widget,
283 GdkEventButton *event)
285 gboolean result = FALSE;
287 /* FIXME: By default, clicking left mouse button on GtkRange moves the
288 slider by one step towards the click location. However, we want stylus
289 taps to move the slider to the position of the tap, which by default
290 is the middle button behaviour. To avoid breaking default GtkRange
291 behaviour, this has been implemented by faking a middle button press. */
293 event->button = (event->button == 1) ? 2 : event->button;
294 if (GTK_WIDGET_CLASS (parent_class)->button_press_event) {
295 result = GTK_WIDGET_CLASS (parent_class)->button_press_event(widget, event);
302 hildon_volumebar_range_button_release_event (GtkWidget *widget,
303 GdkEventButton *event)
305 gboolean result = FALSE;
307 /* FIXME: By default, clicking left mouse button on GtkRange moves the
308 slider by one step towards the click location. However, we want stylus
309 taps to move the slider to the position of the tap, which by default
310 is the middle button behaviour. To avoid breaking default GtkRange
311 behaviour, this has been implemented by faking a middle button press. */
313 event->button = event->button == 1 ? 2 : event->button;
314 if (GTK_WIDGET_CLASS (parent_class)->button_release_event) {
315 result = GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, event);