~ubuntu-branches/debian/squeeze/muine/squeeze

« back to all changes in this revision

Viewing changes to libmuine/volume-button.c

  • Committer: Bazaar Package Importer
  • Author(s): Dave Beckett
  • Date: 2007-02-13 00:07:32 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20070213000732-te83ms9n1ou7ek12
Tags: 0.8.7-1
* New upstream release
  - Require Gtk# 2.6 or newer
  - Build-depend on mono-gmcs, gtk# 2.6
  - Build-depend on libmono-cairo2.0-cil
* muine.install
   - Drop debian/tmp/usr/lib/mono/gac/*
   - Drop debian/tmp/usr/lib/mono/muine/*
   - Add debian/tmp/usr/lib/muine/*dll*
* Build-depend on mono-gmcs, gtk# 2.6
* Urgency high to get rid of gstreamer 0.8 at
  the request of the security team (Closes: #410442)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: C; c-file-style: "gnu" -*- */
2
 
/*
3
 
 * Copyright (C) 2003 Richard Hult <richard@imendio.com>
4
 
 * Copyright (C) 2004 Jorn Baayen <jorn@nl.linux.org>
5
 
 *
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.
10
 
 *
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.
15
 
 *
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.
20
 
 */
21
 
 
22
 
#include <config.h>
23
 
#include <string.h>
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"
34
 
 
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,
39
 
                                             GdkEventKey       *event,
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,
54
 
                                             int                vol);
55
 
 
56
 
enum {
57
 
  VOLUME_CHANGED,
58
 
  LAST_SIGNAL
59
 
};
60
 
 
61
 
static GObjectClass *parent_class;
62
 
static guint signals[LAST_SIGNAL];
63
 
 
64
 
GType
65
 
volume_button_get_type (void)
66
 
{
67
 
  static GType type = 0;
68
 
        
69
 
  if (!type)
70
 
    {
71
 
      static const GTypeInfo info =
72
 
        {
73
 
          sizeof (VolumeButtonClass),
74
 
          NULL,           /* base_init */
75
 
          NULL,           /* base_finalize */
76
 
          (GClassInitFunc) volume_button_class_init,
77
 
          NULL,           /* class_finalize */
78
 
          NULL,           /* class_data */
79
 
          sizeof (VolumeButton),
80
 
          0,
81
 
          (GInstanceInitFunc) volume_button_init,
82
 
        };
83
 
 
84
 
      type = g_type_register_static (GTK_TYPE_TOGGLE_BUTTON, "VolumeButton",
85
 
                                     &info, 0);
86
 
    }
87
 
 
88
 
  return type;
89
 
}
90
 
 
91
 
static void
92
 
volume_button_class_init (VolumeButtonClass *klass)
93
 
{
94
 
  GObjectClass *object_class;
95
 
 
96
 
  parent_class = g_type_class_peek_parent (klass);
97
 
  object_class = (GObjectClass*) klass;
98
 
 
99
 
  object_class->finalize = volume_button_finalize;
100
 
 
101
 
  signals[VOLUME_CHANGED] =
102
 
    g_signal_new ("volume_changed",
103
 
                  G_TYPE_FROM_CLASS (klass),
104
 
                  G_SIGNAL_RUN_LAST,
105
 
                  0,
106
 
                  NULL, NULL,
107
 
                  g_cclosure_marshal_VOID__INT,
108
 
                  G_TYPE_NONE, 1, G_TYPE_INT);
109
 
}
110
 
 
111
 
static void
112
 
volume_button_init (VolumeButton *button)
113
 
{
114
 
  g_signal_connect (button,
115
 
                    "toggled",
116
 
                    G_CALLBACK (toggled_cb),
117
 
                    button);
118
 
 
119
 
  g_signal_connect (button,
120
 
                    "scroll_event",
121
 
                    G_CALLBACK (scroll_event_cb),
122
 
                    button);
123
 
 
124
 
  button->image = gtk_image_new_from_stock ("muine-volume-medium",
125
 
                                            GTK_ICON_SIZE_LARGE_TOOLBAR);
126
 
  gtk_widget_show (button->image);
127
 
 
128
 
  gtk_container_add (GTK_CONTAINER (button), button->image);
129
 
 
130
 
  update_image (button, 0);
131
 
}
132
 
 
133
 
static void
134
 
volume_button_finalize (GObject *object)
135
 
{
136
 
  /*  VolumeButton *button = VOLUME_BUTTON (object);*/
137
 
 
138
 
  if (G_OBJECT_CLASS (parent_class)->finalize)
139
 
    G_OBJECT_CLASS (parent_class)->finalize (object);
140
 
}
141
 
 
142
 
