2008-11-25 Alberto Garcia <agarcia@igalia.com>
[hildon] / src / hildon-picker-dialog.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2008 Nokia Corporation.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /**
22  * SECTION:hildon-picker-dialog
23  * @short_description: A utility widget that shows a #HildonTouchSelector widget
24  *
25  * HildonPickerDialog is a utility widget that shows a #HildonTouchSelector widget in
26  * a new dialog (a #HildonDialog)
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35 #include <stdlib.h>
36 #include <libintl.h>
37
38 #include "hildon-touch-selector.h"
39 #include "hildon-picker-dialog.h"
40
41 #define _(String)  dgettext("hildon-libs", String)
42
43 #define HILDON_PICKER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogPrivate))
44
45 G_DEFINE_TYPE (HildonPickerDialog, hildon_picker_dialog, HILDON_TYPE_DIALOG)
46
47 #define HILDON_TOUCH_SELECTOR_HEIGHT            320
48
49 struct _HildonPickerDialogPrivate
50 {
51   GtkWidget *selector;
52   GtkWidget *button;
53
54   gulong signal_id;
55 };
56
57 /* properties */
58 enum
59 {
60   PROP_0,
61   PROP_DONE_BUTTON_TEXT,
62   PROP_LAST
63 };
64
65 enum
66 {
67   RESPONSE,
68   LAST_SIGNAL
69 };
70
71 #define DEFAULT_DONE_BUTTON_TEXT        _("wdgt_bd_done")
72
73 static void
74 hildon_picker_dialog_set_property (GObject * object,
75                                    guint prop_id,
76                                    const GValue * value,
77                                    GParamSpec * pspec);
78
79 static void
80 hildon_picker_dialog_get_property (GObject * object,
81                                    guint prop_id,
82                                    GValue * value, GParamSpec * pspec);
83 /* gtkwidget */
84
85 /* private functions */
86 static gboolean requires_done_button (HildonPickerDialog * dialog);
87
88 static void
89 _select_on_selector_changed_cb (HildonTouchSelector * dialog,
90                                 gint column, gpointer data);
91
92 static gboolean
93 _hildon_picker_dialog_set_selector (HildonPickerDialog * dialog,
94                                     HildonTouchSelector * selector);
95
96 static void
97 _update_title_on_selector_changed_cb (HildonTouchSelector * selector,
98                                       gint column, gpointer data);
99
100 static void
101 hildon_picker_dialog_class_init (HildonPickerDialogClass * class)
102 {
103   GObjectClass *gobject_class;
104   GtkObjectClass *object_class;
105   GtkWidgetClass *widget_class;
106   GtkContainerClass *container_class;
107
108   gobject_class = (GObjectClass *) class;
109   object_class = (GtkObjectClass *) class;
110   widget_class = (GtkWidgetClass *) class;
111   container_class = (GtkContainerClass *) class;
112
113   /* GObject */
114   gobject_class->set_property = hildon_picker_dialog_set_property;
115   gobject_class->get_property = hildon_picker_dialog_get_property;
116
117   /* GtkWidget */
118
119   /* HildonPickerDialog */
120   class->set_selector = _hildon_picker_dialog_set_selector;
121
122   /* signals */
123
124   /* properties */
125   /**
126    * HildonPickerDialog
127    *
128    * Button label
129    */
130   g_object_class_install_property (gobject_class,
131                                    PROP_DONE_BUTTON_TEXT,
132                                    g_param_spec_string ("done-button-text",
133                                                         "Done Button Label",
134                                                         "Done Button Label",
135                                                         DEFAULT_DONE_BUTTON_TEXT,
136                                                         G_PARAM_READABLE |
137                                                         G_PARAM_WRITABLE |
138                                                         G_PARAM_CONSTRUCT));
139
140   g_type_class_add_private (object_class, sizeof (HildonPickerDialogPrivate));
141 }
142
143
144 static void
145 hildon_picker_dialog_init (HildonPickerDialog * dialog)
146 {
147   dialog->priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
148
149   dialog->priv->selector = NULL;
150   dialog->priv->button =
151     hildon_dialog_add_button (HILDON_DIALOG (dialog), "", GTK_RESPONSE_OK);
152   gtk_widget_grab_default (dialog->priv->button);
153
154   dialog->priv->signal_id = 0;
155 }
156
157
158 static void
159 hildon_picker_dialog_set_property (GObject * object,
160                                    guint param_id,
161                                    const GValue * value, GParamSpec * pspec)
162 {
163   switch (param_id) {
164   case PROP_DONE_BUTTON_TEXT:
165     hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (object),
166                                          g_value_get_string (value));
167     break;
168   default:
169     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
170     break;
171   }
172 }
173
174 static void
175 hildon_picker_dialog_get_property (GObject * object,
176                                    guint param_id,
177                                    GValue * value, GParamSpec * pspec)
178 {
179   HildonPickerDialog *dialog;
180
181   dialog = HILDON_PICKER_DIALOG (object);
182
183   switch (param_id) {
184   case PROP_DONE_BUTTON_TEXT:
185     g_value_set_string (value, hildon_picker_dialog_get_done_label (dialog));
186     break;
187   default:
188     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
189     break;
190   }
191 }
192
193 /* ------------------------------ PRIVATE METHODS ---------------------------- */
194 static void
195 _select_on_selector_changed_cb (HildonTouchSelector * selector,
196                                 gint column, gpointer data)
197 {
198   HildonPickerDialog *dialog = NULL;
199
200   g_return_if_fail (HILDON_IS_PICKER_DIALOG (data));
201
202   dialog = HILDON_PICKER_DIALOG (data);
203
204   gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
205 }
206
207 static void
208 _update_title_on_selector_changed_cb (HildonTouchSelector * selector,
209                                       gint column, gpointer data)
210 {
211   HildonPickerDialog *dialog = NULL;
212   gchar *new_title = NULL;
213
214   g_return_if_fail (HILDON_IS_PICKER_DIALOG (data));
215
216   dialog = HILDON_PICKER_DIALOG (data);
217
218   new_title = hildon_touch_selector_get_current_text (selector);
219
220   gtk_window_set_title (GTK_WINDOW (dialog), new_title);
221
222   g_free (new_title);
223 }
224
225
226 void
227 hildon_picker_dialog_set_done_label (HildonPickerDialog * dialog,
228                                      const gchar * label)
229 {
230   HildonPickerDialogPrivate *priv;
231
232   g_return_if_fail (HILDON_IS_PICKER_DIALOG (dialog));
233   g_return_if_fail (label != NULL);
234
235   priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
236
237   gtk_button_set_label (GTK_BUTTON (priv->button), label);
238 }
239
240 const gchar *
241 hildon_picker_dialog_get_done_label (HildonPickerDialog * dialog)
242 {
243   HildonPickerDialogPrivate *priv;
244
245   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL);
246
247   priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
248
249   return gtk_button_get_label (GTK_BUTTON (priv->button));
250 }
251
252 static gboolean
253 requires_done_button (HildonPickerDialog * dialog)
254 {
255   return hildon_touch_selector_has_multiple_selection
256     (HILDON_TOUCH_SELECTOR (dialog->priv->selector));
257 }
258
259 /* ------------------------------ PUBLIC METHODS ---------------------------- */
260
261 /**
262  * hildon_picker_dialog_new:
263  * @parent: the parent window
264  *
265  * Creates a new #HildonPickerDialog
266  *
267  * Returns: a new #HildonPickerDialog
268  **/
269 GtkWidget *
270 hildon_picker_dialog_new (GtkWindow * parent)
271 {
272   GtkDialog *dialog = NULL;
273
274   dialog = g_object_new (HILDON_TYPE_PICKER_DIALOG, NULL);
275
276   if (parent) {
277     gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
278   }
279
280   return GTK_WIDGET (dialog);
281 }
282
283
284 static gboolean
285 _hildon_picker_dialog_set_selector (HildonPickerDialog * dialog,
286                                     HildonTouchSelector * selector)
287 {
288   if (dialog->priv->selector != NULL) {
289     gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
290                           dialog->priv->selector);
291     g_object_unref (dialog->priv->selector);
292     gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->selector), -1, 320);
293     dialog->priv->selector = NULL;
294   }
295
296   dialog->priv->selector = GTK_WIDGET (selector);
297
298   if (dialog->priv->selector != NULL) {
299     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
300                         dialog->priv->selector, TRUE, TRUE, 0);
301
302    /* NOTE: this is a little hackish, but required at this moment
303       in order to ensure a correct height visualization */
304     gtk_widget_set_size_request (GTK_WIDGET (dialog->priv->selector), -1,
305                                  HILDON_TOUCH_SELECTOR_HEIGHT);
306
307     gtk_widget_show (dialog->priv->selector);
308     g_object_ref (dialog->priv->selector);
309   }
310
311   if (dialog->priv->signal_id) {
312     g_signal_handler_disconnect (dialog->priv->selector,
313                                  dialog->priv->signal_id);
314   }
315
316   if (requires_done_button (dialog)) {
317     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), TRUE);
318     gtk_widget_show (GTK_DIALOG (dialog)->action_area);
319     /* update the title */
320     dialog->priv->signal_id =
321       g_signal_connect (G_OBJECT (dialog->priv->selector), "changed",
322                         G_CALLBACK (_update_title_on_selector_changed_cb),
323                         dialog);
324   } else {
325     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
326     gtk_widget_hide (GTK_DIALOG (dialog)->action_area);
327     dialog->priv->signal_id =
328       g_signal_connect (G_OBJECT (dialog->priv->selector), "changed",
329                         G_CALLBACK (_select_on_selector_changed_cb), dialog);
330   }
331
332   return TRUE;
333 }
334
335 gboolean
336 hildon_picker_dialog_set_selector (HildonPickerDialog * dialog,
337                                    HildonTouchSelector * selector)
338 {
339   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), FALSE);
340   g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
341
342   return HILDON_PICKER_DIALOG_GET_CLASS (dialog)->set_selector (dialog, selector);
343 }
344
345 HildonTouchSelector *
346 hildon_picker_dialog_get_selector (HildonPickerDialog * dialog)
347 {
348   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL);
349
350   return HILDON_TOUCH_SELECTOR (dialog->priv->selector);
351 }