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