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. The title of the dialog is
27 * taken from the button's main label (see hildon_button_get_title()).
29 * You should create your own #HildonTouchSelector at convenience and set it
30 * to the #HildonPickerButton with hildon_picker_button_set_selector(). For
31 * the common use cases of buttons to select date and time, you can use #HildonDateButton
32 * and #HildonTimeButton.
37 * create_selector (void)
39 * GtkWidget *selector;
41 * selector = hildon_touch_selector_new_text ();
43 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "America");
44 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Europe");
45 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Asia");
46 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Africa");
47 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), "Australia");
49 * hildon_touch_selector_set_active (HILDON_TOUCH_SELECTOR (selector), 0, 2);
55 * create_button (HildonTouchSelector *selector)
59 * button = hildon_picker_button_new (HILDON_SIZE_AUTO, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
60 * hildon_button_set_title (HILDON_BUTTON (button), "Continent");
62 * hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (button),
63 * HILDON_TOUCH_SELECTOR (selector));
71 #include "hildon-picker-button.h"
72 #include "hildon-picker-button-private.h"
73 #include "hildon-picker-dialog.h"
75 G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON)
77 #define GET_PRIVATE(o) \
78 (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate))
80 typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate;
82 struct _HildonPickerButtonPrivate
86 gchar *done_button_text;
87 guint disable_value_changed : 1;
100 PROP_DONE_BUTTON_TEXT
103 static guint picker_button_signals[LAST_SIGNAL] = { 0 };
106 _current_selector_empty (HildonPickerButton *button);
109 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
114 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
119 hildon_picker_button_get_property (GObject * object, guint property_id,
120 GValue * value, GParamSpec * pspec)
122 switch (property_id) {
124 g_value_set_object (value,
125 hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object)));
127 case PROP_DONE_BUTTON_TEXT:
128 g_value_set_string (value,
129 hildon_picker_button_get_done_button_text (HILDON_PICKER_BUTTON (object)));
132 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
137 hildon_picker_button_set_property (GObject * object, guint property_id,
138 const GValue * value, GParamSpec * pspec)
140 switch (property_id) {
142 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object),
143 g_value_get_object (value));
145 case PROP_DONE_BUTTON_TEXT:
146 hildon_picker_button_set_done_button_text (HILDON_PICKER_BUTTON (object),
147 g_value_get_string (value));
150 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
155 hildon_picker_button_finalize (GObject * object)
157 HildonPickerButtonPrivate *priv;
159 priv = GET_PRIVATE (object);
161 if (priv->selector) {
162 g_signal_handlers_disconnect_by_func (priv->selector,
163 hildon_picker_button_selector_selection_changed,
165 g_signal_handlers_disconnect_by_func (priv->selector,
166 hildon_picker_button_selector_columns_changed,
168 g_object_unref (priv->selector);
169 priv->selector = NULL;
172 gtk_widget_destroy (priv->dialog);
176 if (priv->done_button_text) {
177 g_free (priv->done_button_text);
178 priv->done_button_text = NULL;
181 G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object);
185 * hildon_picker_button_value_changed:
186 * @button: a #HildonPickerButton
188 * Emits a "#HildonPickerButton::value-changed" signal to the given
189 * #HildonPickerButton
194 hildon_picker_button_value_changed (HildonPickerButton *button)
196 HildonPickerButtonPrivate *priv;
197 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
198 priv = GET_PRIVATE (button);
200 if (!priv->disable_value_changed)
201 g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0);
205 hildon_picker_button_disable_value_changed (HildonPickerButton *button,
208 HildonPickerButtonPrivate *priv;
209 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
210 priv = GET_PRIVATE (button);
212 priv->disable_value_changed = disable;
216 _selection_changed (HildonPickerButton *button)
218 HildonPickerButtonPrivate *priv = GET_PRIVATE (button);
220 if (!GTK_IS_WINDOW (priv->dialog) ||
221 !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) {
222 gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
224 hildon_button_set_value (HILDON_BUTTON (button), value);
226 hildon_picker_button_value_changed (button);
232 hildon_picker_button_on_dialog_response (GtkDialog *dialog,
236 HildonPickerButton *button;
237 HildonPickerButtonPrivate *priv;
240 button = HILDON_PICKER_BUTTON (user_data);
241 priv = GET_PRIVATE (button);
243 if (response == GTK_RESPONSE_OK) {
244 value = hildon_touch_selector_get_current_text
245 (HILDON_TOUCH_SELECTOR (priv->selector));
246 hildon_button_set_value (HILDON_BUTTON (button), value);
248 hildon_picker_button_value_changed (button);
251 gtk_widget_hide (GTK_WIDGET (dialog));
255 hildon_picker_button_clicked (GtkButton * button)
258 HildonPickerButtonPrivate *priv;
260 priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
262 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector));
264 /* Create the dialog if it doesn't exist already. */
266 parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
267 if (GTK_WIDGET_TOPLEVEL (parent)) {
268 priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent));
270 priv->dialog = hildon_picker_dialog_new (NULL);
273 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog),
274 HILDON_TOUCH_SELECTOR (priv->selector));
275 if (priv->done_button_text) {
276 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
277 priv->done_button_text);
280 gtk_window_set_modal (GTK_WINDOW (priv->dialog),
281 gtk_window_get_modal (GTK_WINDOW (parent)));
282 gtk_window_set_title (GTK_WINDOW (priv->dialog),
283 hildon_button_get_title (HILDON_BUTTON (button)));
284 g_signal_connect (priv->dialog, "response",
285 G_CALLBACK (hildon_picker_button_on_dialog_response),
287 g_signal_connect (priv->dialog, "delete-event",
288 G_CALLBACK (gtk_widget_hide_on_delete),
292 if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) {
293 g_warning ("There are no elements in the selector. Nothing to show.");
295 gtk_window_present (GTK_WINDOW (priv->dialog));
300 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
305 _selection_changed (HILDON_PICKER_BUTTON (user_data));
309 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
313 _selection_changed (HILDON_PICKER_BUTTON (user_data));
317 hildon_picker_button_class_init (HildonPickerButtonClass * klass)
319 GObjectClass *object_class = G_OBJECT_CLASS (klass);
320 GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
322 g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate));
324 object_class->get_property = hildon_picker_button_get_property;
325 object_class->set_property = hildon_picker_button_set_property;
326 object_class->finalize = hildon_picker_button_finalize;
328 button_class->clicked = hildon_picker_button_clicked;
330 g_object_class_install_property (object_class,
332 g_param_spec_object ("touch-selector",
333 "HildonTouchSelector widget",
334 "HildonTouchSelector widget to be launched on button clicked",
335 HILDON_TYPE_TOUCH_SELECTOR,
337 g_object_class_install_property (object_class,
338 PROP_DONE_BUTTON_TEXT,
339 g_param_spec_string ("done-button-text",
340 "HildonPickerDialog \"done\" button text",
341 "The text for the \"done\" button in the dialog launched",
346 * HildonPickerButton::value-changed:
347 * @widget: the widget that received the signal
349 * The ::value-changed signal is emitted each time the user chooses a different
350 * item from the #HildonTouchSelector related, and the value label gets updated.
354 picker_button_signals[VALUE_CHANGED] =
355 g_signal_new ("value-changed",
356 G_TYPE_FROM_CLASS (klass),
357 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
360 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
364 hildon_picker_button_init (HildonPickerButton * self)
366 HildonPickerButtonPrivate *priv;
368 priv = GET_PRIVATE (self);
371 priv->selector = NULL;
372 priv->done_button_text = NULL;
373 priv->disable_value_changed = FALSE;
375 hildon_button_set_style (HILDON_BUTTON (self),
376 HILDON_BUTTON_STYLE_PICKER);
380 _current_selector_empty (HildonPickerButton *button)
382 HildonPickerButtonPrivate *priv;
383 HildonTouchSelector *selector = NULL;
384 GtkTreeModel *model = NULL;
388 priv = GET_PRIVATE (button);
389 selector = HILDON_TOUCH_SELECTOR (priv->selector);
391 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE);
393 if (hildon_touch_selector_has_multiple_selection (selector)) {
396 for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) {
397 model = hildon_touch_selector_get_model (selector, i);
399 if (gtk_tree_model_get_iter_first (model, &iter)) {
408 * hildon_picker_button_new:
409 * @size: One of #HildonSizeType, specifying the size of the new button.
410 * @arrangement: one of #HildonButtonArrangement, specifying the placement of the
413 * Creates a new #HildonPickerButton. See hildon_button_new() for details on the
416 * Returns: a newly created #HildonPickerButton
421 hildon_picker_button_new (HildonSizeType size,
422 HildonButtonArrangement arrangement)
426 button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
427 "arrangement", arrangement, "size", size,
434 * hildon_picker_button_set_selector:
435 * @button: a #HildonPickerButton
436 * @selector: a #HildonTouchSelector
438 * Sets @selector as the #HildonTouchSelector to be shown in the
439 * #HildonPickerDialog that @button brings up.
444 hildon_picker_button_set_selector (HildonPickerButton * button,
445 HildonTouchSelector * selector)
447 HildonPickerButtonPrivate *priv;
450 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
451 g_return_if_fail (!selector || HILDON_IS_TOUCH_SELECTOR (selector));
453 priv = GET_PRIVATE (button);
455 if (priv->selector) {
456 g_signal_handlers_disconnect_by_func (priv->selector,
457 hildon_picker_button_selector_selection_changed,
459 g_signal_handlers_disconnect_by_func (priv->selector,
460 hildon_picker_button_selector_columns_changed,
462 g_object_unref (priv->selector);
465 priv->selector = GTK_WIDGET (selector);
468 g_object_ref (selector);
470 g_signal_connect (G_OBJECT (selector), "changed",
471 G_CALLBACK (hildon_picker_button_selector_selection_changed),
474 g_signal_connect (G_OBJECT (selector), "columns-changed",
475 G_CALLBACK (hildon_picker_button_selector_columns_changed),
478 value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
482 value = g_strdup ("");
484 hildon_button_set_value (HILDON_BUTTON (button), value);
485 hildon_picker_button_value_changed (button);
491 * hildon_picker_button_get_selector:
492 * @button: a #HildonPickerButton
494 * Retrieves the #HildonTouchSelector associated to @button.
496 * Returns: a #HildonTouchSelector
500 HildonTouchSelector *
501 hildon_picker_button_get_selector (HildonPickerButton * button)
503 HildonPickerButtonPrivate *priv;
505 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
507 priv = GET_PRIVATE (button);
509 return HILDON_TOUCH_SELECTOR (priv->selector);
513 * hildon_picker_button_get_active:
514 * @button: a #HildonPickerButton
516 * Returns the index of the currently active item, or -1 if there's no
517 * active item. If the selector has several columns, only the first
520 * Returns: an integer which is the index of the currently active item, or -1 if there's no active item.
525 hildon_picker_button_get_active (HildonPickerButton * button)
527 HildonTouchSelector *sel;
528 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1);
530 sel = hildon_picker_button_get_selector (button);
532 return hildon_touch_selector_get_active (sel, 0);
536 * hildon_picker_button_set_active:
537 * @button: a #HildonPickerButton
538 * @index: the index of the item to select, or -1 to have no active item
540 * Sets the active item of the #HildonTouchSelector associated to
541 * @button to @index. If the selector has several columns, only the
547 hildon_picker_button_set_active (HildonPickerButton * button,
550 HildonTouchSelector *sel;
552 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
554 sel = hildon_picker_button_get_selector (button);
555 hildon_touch_selector_set_active (sel, 0, index);
557 text = hildon_touch_selector_get_current_text (sel);
558 hildon_button_set_value (HILDON_BUTTON (button), text);
563 * hildon_picker_button_get_done_button_text:
564 * @button: a #HildonPickerButton
566 * Gets the text used in the #HildonPickerDialog that is launched by
567 * @button. If no custom text is set, then %NULL is returned.
569 * Returns: the custom string to be used, or %NULL if the default
570 * #HildonPickerDialog::done-button-text is to be used.
575 hildon_picker_button_get_done_button_text (HildonPickerButton *button)
577 HildonPickerButtonPrivate *priv;
579 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
581 priv = GET_PRIVATE (button);
583 return priv->done_button_text;
587 * hildon_picker_button_set_done_button_text:
588 * @button: a #HildonPickerButton
589 * @done_button_text: a string
591 * Sets a custom string to be used in the "done" button in #HildonPickerDialog.
592 * If unset, the default HildonPickerButton::done-button-text property
593 * value will be used.
598 hildon_picker_button_set_done_button_text (HildonPickerButton *button,
599 const gchar *done_button_text)
601 HildonPickerButtonPrivate *priv;
603 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
604 g_return_if_fail (done_button_text != NULL);
606 priv = GET_PRIVATE (button);
608 g_free (priv->done_button_text);
609 priv->done_button_text = g_strdup (done_button_text);
612 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
613 priv->done_button_text);