GtkWidget *
143
 
volume_button_new (void)
144
 
{
145
 
  return g_object_new (TYPE_VOLUME_BUTTON, NULL);
146
 
}
147
 
 
148
 
static gboolean
149
 
scale_key_press_event_cb (GtkWidget   *widget,
150
 
                          GdkEventKey *event,
151
 
                          VolumeButton *button)
152
 
{
153
 
  switch (event->keyval)
154
 
    {
155
 
    case GDK_Escape:
156
 
      hide_scale (button);
157
 
 
158
 
      g_signal_emit (button, signals[VOLUME_CHANGED], 0,
159
 
                     button->revert_volume);
160
 
      
161
 
      return TRUE;
162
 
      
163
 
    case GDK_KP_Enter:
164
 
    case GDK_ISO_Enter:
165
 
    case GDK_3270_Enter:
166
 
    case GDK_Return:
167
 
    case GDK_space:
168
 
    case GDK_KP_Space:
169
 
      hide_scale (button);
170
 
      return TRUE;
171
 
      
172
 
    default:
173
 
      break;
174
 
    }
175
 
  
176
 
  return FALSE;
177
 
}
178
 
 
179
 
static void
180
 
scale_value_changed_cb (GtkWidget    *widget,
181
 
                        VolumeButton *button)
182
 
{
183
 
  int vol;
184
 
 
185
 
  vol = gtk_range_get_value (GTK_RANGE (widget));
186
 
  vol = CLAMP (vol, 0, 100);
187
 
 
188
 
  button->volume = vol;
189
 
  update_image (button, vol);
190
 
 
191
 
  g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);
192
 
}
193
 
 
194
 
static gboolean
195
 
popup_button_press_event_cb (GtkWidget      *widget,
196
 
                             GdkEventButton *event,
197
 
                             VolumeButton   *button)
198
 
{
199
 
  if (button->popup)
200
 
    {
201
 
      hide_scale (button);
202
 
      return TRUE;
203
 
    }
204
 
  
205
 
  return FALSE;
206
 
}
207
 
 
208
 
static void
209
 
show_scale (VolumeButton *button)
210
 
{
211
 
  GtkWidget      *frame;
212
 
  GtkWidget      *box;
213
 
  GtkAdjustment  *adj;
214
 
  GtkWidget      *label;
215
 
  GtkRequisition  req;
216
 
  int             x, y;
217
 
  int             width, height;
218
 
  GdkGrabStatus   grabbed;
219
 
  
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)));
223
 
 
224
 
  button->revert_volume = button->volume;
225
 
  
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);
230
 
 
231
 
  gtk_container_add (GTK_CONTAINER (button->popup), frame);
232
 
        
233
 
  box = gtk_vbox_new (FALSE, 0);
234
 
  gtk_widget_show (box);
235
 
 
236
 
  gtk_container_add (GTK_CONTAINER (frame), box);
237
 
 
238
 
  adj = GTK_ADJUSTMENT (gtk_adjustment_new (button->volume, 0, 100, 5, 10, 0));
239
 
  
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);
245
 
        
246
 
  g_signal_connect (button->popup,
247
 
                    "button_press_event",
248
 
                    G_CALLBACK (popup_button_press_event_cb),
249
 
                    button);
250
 
  
251
 
  g_signal_connect (button->scale,
252
 
                    "key_press_event",
253
 
                    G_CALLBACK (scale_key_press_event_cb),
254
 
                    button);
255
 
 
256
 
  g_signal_connect (button->scale,
257
 
                    "value_changed",
258
 
                    G_CALLBACK (scale_value_changed_cb),
259
 
                    button);
260
 
 
261
 
  label = gtk_label_new ("+");  
262
 
  gtk_widget_show (label);
263
 
  gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
264
 
  
265
 
  label = gtk_label_new ("-");  
266
 
  gtk_widget_show (label);
267
 
  gtk_box_pack_end (GTK_BOX (box), label, FALSE, TRUE, 0);
268
 
 
269
 
  gtk_box_pack_start (GTK_BOX (box), button->scale, TRUE, TRUE, 0);
270
 
        
271
 
  /* Align the popup below the button. */
272
 
  gtk_widget_size_request (button->popup, &req);
273
 
        
274
 
  gdk_window_get_origin (GTK_BUTTON (button)->event_window, &x, &y);
275
 
  gdk_drawable_get_size (GTK_BUTTON (button)->event_window, &width, &height);
276
 
 
277
 
  req.width = MAX (req.width, width);
278
 
  
279
 
  x += (width - req.width) / 2;
