2008-09-15 Alberto Garcia <agarcia@igalia.com>
[hildon] / src / hildon-picker-button.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2008 Nokia Corporation, all rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser Public License as published by
8  * the Free Software Foundation; version 2 of the license.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser Public License for more details.
14  *
15  */
16
17 /**
18  * SECTION:hildon-picker-button
19  * @short_description: A button that launches a #HildonPickerDialog and displays the
20  * selected item
21  * @see_also: #HildonTouchSelector, #HildonPickerDialog
22  *
23  * #HildonPickerButton is a widget that lets the user select a particular item from
24  * a list. Visually, it's a button with title and value labels that brings up a
25  * #HildonPickerDialog. The user can then use this dialog to choose an item, which
26  * will be displayed in the value label of the button.
27  *
28  * You should create your own #HildonTouchSelector at convenience and set it
29  * to the #HildonPickerButton with hildon_picker_button_set_selector(). For
30  * the common use cases of buttons to select date and time, you can use #HildonDateButton
31  * and #HildonTimeButton.
32  *
33  */
34
35 #include "hildon-picker-button.h"
36 #include "hildon-picker-dialog.h"
37
38 G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON)
39
40 #define GET_PRIVATE(o)                                                  \
41   (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate))
42
43 typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate;
44
45 struct _HildonPickerButtonPrivate
46 {
47   GtkWidget *selector;
48   GtkWidget *dialog;
49 };
50
51 /* Signals */
52 enum
53 {
54   VALUE_CHANGED,
55   LAST_SIGNAL
56 };
57
58 enum
59 {
60   PROP_SELECTOR = 1,
61 };
62
63 static guint picker_button_signals[LAST_SIGNAL] = { 0 };
64
65 static void
66 hildon_picker_button_get_property (GObject * object, guint property_id,
67                                    GValue * value, GParamSpec * pspec)
68 {
69   switch (property_id) {
70   case PROP_SELECTOR:
71     g_value_set_object (value,
72                         hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object)));
73     break;
74   default:
75     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
76   }
77 }
78
79 static void
80 hildon_picker_button_set_property (GObject * object, guint property_id,
81                                    const GValue * value, GParamSpec * pspec)
82 {
83   switch (property_id) {
84   case PROP_SELECTOR:
85     hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object),
86                                        g_value_get_object (value));
87     break;
88   default:
89     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
90   }
91 }
92
93 static void
94 hildon_picker_button_clicked (GtkButton * button)
95 {
96   GtkWidget *parent;
97   HildonPickerButtonPrivate *priv;
98   gint response;
99
100   priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
101
102   g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector));
103
104   /* Create the dialog if it doesn't exist already.  */
105   if (!priv->dialog) {
106     parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
107     if (GTK_WIDGET_TOPLEVEL (parent)) {
108       priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent));
109     } else {
110       priv->dialog = hildon_picker_dialog_new (NULL);
111     }
112
113     hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog),
114                                        HILDON_TOUCH_SELECTOR (priv->selector));
115
116     gtk_window_set_modal (GTK_WINDOW (priv->dialog),
117                           gtk_window_get_modal (GTK_WINDOW (parent)));
118     gtk_window_set_title (GTK_WINDOW (priv->dialog),
119                           hildon_button_get_title (HILDON_BUTTON (button)));
120   }
121
122   response = gtk_dialog_run (GTK_DIALOG (priv->dialog));
123   switch (response) {
124   case GTK_RESPONSE_OK:
125     hildon_button_set_value (HILDON_BUTTON (button),
126                              hildon_touch_selector_get_current_text
127                              (HILDON_TOUCH_SELECTOR (priv->selector)));
128     g_signal_emit (HILDON_PICKER_BUTTON (button),
129                    picker_button_signals[VALUE_CHANGED], 0);
130     break;
131   }
132   gtk_widget_hide (priv->dialog);
133 }
134
135 static void
136 hildon_picker_button_class_init (HildonPickerButtonClass * klass)
137 {
138   GObjectClass *object_class = G_OBJECT_CLASS (klass);
139   GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
140
141   g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate));
142
143   object_class->get_property = hildon_picker_button_get_property;
144   object_class->set_property = hildon_picker_button_set_property;
145
146   button_class->clicked = hildon_picker_button_clicked;
147
148   g_object_class_install_property (object_class,
149                                    PROP_SELECTOR,
150                                    g_param_spec_object ("touch-selector",
151                                                         "HildonTouchSelector widget",
152                                                         "HildonTouchSelector widget to be launched on button clicked",
153                                                         HILDON_TYPE_TOUCH_SELECTOR,
154                                                         G_PARAM_READWRITE));
155
156   /**
157    * HildonPickerButton::value-changed:
158    * @widget: the widget that received the signal
159    *
160    * The ::value-changed signal is emitted each time the user chooses a different
161    * item from the #HildonTouchSelector related, and the value label gets updated.
162    */
163   picker_button_signals[VALUE_CHANGED] =
164     g_signal_new ("value-changed",
165                   G_TYPE_FROM_CLASS (klass),
166                   G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
167                   0,
168                   NULL, NULL,
169                   g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
170 }
171
172 static void
173 hildon_picker_button_init (HildonPickerButton * self)
174 {
175   HildonPickerButtonPrivate *priv;
176
177   priv = GET_PRIVATE (self);
178
179   priv->dialog = NULL;
180   priv->selector = NULL;
181 }
182
183 /**
184  * hildon_picker_button_new:
185  * @size: One of #HildonSizeType, specifying the size of the new button.
186  * @arrangement: one of #HildonButtonArrangement, specifying the placement of the
187  * labels.
188  *
189  * Creates a new #HildonPickerButton. See hildon_button_new() for details on the
190  * parameters.
191  *
192  * Returns: a newly created #HildonPickerButton
193  **/
194 GtkWidget *
195 hildon_picker_button_new (HildonSizeType          size,
196                           HildonButtonArrangement arrangement)
197 {
198   GtkWidget *button;
199
200   button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
201                          "arrangement", arrangement, "size", size, NULL);
202
203   return button;
204 }
205
206 /**
207  * hildon_picker_button_set_selector:
208  * @button: a #HildonPickerButton
209  * @selector: a #HildonTouchSelector
210  *
211  * Sets @selector as the #HildonTouchSelector to be shown in the
212  * #HildonPickerDialog that @button brings up.
213  **/
214 void
215 hildon_picker_button_set_selector (HildonPickerButton * button,
216                                    HildonTouchSelector * selector)
217 {
218   HildonPickerButtonPrivate *priv;
219
220   g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
221   g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
222
223   priv = GET_PRIVATE (button);
224
225   priv->selector = g_object_ref (selector);
226 }
227
228 /**
229  * hildon_picker_button_get_selector:
230  * @button: a #HildonPickerButton
231  *
232  * Retrieves the #HildonTouchSelector associated to @button.
233  *
234  * Returns: a #HildonTouchSelector
235  **/
236 HildonTouchSelector *
237 hildon_picker_button_get_selector (HildonPickerButton * button)
238 {
239   HildonPickerButtonPrivate *priv;
240
241   g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
242
243   priv = GET_PRIVATE (button);
244
245   return HILDON_TOUCH_SELECTOR (priv->selector);
246 }