2008-07-29 Claudio Saavedra <csaavedra@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 #HildonTouchPicker widget
24  *
25  * HildonPickerDialog is a utility widget that shows a #HildonTouchPicker widget in
26  * a new dialog (see #GtkDialog for more information about this issue)
27  *
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <string.h>
35 #include <stdlib.h>
36
37 #include <libintl.h>
38 #include <gtk/gtkmarshal.h>
39
40 #include "hildon-touch-picker.h"
41 #include "hildon-picker-dialog.h"
42
43 #define _(String)  dgettext("hildon-libs", String)
44
45 #define HILDON_PICKER_DIALOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_PICKER_DIALOG, HildonPickerDialogPrivate))
46
47 G_DEFINE_TYPE (HildonPickerDialog, hildon_picker_dialog, GTK_TYPE_DIALOG)
48
49 struct _HildonPickerDialogPrivate
50 {
51   GtkWidget *picker;
52   GtkWidget *separator;
53   GtkWidget *button;
54
55   GtkWidget *title_label;
56
57   gulong signal_id;
58 };
59
60 /* properties */
61 enum
62 {
63   PROP_0,
64   PROP_DONE_BUTTON_TEXT,
65   PROP_LAST
66 };
67
68 enum
69 {
70   RESPONSE,
71   LAST_SIGNAL
72 };
73
74 #define DEFAULT_DONE_BUTTON_TEXT        "Done"
75
76 static void
77 hildon_picker_dialog_set_property (GObject * object,
78                                    guint prop_id,
79                                    const GValue * value,
80                                    GParamSpec * pspec);
81
82 static void
83 hildon_picker_dialog_get_property (GObject * object,
84                                    guint prop_id,
85                                    GValue * value, GParamSpec * pspec);
86 /* gtkwidget */
87 static void hildon_picker_dialog_realize (GtkWidget * widget);
88
89 /* private functions */
90 static gboolean requires_done_button (HildonPickerDialog * dialog);
91
92 static void
93 _select_on_picker_changed_cb (HildonTouchPicker * dialog,
94                               gint column, gpointer data);
95
96 static gboolean
97 _hildon_picker_dialog_set_picker (HildonPickerDialog * dialog,
98                                   HildonTouchPicker * picker);
99
100 static void
101 _update_title_on_picker_changed_cb (HildonTouchPicker * picker,
102                                     gint column, gpointer data);
103
104 static void
105 hildon_picker_dialog_class_init (HildonPickerDialogClass * class)
106 {
107   GObjectClass *gobject_class;
108   GtkObjectClass *object_class;
109   GtkWidgetClass *widget_class;
110   GtkContainerClass *container_class;
111
112   gobject_class = (GObjectClass *) class;
113   object_class = (GtkObjectClass *) class;
114   widget_class = (GtkWidgetClass *) class;
115   container_class = (GtkContainerClass *) class;
116
117   /* GObject */
118   gobject_class->set_property = hildon_picker_dialog_set_property;
119   gobject_class->get_property = hildon_picker_dialog_get_property;
120
121   /* GtkWidget */
122   widget_class->realize = hildon_picker_dialog_realize;
123
124   /* HildonPickerDialog */
125   class->set_picker = _hildon_picker_dialog_set_picker;
126
127   /* signals */
128
129   /* properties */
130   /**
131    * HildonPickerDialog
132    *
133    * Button label
134    */
135   g_object_class_install_property (gobject_class,
136                                    PROP_DONE_BUTTON_TEXT,
137                                    g_param_spec_string ("done-button-text",
138                                                         "Done Button Label",
139                                                         "Done Button Label",
140                                                         DEFAULT_DONE_BUTTON_TEXT,
141                                                         G_PARAM_READABLE |
142                                                         G_PARAM_WRITABLE |
143                                                         G_PARAM_CONSTRUCT));
144
145   g_type_class_add_private (object_class, sizeof (HildonPickerDialogPrivate));
146 }
147
148
149 static void
150 hildon_picker_dialog_init (HildonPickerDialog * dialog)
151 {
152   GtkWidget *separator = NULL;
153
154   dialog->priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
155
156   dialog->priv->picker = NULL;
157   dialog->priv->button =
158     gtk_dialog_add_button (GTK_DIALOG (dialog), "", GTK_RESPONSE_OK);
159
160   dialog->priv->title_label = gtk_label_new ("default value");
161   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
162                       dialog->priv->title_label, FALSE, FALSE, 0);
163   separator = gtk_hseparator_new ();
164   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
165                       separator, FALSE, FALSE, 0);
166
167   dialog->priv->signal_id = 0;
168
169 /*   gtk_widget_show (dialog->priv->title_label); */
170 /*   gtk_widget_show (separator); */
171 }
172
173
174 static void
175 hildon_picker_dialog_set_property (GObject * object,
176                                    guint param_id,
177                                    const GValue * value, GParamSpec * pspec)
178 {
179   HildonPickerDialogPrivate *priv = HILDON_PICKER_DIALOG_GET_PRIVATE (object);
180   g_assert (priv);
181
182   switch (param_id) {
183   case PROP_DONE_BUTTON_TEXT:
184     hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (object),
185                                          g_value_get_string (value));
186     break;
187   default:
188     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
189     break;
190   }
191 }
192
193 static void
194 hildon_picker_dialog_get_property (GObject * object,
195                                    guint param_id,
196                                    GValue * value, GParamSpec * pspec)
197 {
198   HildonPickerDialog *dialog;
199   HildonPickerDialogPrivate *priv;
200
201   dialog = HILDON_PICKER_DIALOG (object);
202   priv = HILDON_PICKER_DIALOG_GET_PRIVATE (object);
203
204   switch (param_id) {
205   case PROP_DONE_BUTTON_TEXT:
206     g_value_set_string (value, hildon_picker_dialog_get_done_label (dialog));
207     break;
208   default:
209     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
210     break;
211   }
212 }
213
214
215 static void
216 hildon_picker_dialog_realize (GtkWidget * widget)
217 {
218   GTK_WIDGET_CLASS (hildon_picker_dialog_parent_class)->realize (widget);
219
220 /*   gdk_window_set_decorations (widget->window, GDK_DECOR_BORDER); */
221 }
222
223 /* ------------------------------ PRIVATE METHODS ---------------------------- */
224 static void
225 _select_on_picker_changed_cb (HildonTouchPicker * picker,
226                               gint column, gpointer data)
227 {
228   HildonPickerDialog *dialog = NULL;
229
230   g_return_if_fail (HILDON_IS_PICKER_DIALOG (data));
231
232   dialog = HILDON_PICKER_DIALOG (data);
233
234   gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
235 }
236
237 static void
238 _update_title_on_picker_changed_cb (HildonTouchPicker * picker,
239                                     gint column, gpointer data)
240 {
241   HildonPickerDialog *dialog = NULL;
242   gchar *new_title = NULL;
243
244   g_return_if_fail (HILDON_IS_PICKER_DIALOG (data));
245
246   dialog = HILDON_PICKER_DIALOG (data);
247
248   new_title = hildon_touch_picker_get_current_text (picker);
249
250   if (dialog->priv->title_label != NULL) {
251 /*       gtk_label_set_text (GTK_LABEL(picker->priv->title_label), new_title); */
252   }
253   gtk_window_set_title (GTK_WINDOW (dialog), new_title);
254
255   g_free (new_title);
256 }
257
258
259 void
260 hildon_picker_dialog_set_done_label (HildonPickerDialog * dialog,
261                                      const gchar * label)
262 {
263   HildonPickerDialogPrivate *priv;
264
265   g_return_if_fail (HILDON_IS_PICKER_DIALOG (dialog));
266   g_return_if_fail (label != NULL);
267
268   priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
269
270   gtk_button_set_label (GTK_BUTTON (priv->button), label);
271 }
272
273 const gchar *
274 hildon_picker_dialog_get_done_label (HildonPickerDialog * dialog)
275 {
276   HildonPickerDialogPrivate *priv;
277
278   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL);
279
280   priv = HILDON_PICKER_DIALOG_GET_PRIVATE (dialog);
281
282   return gtk_button_get_label (GTK_BUTTON (priv->button));
283 }
284
285 static gboolean
286 requires_done_button (HildonPickerDialog * dialog)
287 {
288   gint n_columns = 0;
289   HildonTouchPickerSelectionMode mode =
290     HILDON_TOUCH_PICKER_SELECTION_MODE_SINGLE;
291
292   n_columns =
293     hildon_touch_picker_get_num_columns (HILDON_TOUCH_PICKER
294                                          (dialog->priv->picker));
295   mode =
296     hildon_touch_picker_get_column_selection_mode (HILDON_TOUCH_PICKER
297                                                    (dialog->priv->picker));
298
299   return ((n_columns > 1)
300           || (mode == HILDON_TOUCH_PICKER_SELECTION_MODE_MULTIPLE));
301 }
302
303
304 /* ------------------------------ PUBLIC METHODS ---------------------------- */
305
306 /**
307  * hildon_picker_dialog_new:
308  * @:
309  *
310  * Creates a new #HildonPickerDialog
311  *
312  * Returns: a new #HildonPickerDialog
313  **/
314 GtkWidget *
315 hildon_picker_dialog_new (GtkWindow * parent)
316 {
317   GtkDialog *dialog = NULL;
318
319   dialog = g_object_new (HILDON_TYPE_PICKER_DIALOG, NULL);
320
321   if (parent) {
322     gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
323   }
324
325   return GTK_WIDGET (dialog);
326 }
327
328
329 static gboolean
330 _hildon_picker_dialog_set_picker (HildonPickerDialog * dialog,
331                                   HildonTouchPicker * picker)
332 {
333   if (dialog->priv->picker != NULL) {
334     gtk_container_remove (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
335                           dialog->priv->picker);
336     g_object_unref (dialog->priv->picker);
337     dialog->priv->picker = NULL;
338   }
339
340   dialog->priv->picker = GTK_WIDGET (picker);
341
342   if (dialog->priv->picker != NULL) {
343     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
344                         dialog->priv->picker, TRUE, TRUE, 0);
345     gtk_widget_show (dialog->priv->picker);
346     g_object_ref (dialog->priv->picker);
347   }
348
349   if (dialog->priv->signal_id) {
350     g_signal_handler_disconnect (dialog->priv->picker,
351                                  dialog->priv->signal_id);
352   }
353
354   if (requires_done_button (dialog)) {
355     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), TRUE);
356     gtk_widget_show (GTK_DIALOG (dialog)->action_area);
357     /* update the title */
358     dialog->priv->signal_id =
359       g_signal_connect (G_OBJECT (dialog->priv->picker), "changed",
360                         G_CALLBACK (_update_title_on_picker_changed_cb),
361                         dialog);
362   } else {
363     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
364     gtk_widget_hide (GTK_DIALOG (dialog)->action_area);
365     dialog->priv->signal_id =
366       g_signal_connect (G_OBJECT (dialog->priv->picker), "changed",
367                         G_CALLBACK (_select_on_picker_changed_cb), dialog);
368   }
369
370   return TRUE;
371 }
372
373 gboolean
374 hildon_picker_dialog_set_picker (HildonPickerDialog * dialog,
375                                  HildonTouchPicker * picker)
376 {
377   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), FALSE);
378   g_return_val_if_fail (HILDON_IS_TOUCH_PICKER (picker), FALSE);
379
380   return HILDON_PICKER_DIALOG_GET_CLASS (dialog)->set_picker (dialog, picker);
381 }
382
383 HildonTouchPicker *
384 hildon_picker_dialog_get_picker (HildonPickerDialog * dialog)
385 {
386   g_return_val_if_fail (HILDON_IS_PICKER_DIALOG (dialog), NULL);
387
388   return HILDON_TOUCH_PICKER (dialog->priv->picker);
389 }