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