1
/* -*- mode: C; c-file-style: "gnu" -*- */
3
* Copyright (C) 2003 Richard Hult <richard@imendio.com>
4
* Copyright (C) 2004 Jorn Baayen <jorn@nl.linux.org>
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation; either version 2 of the
9
* License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* General Public License for more details.
16
* You should have received a copy of the GNU General Public
17
* License along with this program; if not, write to the
18
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
* Boston, MA 02111-1307, USA.
24
#include <gdk/gdkkeysyms.h>
25
#include <gtk/gtkwindow.h>
26
#include <gtk/gtkframe.h>
27
#include <gtk/gtkvbox.h>
28
#include <gtk/gtkvscale.h>
29
#include <gtk/gtklabel.h>
30
#include <gtk/gtkmain.h>
31
#include <gtk/gtkimage.h>
32
#include <gtk/gtkiconfactory.h>
33
#include "volume-button.h"
35
static void volume_button_class_init (VolumeButtonClass *klass);
36
static void volume_button_init (VolumeButton *button);
37
static void volume_button_finalize (GObject *object);
38
static gboolean scale_key_press_event_cb (GtkWidget *widget,
40
VolumeButton *button);
41
static void scale_value_changed_cb (GtkWidget *widget,
42
VolumeButton *button);
43
static gboolean popup_button_press_event_cb (GtkWidget *widget,
44
GdkEventButton *event,
45
VolumeButton *button);
46
static void show_scale (VolumeButton *button);
47
static void hide_scale (VolumeButton *button);
48
static void toggled_cb (GtkWidget *widget,
49
gpointer user_button);
50
static gboolean scroll_event_cb (GtkWidget *widget,
51
GdkEventScroll *event,
52
VolumeButton *button);
53
static void update_image (VolumeButton *button,
61
static GObjectClass *parent_class;
62
static guint signals[LAST_SIGNAL];
65
volume_button_get_type (void)
67
static GType type = 0;
71
static const GTypeInfo info =
73
sizeof (VolumeButtonClass),
75
NULL, /* base_finalize */
76
(GClassInitFunc) volume_button_class_init,
77
NULL, /* class_finalize */
78
NULL, /* class_data */
79
sizeof (VolumeButton),
81
(GInstanceInitFunc) volume_button_init,
84
type = g_type_register_static (GTK_TYPE_TOGGLE_BUTTON, "VolumeButton",
92
volume_button_class_init (VolumeButtonClass *klass)
94
GObjectClass *object_class;
96
parent_class = g_type_class_peek_parent (klass);
97
object_class = (GObjectClass*) klass;
99
object_class->finalize = volume_button_finalize;
101
signals[VOLUME_CHANGED] =
102
g_signal_new ("volume_changed",
103
G_TYPE_FROM_CLASS (klass),
107
g_cclosure_marshal_VOID__INT,
108
G_TYPE_NONE, 1, G_TYPE_INT);
112
volume_button_init (VolumeButton *button)
114
g_signal_connect (button,
116
G_CALLBACK (toggled_cb),
119
g_signal_connect (button,
121
G_CALLBACK (scroll_event_cb),
124
button->image = gtk_image_new_from_stock ("muine-volume-medium",
125
GTK_ICON_SIZE_LARGE_TOOLBAR);
126
gtk_widget_show (button->image);
128
gtk_container_add (GTK_CONTAINER (button), button->image);
130
update_image (button, 0);
134
volume_button_finalize (GObject *object)
136
/* VolumeButton *button = VOLUME_BUTTON (object);*/
138
if (G_OBJECT_CLASS (parent_class)->finalize)
139
G_OBJECT_CLASS (parent_class)->finalize (object);
143
volume_button_new (void)
145
return g_object_new (TYPE_VOLUME_BUTTON, NULL);
149
scale_key_press_event_cb (GtkWidget *widget,
151
VolumeButton *button)
153
switch (event->keyval)
158
g_signal_emit (button, signals[VOLUME_CHANGED], 0,
159
button->revert_volume);
180
scale_value_changed_cb (GtkWidget *widget,
181
VolumeButton *button)
185
vol = gtk_range_get_value (GTK_RANGE (widget));
186
vol = CLAMP (vol, 0, 100);
188
button->volume = vol;
189
update_image (button, vol);
191
g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);
195
popup_button_press_event_cb (GtkWidget *widget,
196
GdkEventButton *event,
197
VolumeButton *button)
209
show_scale (VolumeButton *button)
218
GdkGrabStatus grabbed;
220
button->popup = gtk_window_new (GTK_WINDOW_POPUP);
221
gtk_window_set_screen (GTK_WINDOW (button->popup),
222
gtk_widget_get_screen (GTK_WIDGET (button)));
224
button->revert_volume = button->volume;
226
frame = gtk_frame_new (NULL);
227
gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
228
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
229
gtk_widget_show (frame);
231
gtk_container_add (GTK_CONTAINER (button->popup), frame);
233
box = gtk_vbox_new (FALSE, 0);
234
gtk_widget_show (box);
236
gtk_container_add (GTK_CONTAINER (frame), box);
238
adj = GTK_ADJUSTMENT (gtk_adjustment_new (button->volume, 0, 100, 5, 10, 0));
240
button->scale = gtk_vscale_new (adj);
241
gtk_scale_set_draw_value (GTK_SCALE (button->scale), FALSE);
242
gtk_range_set_update_policy (GTK_RANGE (button->scale), GTK_UPDATE_CONTINUOUS);
243
gtk_range_set_inverted (GTK_RANGE (button->scale), TRUE);
244
gtk_widget_show (button->scale);
246
g_signal_connect (button->popup,
247
"button_press_event",
248
G_CALLBACK (popup_button_press_event_cb),
251
g_signal_connect (button->scale,
253
G_CALLBACK (scale_key_press_event_cb),
256
g_signal_connect (button->scale,
258
G_CALLBACK (scale_value_changed_cb),
261
label = gtk_label_new ("+");
262
gtk_widget_show (label);
263
gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
265
label = gtk_label_new ("-");
266
gtk_widget_show (label);
267
gtk_box_pack_end (GTK_BOX (box), label, FALSE, TRUE, 0);
269
gtk_box_pack_start (GTK_BOX (box), button->scale, TRUE, TRUE, 0);
271
/* Align the popup below the button. */
272
gtk_widget_size_request (button->popup, &req);
274
gdk_window_get_origin (GTK_BUTTON (button)->event_window, &x, &y);
275
gdk_drawable_get_size (GTK_BUTTON (button)->event_window, &width, &height);
277
req.width = MAX (req.width, width);
279
x += (width - req.width) / 2;
285
gtk_widget_set_size_request (button->scale, -1, 100);
286
gtk_widget_set_size_request (button->popup, req.width, -1);
288
gtk_window_move (GTK_WINDOW (button->popup), x, y);
289
gtk_widget_show (button->popup);
291
gtk_widget_grab_focus (button->popup);
292
gtk_grab_add (button->popup);
294
grabbed = gdk_pointer_grab (button->popup->window,
296
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
300
if (grabbed == GDK_GRAB_SUCCESS)
302
grabbed = gdk_keyboard_grab (button->popup->window, TRUE, GDK_CURRENT_TIME);
304
if (grabbed != GDK_GRAB_SUCCESS)
306
gtk_grab_remove (button->popup);
307
gtk_widget_destroy (button->popup);
308
button->popup = NULL;
313
gtk_grab_remove (button->popup);
314
gtk_widget_destroy (button->popup);
315
button->popup = NULL;
320
hide_scale (VolumeButton *button)
322
GtkToggleButton *toggle;
326
gtk_grab_remove (button->scale);
327
gdk_pointer_ungrab (GDK_CURRENT_TIME);
328
gdk_keyboard_ungrab (GDK_CURRENT_TIME);
330
gtk_widget_destroy (GTK_WIDGET (button->popup));
332
button->popup = NULL;
335
toggle = GTK_TOGGLE_BUTTON (button);
336
if (gtk_toggle_button_get_active (toggle))
337
gtk_toggle_button_set_active (toggle, FALSE);
341
toggled_cb (GtkWidget *widget, gpointer user_button)
343
GtkToggleButton *toggle;
345
toggle = GTK_TOGGLE_BUTTON (widget);
346
if (gtk_toggle_button_get_active (toggle))
347
show_scale (VOLUME_BUTTON (widget));
349
hide_scale (VOLUME_BUTTON (widget));
353
scroll_event_cb (GtkWidget *widget,
354
GdkEventScroll *event,
355
VolumeButton *button)
359
vol = button->volume;
361
switch (event->direction)
367
case GDK_SCROLL_DOWN:
375
vol = CLAMP (vol, 0, 100);
377
button->volume = vol;
378
update_image (button, vol);
380
g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);
386
update_image (VolumeButton *button, int vol)
391
id = "muine-volume-zero";
392
else if (vol <= 100 / 3)
393
id = "muine-volume-min";
394
else if (vol <= 2 * 100 / 3)
395
id = "muine-volume-medium";
397
id = "muine-volume-max";
399
gtk_image_set_from_stock (GTK_IMAGE (button->image), id, GTK_ICON_SIZE_LARGE_TOOLBAR);
403
volume_button_set_volume (VolumeButton *button, int vol)
405
if (button->volume == vol)
408
button->volume = vol;
410
update_image (button, vol);
412
g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);