280
 
  y += height;
281
 
  
282
 
  x = MAX (0, x);
283
 
  y = MAX (0, y);
284
 
  
285
 
  gtk_widget_set_size_request (button->scale, -1, 100);
286
 
  gtk_widget_set_size_request (button->popup, req.width, -1);
287
 
  
288
 
  gtk_window_move (GTK_WINDOW (button->popup), x, y);
289
 
  gtk_widget_show (button->popup);
290
 
 
291
 
  gtk_widget_grab_focus (button->popup);
292
 
  gtk_grab_add (button->popup);
293
 
 
294
 
  grabbed = gdk_pointer_grab (button->popup->window,
295
 
                              TRUE,
296
 
                              GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
297
 
                              NULL, NULL,
298
 
                              GDK_CURRENT_TIME);
299
 
  
300
 
  if (grabbed == GDK_GRAB_SUCCESS)
301
 
    {
302
 
      grabbed = gdk_keyboard_grab (button->popup->window, TRUE, GDK_CURRENT_TIME);
303
 
 
304
 
      if (grabbed != GDK_GRAB_SUCCESS)
305
 
        {
306
 
          gtk_grab_remove (button->popup);
307
 
          gtk_widget_destroy (button->popup);
308
 
          button->popup = NULL;
309
 
        }
310
 
    }
311
 
  else
312
 
    {
313
 
          gtk_grab_remove (button->popup);
314
 
          gtk_widget_destroy (button->popup);
315
 
          button->popup = NULL;
316
 
    }
317
 
}
318
 
 
319
 
static void
320
 
hide_scale (VolumeButton *button)
321
 
{
322
 
  GtkToggleButton *toggle;
323
 
 
324
 
  if (button->popup)
325
 
    {
326
 
      gtk_grab_remove (button->scale);
327
 
      gdk_pointer_ungrab (GDK_CURRENT_TIME);            
328
 
      gdk_keyboard_ungrab (GDK_CURRENT_TIME);
329
 
 
330
 
      gtk_widget_destroy (GTK_WIDGET (button->popup));
331
 
 
332
 
      button->popup = NULL;
333
 
    }
334
 
 
335
 
  toggle = GTK_TOGGLE_BUTTON (button);
336
 
  if (gtk_toggle_button_get_active (toggle))
337
 
    gtk_toggle_button_set_active (toggle, FALSE);
338
 
}
339
 
 
340
 
static void
341
 
toggled_cb (GtkWidget *widget, gpointer user_button)
342
 
{
343
 
  GtkToggleButton *toggle;
344
 
 
345
 
  toggle = GTK_TOGGLE_BUTTON (widget);
346
 
  if (gtk_toggle_button_get_active (toggle))
347
 
    show_scale (VOLUME_BUTTON (widget));
348
 
  else
349
 
    hide_scale (VOLUME_BUTTON (widget));
350
 
}
351
 
 
352
 
static gboolean
353
 
scroll_event_cb (GtkWidget      *widget,
354
 
                 GdkEventScroll *event,
355
 
                 VolumeButton   *button)
356
 
{
357
 
  int vol;
358
 
 
359
 
  vol = button->volume;
360
 
    
361
 
  switch (event->direction)
362
 
    {
363
 
    case GDK_SCROLL_UP:
364
 
      vol += 10;
365
 
      break;
366
 
 
367
 
    case GDK_SCROLL_DOWN:
368
 
      vol -= 10;
369
 
      break;
370
 
 
371
 
    default:
372
 
      return FALSE;
373
 
    }
374
 
 
375
 
  vol = CLAMP (vol, 0, 100);
376
 
 
377
 
  button->volume = vol;
378
 
  update_image (button, vol);
379
 
  
380
 
  g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);
381
 
  
382
 
  return TRUE;
383
 
}
384
 
 
385
 
static void
386
 
update_image (VolumeButton *button, int vol)
387
 
{
388
 
  const char *id;
389
 
 
390
 
  if (vol <= 0)
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";
396
 
  else
397
 
    id = "muine-volume-max";
398
 
 
399
 
  gtk_image_set_from_stock (GTK_IMAGE (button->image), id, GTK_ICON_SIZE_LARGE_TOOLBAR);
400
 
}
401
 
 
402
 
void
403
 
volume_button_set_volume (VolumeButton *button, int vol)
404
 
{
405
 
  if (button->volume == vol)
406
 
    return;
407
 
 
408
 
  button->volume = vol;
409
 
 
410
 
  update_image (button, vol);
411
 
  
412
 
  g_signal_emit (button, signals[VOLUME_CHANGED], 0, vol);
413
 
}