3c2bed031e9e5da8a4c1ecf9163caa4a86356bb1
[hildon] / src / hildon-vvolumebar.c
1 /*
2  * This file is part of hildon-libs
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-vvolumebar
27  * @short_description: A widget that displays a vertical volume bar
28  * @see_also: #HildonVolumebar, #HildonHVolumebar
29  *
30  * #HildonVVolumebar is a subclass of #HildonVolumebar.  It displays a
31  * vertical volume bar that allows increasing or decreasing volume
32  * within a predefined range, and muting when users click the mute icon.
33  */
34
35 #include <config.h>
36 #include "hildon-vvolumebar.h"
37 #include <gtk/gtk.h>
38 #include "hildon-volumebar-range.h"
39 #include "hildon-volumebar-private.h"
40
41 /* Volume bar */
42 #define DEFAULT_BAR_WIDTH               58
43 #define MINIMUM_BAR_HEIGHT             165
44 /* Toggle button */
45 #define DEFAULT_VERTICAL_TBUTTON_WIDTH  26
46 #define DEFAULT_VERTICAL_TBUTTON_HEIGHT 26
47 #define DEFAULT_ENDING_SIZE             20
48 /* Gap to leave for mute button */
49 #define HORIZONTAL_MUTE_GAP             16
50 #define VERTICAL_MUTE_GAP                6
51
52 static HildonVolumebarClass *parent_class;
53 static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass);
54 static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar);
55 static gboolean hildon_vvolumebar_expose(GtkWidget * widget,
56                                          GdkEventExpose * event);
57 static void hildon_vvolumebar_size_request(GtkWidget * widget,
58                                            GtkRequisition * requisition);
59 static void hildon_vvolumebar_size_allocate(GtkWidget * widget,
60                                             GtkAllocation * allocation);
61
62 GType hildon_vvolumebar_get_type(void)
63 {
64     static GType type = 0;
65
66     if (!type) {
67         static const GTypeInfo info = {
68             sizeof(HildonVVolumebarClass),
69             NULL,       /* base_init */
70             NULL,       /* base_finalize */
71             (GClassInitFunc) hildon_vvolumebar_class_init,     /* class_init */
72             NULL,       /* class_finalize */
73             NULL,       /* class_data */
74             sizeof(HildonVVolumebar),
75             0,
76             (GInstanceInitFunc) hildon_vvolumebar_init,
77         };
78         type =
79             g_type_register_static(HILDON_TYPE_VOLUMEBAR,
80                                    "HildonVVolumebar", &info, 0);
81     }
82     return type;
83 }
84
85 static void hildon_vvolumebar_class_init(HildonVVolumebarClass * klass)
86 {
87     GtkWidgetClass *volumebar_class = GTK_WIDGET_CLASS(klass);
88
89     parent_class = g_type_class_peek_parent(klass);
90
91     volumebar_class->size_request = hildon_vvolumebar_size_request;
92     volumebar_class->size_allocate = hildon_vvolumebar_size_allocate;
93     volumebar_class->expose_event = hildon_vvolumebar_expose;
94 }
95
96 static void hildon_vvolumebar_init(HildonVVolumebar * vvolumebar)
97 {
98     HildonVolumebarPrivate *priv;
99
100     priv = HILDON_VOLUMEBAR_GET_PRIVATE(vvolumebar);
101
102     priv->volumebar =
103         HILDON_VOLUMEBAR_RANGE(hildon_volumebar_range_new
104                                (GTK_ORIENTATION_VERTICAL));
105
106     GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(vvolumebar), GTK_CAN_FOCUS);
107
108     gtk_widget_set_parent(GTK_WIDGET(priv->tbutton), GTK_WIDGET(vvolumebar));
109     gtk_widget_set_parent(GTK_WIDGET(priv->volumebar), GTK_WIDGET(vvolumebar));
110
111     gtk_scale_set_draw_value(GTK_SCALE(priv->volumebar), FALSE);
112
113     /* Signals */
114     g_signal_connect_swapped(G_OBJECT(priv->volumebar), "value-changed",
115                              G_CALLBACK(hildon_volumebar_level_change),
116                              vvolumebar);
117     g_signal_connect_swapped(priv->tbutton, "toggled",
118         G_CALLBACK(_hildon_volumebar_mute_toggled), vvolumebar);
119
120     gtk_widget_show(GTK_WIDGET(priv->volumebar));
121 }
122
123 /**
124  * hildon_vvolumebar_new:
125  *
126  * Creates a new #HildonVVolumebar widget.
127  *
128  * Returns: a new #HildonVVolumebar
129  */
130 GtkWidget *hildon_vvolumebar_new(void)
131 {
132     return GTK_WIDGET(g_object_new(HILDON_TYPE_VVOLUMEBAR, NULL));
133 }
134
135 static gboolean hildon_vvolumebar_expose(GtkWidget * widget,
136                                          GdkEventExpose * event)
137 {
138     HildonVolumebarPrivate *priv;
139
140     g_assert(HILDON_IS_VVOLUMEBAR(widget));
141
142     priv = HILDON_VOLUMEBAR_GET_PRIVATE(HILDON_VOLUMEBAR(widget));
143     
144     if (GTK_WIDGET_DRAWABLE(widget)) {
145         /* Paint background */
146         gtk_paint_box(widget->style, widget->window,
147                       GTK_WIDGET_STATE(priv->volumebar), GTK_SHADOW_OUT,
148                       NULL, widget, "background",
149                       widget->allocation.x,
150                       widget->allocation.y,
151                       widget->allocation.width,
152                       widget->allocation.height);
153
154         /* The contents of the widget can paint themselves */
155         (*GTK_WIDGET_CLASS(parent_class)->expose_event) (widget, event);
156     }
157
158     return FALSE;
159 }
160
161 static void
162 hildon_vvolumebar_size_request(GtkWidget * widget,
163                                GtkRequisition * requisition)
164 {
165     g_assert(HILDON_IS_VVOLUMEBAR(widget));
166
167     requisition->height = MINIMUM_BAR_HEIGHT;
168     requisition->width = DEFAULT_BAR_WIDTH;
169 }
170
171 static void
172 hildon_vvolumebar_size_allocate(GtkWidget * widget,
173                                 GtkAllocation * allocation)
174 {
175     HildonVolumebarPrivate *priv;
176
177     GtkAllocation range_allocation, button_allocation;
178
179     g_assert(HILDON_IS_VVOLUMEBAR(widget));
180
181     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
182
183     /* Center the widget horizontally */
184     if (allocation->width > DEFAULT_BAR_WIDTH) {
185         allocation->x +=
186           (allocation->width - DEFAULT_BAR_WIDTH) / 2;
187         allocation->width = DEFAULT_BAR_WIDTH;
188     }
189
190     GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
191
192     if (priv->volumebar && GTK_WIDGET_VISIBLE(priv->volumebar)) {
193         /* Allocate space for the slider */
194         range_allocation.x = allocation->x;
195         range_allocation.y = allocation->y + DEFAULT_ENDING_SIZE;
196
197         range_allocation.width = DEFAULT_BAR_WIDTH;
198         
199         if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton))
200         {
201             /* Leave room for the mute button */
202             range_allocation.height = MAX(0,
203                                           allocation->height
204                                           - 2 * DEFAULT_ENDING_SIZE
205                                           - DEFAULT_VERTICAL_TBUTTON_HEIGHT
206                                           - VERTICAL_MUTE_GAP);
207         }
208         
209         else
210         {
211             range_allocation.height = MAX(0,
212                                           allocation->height
213                                           - 2 * DEFAULT_ENDING_SIZE);
214         }
215         
216         gtk_widget_size_allocate(GTK_WIDGET(priv->volumebar),
217                                  &range_allocation);
218     }
219     
220     if (priv->tbutton && GTK_WIDGET_VISIBLE(priv->tbutton)) {
221         /* Allocate space for the mute button */
222         button_allocation.x = allocation->x + HORIZONTAL_MUTE_GAP;
223         button_allocation.y = allocation->y + allocation->height -
224                               VERTICAL_MUTE_GAP - 2 * DEFAULT_ENDING_SIZE;
225         button_allocation.width = DEFAULT_VERTICAL_TBUTTON_WIDTH;
226         button_allocation.height = DEFAULT_VERTICAL_TBUTTON_HEIGHT;
227         gtk_widget_size_allocate(GTK_WIDGET(priv->tbutton),
228                                  &button_allocation);
229     }
230 }