2 * This file is a part of hildon
4 * Copyright (C) 2008 Nokia Corporation, all rights reserved.
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.
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.
18 * SECTION:hildon-picker-button
19 * @short_description: A button that launches a #HildonPickerDialog and displays the
21 * @see_also: #HildonTouchSelector, #HildonPickerDialog
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.
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.
36 * create_selector (void)
38 * GtkWidget *selector;
40 * selector = hildon_touch_selector_new_text ();
42 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "America");
43 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Europe");
44 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Asia");
45 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Africa");
46 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Australia");
48 * hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, 2);
54 * create_button (HildonTouchSelector *selector)
58 * button = hildon_picker_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
59 * hildon_button_set_title (HILDON_BUTTON (button), "Continent");
61 * hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
62 * HILDON_TOUCH_SELECTOR (selector));
70 #include "hildon-picker-button.h"
71 #include "hildon-picker-dialog.h"
73 G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON)
75 #define GET_PRIVATE(o) \
76 (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate))
78 typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate;
80 struct _HildonPickerButtonPrivate
84 gchar *done_button_text;
100 static guint picker_button_signals[LAST_SIGNAL] = { 0 };
103 _current_selector_empty (HildonPickerButton *button);
106 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
111 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
116 hildon_picker_button_get_property (GObject * object, guint property_id,
117 GValue * value, GParamSpec * pspec)
119 switch (property_id) {
121 g_value_set_object (value,
122 hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object)));
124 case PROP_DONE_BUTTON_TEXT:
125 g_value_set_string (value,
126 hildon_picker_button_get_done_button_text (HILDON_PICKER_BUTTON (object)));
129 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
134 hildon_picker_button_set_property (GObject * object, guint property_id,
135 const GValue * value, GParamSpec * pspec)
137 switch (property_id) {
139 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object),
140 g_value_get_object (value));
142 case PROP_DONE_BUTTON_TEXT:
143 hildon_picker_button_set_done_button_text (HILDON_PICKER_BUTTON (object),
144 g_value_get_string (value));
147 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
152 hildon_picker_button_finalize (GObject * object)
154 HildonPickerButtonPrivate *priv;
156 priv = GET_PRIVATE (object);
158 if (priv->selector) {
159 g_signal_handlers_disconnect_by_func (priv->selector,
160 hildon_picker_button_selector_selection_changed,
162 g_signal_handlers_disconnect_by_func (priv->selector,
163 hildon_picker_button_selector_columns_changed,
165 g_object_unref (priv->selector);
166 priv->selector = NULL;
169 gtk_widget_destroy (priv->dialog);
173 if (priv->done_button_text) {
174 g_free (priv->done_button_text);
175 priv->done_button_text = NULL;
178 G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object);
182 _selection_changed (HildonPickerButton *button)
184 HildonPickerButtonPrivate *priv = GET_PRIVATE (button);
186 if (!GTK_IS_WINDOW (priv->dialog) ||
187 !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) {
188 gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
190 hildon_button_set_value (HILDON_BUTTON (button), value);
192 g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0);
198 hildon_picker_button_on_dialog_response (GtkDialog *dialog,
202 gtk_widget_hide (GTK_WIDGET (dialog));
204 if (response == GTK_RESPONSE_OK) {
205 _selection_changed (HILDON_PICKER_BUTTON (user_data));
210 hildon_picker_button_clicked (GtkButton * button)
213 HildonPickerButtonPrivate *priv;
215 priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
217 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector));
219 /* Create the dialog if it doesn't exist already. */
221 parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
222 if (GTK_WIDGET_TOPLEVEL (parent)) {
223 priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent));
225 priv->dialog = hildon_picker_dialog_new (NULL);
228 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog),
229 HILDON_TOUCH_SELECTOR (priv->selector));
230 if (priv->done_button_text) {
231 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
232 priv->done_button_text);
235 gtk_window_set_modal (GTK_WINDOW (priv->dialog),
236 gtk_window_get_modal (GTK_WINDOW (parent)));
237 gtk_window_set_title (GTK_WINDOW (priv->dialog),
238 hildon_button_get_title (HILDON_BUTTON (button)));
239 g_signal_connect (priv->dialog, "response",
240 G_CALLBACK (hildon_picker_button_on_dialog_response),
242 g_signal_connect (priv->dialog, "delete-event",
243 G_CALLBACK (gtk_widget_hide_on_delete),
247 if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) {
248 g_warning ("There are no elements in the selector. Nothing to show.");
250 gtk_window_present (GTK_WINDOW (priv->dialog));
255 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
260 _selection_changed (HILDON_PICKER_BUTTON (user_data));
264 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
268 _selection_changed (HILDON_PICKER_BUTTON (user_data));
272 hildon_picker_button_class_init (HildonPickerButtonClass * klass)
274 GObjectClass *object_class = G_OBJECT_CLASS (klass);
275 GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
277 g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate));
279 object_class->get_property = hildon_picker_button_get_property;
280 object_class->set_property = hildon_picker_button_set_property;
281 object_class->finalize = hildon_picker_button_finalize;
283 button_class->clicked = hildon_picker_button_clicked;
285 g_object_class_install_property (object_class,
287 g_param_spec_object ("touch-selector",
288 "HildonTouchSelector widget",
289 "HildonTouchSelector widget to be launched on button clicked",
290 HILDON_TYPE_TOUCH_SELECTOR,
292 g_object_class_install_property (object_class,
293 PROP_DONE_BUTTON_TEXT,
294 g_param_spec_string ("done-button-text",
295 "HildonPickerDialog \"done\" button text",
296 "The text for the \"done\" button in the dialog launched",
301 * HildonPickerButton::value-changed:
302 * @widget: the widget that received the signal
304 * The ::value-changed signal is emitted each time the user chooses a different
305 * item from the #HildonTouchSelector related, and the value label gets updated.
309 picker_button_signals[VALUE_CHANGED] =
310 g_signal_new ("value-changed",
311 G_TYPE_FROM_CLASS (klass),
312 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
315 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
319 hildon_picker_button_init (HildonPickerButton * self)
321 HildonPickerButtonPrivate *priv;
323 priv = GET_PRIVATE (self);
326 priv->selector = NULL;
327 priv->done_button_text = NULL;
329 hildon_button_set_style (HILDON_BUTTON (self),
330 HILDON_BUTTON_STYLE_PICKER);
334 _current_selector_empty (HildonPickerButton *button)
336 HildonPickerButtonPrivate *priv;
337 HildonTouchSelector *selector = NULL;
338 GtkTreeModel *model = NULL;
342 priv = GET_PRIVATE (button);
343 selector = HILDON_TOUCH_SELECTOR (priv->selector);
345 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE);
347 if (hildon_touch_selector_has_multiple_selection (selector)) {
350 for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) {
351 model = hildon_touch_selector_get_model (selector, i);
353 if (gtk_tree_model_get_iter_first (model, &iter)) {
362 * hildon_picker_button_new:
363 * @size: One of #HildonSizeType, specifying the size of the new button.
364 * @arrangement: one of #HildonButtonArrangement, specifying the placement of the
367 * Creates a new #HildonPickerButton. See hildon_button_new() for details on the
370 * Returns: a newly created #HildonPickerButton
375 hildon_picker_button_new (HildonSizeType size,
376 HildonButtonArrangement arrangement)
380 button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
381 "arrangement", arrangement, "size", size,
388 * hildon_picker_button_set_selector:
389 * @button: a #HildonPickerButton
390 * @selector: a #HildonTouchSelector
392 * Sets @selector as the #HildonTouchSelector to be shown in the
393 * #HildonPickerDialog that @button brings up.
398 hildon_picker_button_set_selector (HildonPickerButton * button,
399 HildonTouchSelector * selector)
401 HildonPickerButtonPrivate *priv;
404 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
405 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
407 priv = GET_PRIVATE (button);
409 if (priv->selector) {
410 g_signal_handlers_disconnect_by_func (priv->selector,
411 hildon_picker_button_selector_selection_changed,
413 g_signal_handlers_disconnect_by_func (priv->selector,
414 hildon_picker_button_selector_columns_changed,
416 g_object_unref (priv->selector);
419 priv->selector = g_object_ref (selector);
421 g_signal_connect (G_OBJECT (selector), "changed",
422 G_CALLBACK (hildon_picker_button_selector_selection_changed),
425 g_signal_connect (G_OBJECT (selector), "columns-changed",
426 G_CALLBACK (hildon_picker_button_selector_columns_changed),
429 value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
431 hildon_button_set_value (HILDON_BUTTON (button), value);
433 g_signal_emit (HILDON_PICKER_BUTTON (button),
434 picker_button_signals[VALUE_CHANGED], 0);
439 * hildon_picker_button_get_selector:
440 * @button: a #HildonPickerButton
442 * Retrieves the #HildonTouchSelector associated to @button.
444 * Returns: a #HildonTouchSelector
448 HildonTouchSelector *
449 hildon_picker_button_get_selector (HildonPickerButton * button)
451 HildonPickerButtonPrivate *priv;
453 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
455 priv = GET_PRIVATE (button);
457 return HILDON_TOUCH_SELECTOR (priv->selector);
461 * hildon_picker_button_get_active:
462 * @button: a #HildonPickerButton
464 * Returns the index of the currently active item, or -1 if there's no
465 * active item. If the selector has several columns, only the first
468 * Returns: an integer which is the index of the currently active item, or -1 if there's no active item.
473 hildon_picker_button_get_active (HildonPickerButton * button)
475 HildonTouchSelector *sel;
476 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1);
478 sel = hildon_picker_button_get_selector (button);
480 return hildon_touch_selector_get_active (sel, 0);
484 * hildon_picker_button_set_active:
485 * @button: a #HildonPickerButton
486 * @index: the index of the item to select, or -1 to have no active item
488 * Sets the active item of the #HildonTouchSelector associated to
489 * @button to @index. If the selector has several columns, only the
495 hildon_picker_button_set_active (HildonPickerButton * button,
498 HildonTouchSelector *sel;
500 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
502 sel = hildon_picker_button_get_selector (button);
503 hildon_touch_selector_set_active (sel, 0, index);
505 text = hildon_touch_selector_get_current_text (sel);
506 hildon_button_set_value (HILDON_BUTTON (button), text);
511 * hildon_picker_button_get_done_button_text:
512 * @button: a #HildonPickerButton
514 * Gets the text used in the #HildonPickerDialog that is launched by
515 * @button. If no custom text is set, then %NULL is returned.
517 * Returns: the custom string to be used, or %NULL if the default
518 * #HildonPickerDialog::done-button-text is to be used.
523 hildon_picker_button_get_done_button_text (HildonPickerButton *button)
525 HildonPickerButtonPrivate *priv;
527 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
529 priv = GET_PRIVATE (button);
531 return priv->done_button_text;
535 * hildon_picker_button_set_done_button_text:
536 * @button: a #HildonPickerButton
537 * @done_button_text: a string
539 * Sets a custom string to be used in the "done" button in #HildonPickerDialog.
540 * If unset, the default HildonPickerButton::done-button-text property
541 * value will be used.
546 hildon_picker_button_set_done_button_text (HildonPickerButton *button,
547 const gchar *done_button_text)
549 HildonPickerButtonPrivate *priv;
551 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
552 g_return_if_fail (done_button_text != NULL);
554 priv = GET_PRIVATE (button);
556 g_free (priv->done_button_text);
557 priv->done_button_text = g_strdup (done_button_text);
560 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
561 priv->done_button_text);