b25e19b811bda74080f82111516b836c89595836
[hildon] / src / hildon-hvolumebar.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
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.
12  *
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.
17  *
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
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-hvolumebar
27  * @short_description: A widget that displays a horizontal volume bar.
28  * @see_also: #HildonVVolumebar, #HildonVolumebar
29  * 
30  * The #HildonHVolumebar widget displays a horizontal volume bar that allows
31  * increasing or decreasing volume within a pre-defined range, and includes 
32  * a mute icon which users can click to mute the sound.
33  * 
34  * <example>
35  * <programlisting>
36  * GtkWidget *volbar = hildon_hvolumebar_new ();
37  * g_signal_connect (G_OBJECT(volbar), "mute_toggled", G_CALLBACK(mute_toggle), NULL);
38  * g_signal_connect (G_OBJECT(volbar), "level_changed", G_CALLBACK(level_change), NULL);
39  * </programlisting>
40  * </example>
41  *
42  */
43
44 #undef                                          HILDON_DISABLE_DEPRECATED
45
46 #include                                        "hildon-hvolumebar.h"
47 #include                                        "hildon-volumebar.h"
48 #include                                        "hildon-volumebar-range.h"
49 #include                                        "hildon-volumebar-private.h"
50
51 /* Defines for normal version of HVolumebar */
52 /* Toggle button */
53
54 #define                                         DEFAULT_TBUTTON_WIDTH 60
55
56 #define                                         DEFAULT_TBUTTON_HEIGHT 60
57
58 /* Volume bar */
59 #define                                         MINIMUM_BAR_WIDTH 147
60
61 #define                                         DEFAULT_BAR_HEIGHT 60
62
63 #define                                         DEFAULT_ENDING_SIZE 20
64
65 /* Gap to leave for mute button */
66 #define                                         VERTICAL_MUTE_GAP 0
67
68 #define                                         HORIZONTAL_MUTE_GAP 0
69
70 /* Sizes inside a toolbar */
71 /* Toggle button */
72
73 #define                                         TOOL_DEFAULT_TBUTTON_WIDTH 26
74
75 #define                                         TOOL_DEFAULT_TBUTTON_HEIGHT 26
76
77 /* Volumebar */
78
79 #define                                         TOOL_MINIMUM_BAR_WIDTH 121
80
81 #define                                         TOOL_DEFAULT_BAR_HEIGHT 40
82
83 #define                                         TOOL_DEFAULT_ENDING_SIZE 0
84
85 #define                                         TOOL_VERTICAL_MUTE_GAP \
86                                                 ((TOOL_DEFAULT_BAR_HEIGHT - TOOL_DEFAULT_TBUTTON_HEIGHT) / 2)
87
88 static HildonVolumebarClass*                    parent_class;
89
90 static void 
91 hildon_hvolumebar_class_init                    (HildonHVolumebarClass *klass);
92
93 static void 
94 hildon_hvolumebar_init                          (HildonHVolumebar *hvolumebar);
95
96 static gboolean
97 hildon_hvolumebar_expose                        (GtkWidget *widget,
98                                                  GdkEventExpose *event);
99 static void 
100 hildon_hvolumebar_size_request                  (GtkWidget *widget,
101                                                  GtkRequisition *requisition);
102 static void 
103 hildon_hvolumebar_size_allocate                 (GtkWidget *widget,
104                                                  GtkAllocation *allocation);
105 static void 
106 hildon_hvolumebar_map                           (GtkWidget *widget);
107
108 /**
109  * hildon_hvolumebar_get_type:
110  *
111  * Returns GType for HildonHVolumebar.
112  *
113  * Returns: HildonHVolumebar type
114  */
115 GType G_GNUC_CONST
116 hildon_hvolumebar_get_type                      (void)
117 {
118     static GType type = 0;
119
120     if (!type) {
121         static const GTypeInfo info = {
122             sizeof (HildonHVolumebarClass),
123             NULL,       /* base_init */
124             NULL,       /* base_finalize */
125             (GClassInitFunc) hildon_hvolumebar_class_init,     /* class_init */
126             NULL,       /* class_finalize */
127             NULL,       /* class_data */
128             sizeof (HildonHVolumebar),
129             0,
130             (GInstanceInitFunc) hildon_hvolumebar_init,
131         };
132         type = g_type_register_static (HILDON_TYPE_VOLUMEBAR,
133                 "HildonHVolumebar", &info, 0);
134     }
135     return type;
136 }
137
138 static void
139 hildon_hvolumebar_class_init                    (HildonHVolumebarClass *klass)
140 {
141     GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS (klass);
142
143     parent_class = g_type_class_peek_parent (klass);
144
145     volumebar_class->size_request   = hildon_hvolumebar_size_request;
146     volumebar_class->size_allocate  = hildon_hvolumebar_size_allocate;
147     volumebar_class->map            = hildon_hvolumebar_map;
148     volumebar_class->expose_event   = hildon_hvolumebar_expose;
149 }
150
151 static void 
152 hildon_hvolumebar_init                          (HildonHVolumebar *hvolumebar)
153 {
154     HildonVolumebarPrivate *priv;
155
156     priv = HILDON_VOLUMEBAR_GET_PRIVATE (hvolumebar);
157
158     priv->volumebar =
159         HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new
160                 (GTK_ORIENTATION_HORIZONTAL));
161
162     gtk_widget_set_parent (GTK_WIDGET (priv->tbutton), GTK_WIDGET (hvolumebar));
163     gtk_widget_set_parent (GTK_WIDGET (priv->volumebar), GTK_WIDGET (hvolumebar));
164
165     gtk_scale_set_draw_value (GTK_SCALE (priv->volumebar), FALSE);
166
167     /* Signals */
168     g_signal_connect_swapped (G_OBJECT (priv->volumebar), "value-changed",
169             G_CALLBACK(hildon_volumebar_level_change),
170             hvolumebar);
171
172     g_signal_connect_swapped (priv->tbutton, "toggled",
173             G_CALLBACK (hildon_volumebar_mute_toggled), hvolumebar);
174
175     gtk_widget_show (GTK_WIDGET (priv->volumebar));
176 }
177
178 /**
179  * hildon_hvolumebar_new:
180  *
181  * Creates a new #HildonHVolumebar widget.
182  *
183  * Returns: a new #HildonHVolumebar
184  */
185 GtkWidget*
186 hildon_hvolumebar_new                           (void)
187 {
188     return GTK_WIDGET (g_object_new(HILDON_TYPE_HVOLUMEBAR, NULL));
189 }
190
191 static void 
192 hildon_hvolumebar_map                           (GtkWidget* widget)
193 {
194     HildonVolumebarPrivate *priv;
195     GtkWidget *parent;
196
197     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
198     g_assert (priv);
199
200     parent = gtk_widget_get_ancestor (GTK_WIDGET (widget), GTK_TYPE_TOOLBAR);
201
202     /* Check if the volumebar is in a toolbar */
203     if (parent)
204         priv->is_toolbar = TRUE;
205
206     GTK_WIDGET_CLASS (parent_class)->map (widget);
207 }
208
209 static gboolean 
210 hildon_hvolumebar_expose                        (GtkWidget * widget,
211                                                  GdkEventExpose * event)
212 {
213     HildonVolumebarPrivate *priv;
214
215     priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget));
216     g_assert (priv);
217
218     if (GTK_WIDGET_DRAWABLE (widget)) {
219         /* Paint background */
220         gtk_paint_box (widget->style, widget->window,
221                 GTK_WIDGET_STATE (priv->volumebar), GTK_SHADOW_OUT,
222                 NULL, widget, "background",
223                 widget->allocation.x,
224                 widget->allocation.y,
225                 widget->allocation.width,
226                 widget->allocation.height);
227
228         /* The contents of the widget can paint themselves */
229         /* FIXME Not sure if this is even needed here */
230         (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event);
231     }
232
233     return FALSE;
234 }
235
236 static void
237 hildon_hvolumebar_size_request                  (GtkWidget * widget,
238                                                  GtkRequisition * requisition)
239 {
240     HildonVolumebarPrivate *priv;
241
242     priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget));
243     g_assert (priv);
244
245     /* Volumebar has different dimensions in toolbar */
246     requisition->width = (priv->is_toolbar
247             ? TOOL_MINIMUM_BAR_WIDTH
248             : MINIMUM_BAR_WIDTH);
249
250     requisition->height = (priv->is_toolbar
251             ? TOOL_DEFAULT_BAR_HEIGHT
252             : DEFAULT_BAR_HEIGHT);
253 }
254
255 static void
256 hildon_hvolumebar_size_allocate                 (GtkWidget * widget,
257                                                  GtkAllocation * allocation)
258 {
259     HildonVolumebarPrivate *priv;
260     GtkAllocation button_allocation, range_allocation;
261
262     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
263     g_assert (priv);
264
265     button_allocation.x = 0;
266     button_allocation.width = 0;
267
268     /* Center the widget vertically */
269     if (priv->is_toolbar && allocation->height > TOOL_DEFAULT_BAR_HEIGHT) {
270         allocation->y += (allocation->height - TOOL_DEFAULT_BAR_HEIGHT) / 2;
271         allocation->height = TOOL_DEFAULT_BAR_HEIGHT;
272     }
273
274     if (!priv->is_toolbar && allocation->height > DEFAULT_BAR_HEIGHT) {
275         allocation->y += (allocation->height - DEFAULT_BAR_HEIGHT) / 2;
276         allocation->height = DEFAULT_BAR_HEIGHT;
277     }
278
279     GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
280
281     if (priv->tbutton && GTK_WIDGET_VISIBLE (priv->tbutton)) {
282
283         /* Allocate space for the mute button */
284         if (priv->is_toolbar) {
285             button_allocation.x = allocation->x;
286             button_allocation.y = allocation->y + TOOL_VERTICAL_MUTE_GAP;
287             button_allocation.width = TOOL_DEFAULT_TBUTTON_WIDTH;
288             button_allocation.height = TOOL_DEFAULT_TBUTTON_HEIGHT;
289         } else {
290             button_allocation.x = allocation->x + DEFAULT_ENDING_SIZE;
291             button_allocation.y = allocation->y + VERTICAL_MUTE_GAP;
292             button_allocation.width = DEFAULT_TBUTTON_WIDTH;
293             button_allocation.height = DEFAULT_TBUTTON_HEIGHT;
294         }
295         gtk_widget_size_allocate (GTK_WIDGET (priv->tbutton),
296                 &button_allocation);
297     }
298     if (priv->volumebar && GTK_WIDGET_VISIBLE (priv->volumebar)) {
299
300         /* Allocate space for the slider */
301         range_allocation.y = allocation->y;
302
303         if (priv->tbutton && GTK_WIDGET_VISIBLE (priv->tbutton))
304         {
305             /* Leave room for the mute button */
306             range_allocation.x = button_allocation.x
307                 + button_allocation.width
308                 + HORIZONTAL_MUTE_GAP;
309
310             if (priv->is_toolbar) 
311             {
312                 /* In toolbar with mute button */
313                 range_allocation.width = MAX(0,
314                         allocation->width
315                         - 2 * TOOL_DEFAULT_ENDING_SIZE
316                         - TOOL_DEFAULT_TBUTTON_WIDTH
317                         - HORIZONTAL_MUTE_GAP);
318
319                 range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT;
320
321             } 
322
323             else 
324             {
325                 /* Standalone with mute button */
326                 range_allocation.width = MAX(0,
327                         allocation->width
328                         - 2 * DEFAULT_ENDING_SIZE
329                         - DEFAULT_TBUTTON_WIDTH
330                         - HORIZONTAL_MUTE_GAP);
331
332                 range_allocation.height = DEFAULT_BAR_HEIGHT;
333             }
334
335         }
336
337         else
338         {
339             if (priv->is_toolbar) 
340             {
341                 /* In toolbar without mute button */
342                 range_allocation.x = allocation->x;
343
344                 range_allocation.width = MAX(0,
345                         allocation->width
346                         - 2 * TOOL_DEFAULT_ENDING_SIZE );
347
348                 range_allocation.height = TOOL_DEFAULT_BAR_HEIGHT;
349
350             } 
351
352             else 
353             {
354                 /* Standalone without mute button */
355                 range_allocation.x = allocation->x + DEFAULT_ENDING_SIZE;
356
357                 range_allocation.width = MAX(0,
358                         allocation->width
359                         - 2 * DEFAULT_ENDING_SIZE );
360
361                 range_allocation.height = DEFAULT_BAR_HEIGHT;
362             }
363         }
364
365         gtk_widget_size_allocate (GTK_WIDGET (priv->volumebar),
366                 &range_allocation);
367     }
368 }
369