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
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 * @file hildon-volumebar-range.c
28 * This file contains the implementation of the HildonVolumebarRange.
29 * This widget is an "workhorse" for #HildonVolumebar widget.
30 * It is not designed to be used as a standalone widget.
32 * Purpose of this widget is to act as an "container" for GtkScale
33 * widget. #HildonVolumebarRange changes some event parameters so
34 * that #HildonVolumebar can meet its specifications.
36 * Currently #HildonVolumebarRange models range of [0..100].
40 #include "hildon-volumebar-range.h"
41 #include <gtk/gtkrange.h>
42 #include <gdk/gdkkeysyms.h>
44 #define VOLUMEBAR_RANGE_INITIAL_VALUE 50.0
46 #define VOLUMEBAR_RANGE_MINIMUM_VALUE 0.0
48 #define VOLUMEBAR_RANGE_MAXIMUM_VALUE 100.0
50 #define VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE 5.0
52 #define VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE 5.0
54 #define VOLUMEBAR_RANGE_PAGE_SIZE_VALUE 0.0
56 #define CHANGE_THRESHOLD 0.001
58 static GtkScaleClass* parent_class;
61 hildon_volumebar_range_class_init (HildonVolumebarRangeClass*
65 hildon_volumebar_range_init (HildonVolumebarRange*
69 hildon_volumebar_range_set_property (GObject *object,
75 hildon_volumebar_range_get_property (GObject *object,
81 hildon_volumebar_range_button_press_event (GtkWidget *widget,
82 GdkEventButton *event);
85 hildon_volumebar_range_button_release_event (GtkWidget *widget,
86 GdkEventButton *event);
89 hildon_volumebar_range_keypress (GtkWidget *widget,
99 hildon_volumebar_range_get_type (void)
101 static GType volumerange_type = 0;
103 if (!volumerange_type) {
104 static const GTypeInfo volumerange_info = {
105 sizeof (HildonVolumebarRangeClass),
106 NULL, /* base_init */
107 NULL, /* base_finalize */
108 (GClassInitFunc) hildon_volumebar_range_class_init,
109 NULL, /* class_finalize */
110 NULL, /* class_data */
111 sizeof (HildonVolumebarRange),
113 (GInstanceInitFunc) hildon_volumebar_range_init,
115 volumerange_type = g_type_register_static (GTK_TYPE_SCALE,
116 "HildonVolumebarRange",
117 &volumerange_info, 0);
120 return volumerange_type;
124 hildon_volumebar_range_class_init (HildonVolumebarRangeClass *volumerange_class)
126 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (volumerange_class);
127 GObjectClass *object_class = G_OBJECT_CLASS (volumerange_class);
129 parent_class = g_type_class_peek_parent (volumerange_class);
131 widget_class->button_press_event =
132 hildon_volumebar_range_button_press_event;
133 widget_class->button_release_event =
134 hildon_volumebar_range_button_release_event;
135 widget_class->key_press_event = hildon_volumebar_range_keypress;
137 object_class->set_property = hildon_volumebar_range_set_property;
138 object_class->get_property = hildon_volumebar_range_get_property;
140 g_object_class_install_property (object_class,
142 g_param_spec_double ("level",
144 "Current volume level",
145 VOLUMEBAR_RANGE_MINIMUM_VALUE,
146 VOLUMEBAR_RANGE_MAXIMUM_VALUE,
147 VOLUMEBAR_RANGE_INITIAL_VALUE,
153 hildon_volumebar_range_init (HildonVolumebarRange *volumerange)
155 /* stepper_a = "less", stepper_d = "more" */
156 GTK_RANGE (volumerange)->has_stepper_a = TRUE;
157 GTK_RANGE (volumerange)->has_stepper_d = TRUE;
161 hildon_volumebar_range_set_property (GObject *object,
166 HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE (object);
170 hildon_volumebar_range_set_level (range, g_value_get_double (value));
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
181 hildon_volumebar_range_get_property (GObject *object,
186 HildonVolumebarRange *range = HILDON_VOLUMEBAR_RANGE (object);
191 g_value_set_double (value, hildon_volumebar_range_get_level(range));
195 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
201 hildon_volumebar_range_keypress (GtkWidget *widget,
204 /* Accept arrow keys only if they match the orientation of the widget */
205 if (GTK_RANGE (widget)->orientation == GTK_ORIENTATION_HORIZONTAL)
207 if (event->keyval == GDK_Up || event->keyval == GDK_Down) {
213 if (event->keyval == GDK_Left || event->keyval == GDK_Right) {
218 return ((GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget,
223 hildon_volumebar_range_new (GtkOrientation orientation)
225 GtkAdjustment * adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (VOLUMEBAR_RANGE_INITIAL_VALUE,
226 VOLUMEBAR_RANGE_MINIMUM_VALUE,
227 VOLUMEBAR_RANGE_MAXIMUM_VALUE,
228 VOLUMEBAR_RANGE_STEP_INCREMENT_VALUE,
229 VOLUMEBAR_RANGE_PAGE_INCREMENT_VALUE,
230 VOLUMEBAR_RANGE_PAGE_SIZE_VALUE));
232 HildonVolumebarRange *self =
233 g_object_new(HILDON_TYPE_VOLUMEBAR_RANGE,
234 "adjustment", adjustment,
237 GTK_RANGE (self)->orientation = orientation;
239 /* Default vertical range is upside down for purposes of this widget */
240 gtk_range_set_inverted (GTK_RANGE (self),
241 (orientation == GTK_ORIENTATION_VERTICAL));
243 return GTK_WIDGET(self);
247 hildon_volumebar_range_get_level (HildonVolumebarRange *self)
249 g_return_val_if_fail (HILDON_IS_VOLUMEBAR_RANGE(self), -1.0);
251 return gtk_adjustment_get_value (gtk_range_get_adjustment(GTK_RANGE (self)));
255 hildon_volumebar_range_set_level (HildonVolumebarRange * self,
258 GtkAdjustment *adjustment;
260 g_return_if_fail (HILDON_IS_VOLUMEBAR_RANGE (self));
262 adjustment = gtk_range_get_adjustment (GTK_RANGE (self));
264 /* Check that value has actually changed. Note that it's not safe to
265 * just compare if floats are equivalent or not */
266 if (ABS (gtk_adjustment_get_value (adjustment) - level) > CHANGE_THRESHOLD) {
267 gtk_adjustment_set_value(adjustment, level);
272 hildon_volumebar_range_button_press_event (GtkWidget *widget,
273 GdkEventButton *event)
275 gboolean result = FALSE;
277 /* FIXME: By default, clicking left mouse button on GtkRange moves the
278 slider by one step towards the click location. However, we want stylus
279 taps to move the slider to the position of the tap, which by default
280 is the middle button behaviour. To avoid breaking default GtkRange
281 behaviour, this has been implemented by faking a middle button press. */
283 event->button = (event->button == 1) ? 2 : event->button;
284 if (GTK_WIDGET_CLASS (parent_class)->button_press_event) {
285 result = GTK_WIDGET_CLASS (parent_class)->button_press_event(widget, event);
292 hildon_volumebar_range_button_release_event (GtkWidget *widget,
293 GdkEventButton *event)
295 gboolean result = FALSE;
297 /* FIXME: By default, clicking left mouse button on GtkRange moves the
298 slider by one step towards the click location. However, we want stylus
299 taps to move the slider to the position of the tap, which by default
300 is the middle button behaviour. To avoid breaking default GtkRange
301 behaviour, this has been implemented by faking a middle button press. */
303 event->button = event->button == 1 ? 2 : event->button;
304 if (GTK_WIDGET_CLASS (parent_class)->button_release_event) {
305 result = GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, event);