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-button-private.h"
72 #include "hildon-picker-dialog.h"
74 G_DEFINE_TYPE (HildonPickerButton, hildon_picker_button, HILDON_TYPE_BUTTON)
76 #define GET_PRIVATE(o) \
77 (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_PICKER_BUTTON, HildonPickerButtonPrivate))
79 typedef struct _HildonPickerButtonPrivate HildonPickerButtonPrivate;
81 struct _HildonPickerButtonPrivate
85 gchar *done_button_text;
86 guint disable_value_changed : 1;
102 static guint picker_button_signals[LAST_SIGNAL] = { 0 };
105 _current_selector_empty (HildonPickerButton *button);
108 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
113 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
118 hildon_picker_button_get_property (GObject * object, guint property_id,
119 GValue * value, GParamSpec * pspec)
121 switch (property_id) {
123 g_value_set_object (value,
124 hildon_picker_button_get_selector (HILDON_PICKER_BUTTON (object)));
126 case PROP_DONE_BUTTON_TEXT:
127 g_value_set_string (value,
128 hildon_picker_button_get_done_button_text (HILDON_PICKER_BUTTON (object)));
131 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
136 hildon_picker_button_set_property (GObject * object, guint property_id,
137 const GValue * value, GParamSpec * pspec)
139 switch (property_id) {
141 hildon_picker_button_set_selector (HILDON_PICKER_BUTTON (object),
142 g_value_get_object (value));
144 case PROP_DONE_BUTTON_TEXT:
145 hildon_picker_button_set_done_button_text (HILDON_PICKER_BUTTON (object),
146 g_value_get_string (value));
149 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
154 hildon_picker_button_finalize (GObject * object)
156 HildonPickerButtonPrivate *priv;
158 priv = GET_PRIVATE (object);
160 if (priv->selector) {
161 g_signal_handlers_disconnect_by_func (priv->selector,
162 hildon_picker_button_selector_selection_changed,
164 g_signal_handlers_disconnect_by_func (priv->selector,
165 hildon_picker_button_selector_columns_changed,
167 g_object_unref (priv->selector);
168 priv->selector = NULL;
171 gtk_widget_destroy (priv->dialog);
175 if (priv->done_button_text) {
176 g_free (priv->done_button_text);
177 priv->done_button_text = NULL;
180 G_OBJECT_CLASS (hildon_picker_button_parent_class)->finalize (object);
184 * hildon_picker_button_value_changed:
185 * @button: a #HildonPickerButton
187 * Emits a "#HildonPickerButton::value-changed" signal to the given
188 * #HildonPickerButton
191 hildon_picker_button_value_changed (HildonPickerButton *button)
193 HildonPickerButtonPrivate *priv;
194 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
195 priv = GET_PRIVATE (button);
197 if (!priv->disable_value_changed)
198 g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0);
202 hildon_picker_button_disable_value_changed (HildonPickerButton *button,
205 HildonPickerButtonPrivate *priv;
206 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
207 priv = GET_PRIVATE (button);
209 priv->disable_value_changed = disable;
213 _selection_changed (HildonPickerButton *button)
215 HildonPickerButtonPrivate *priv = GET_PRIVATE (button);
217 if (!GTK_IS_WINDOW (priv->dialog) ||
218 !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) {
219 gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
221 hildon_button_set_value (HILDON_BUTTON (button), value);
223 hildon_picker_button_value_changed (button);
229 hildon_picker_button_on_dialog_response (GtkDialog *dialog,
233 HildonPickerButton *button;
234 HildonPickerButtonPrivate *priv;
237 button = HILDON_PICKER_BUTTON (user_data);
238 priv = GET_PRIVATE (button);
240 if (response == GTK_RESPONSE_OK) {
241 value = hildon_touch_selector_get_current_text
242 (HILDON_TOUCH_SELECTOR (priv->selector));
243 hildon_button_set_value (HILDON_BUTTON (button), value);
245 hildon_picker_button_value_changed (button);
248 gtk_widget_hide (GTK_WIDGET (dialog));
252 hildon_picker_button_clicked (GtkButton * button)
255 HildonPickerButtonPrivate *priv;
257 priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
259 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector));
261 /* Create the dialog if it doesn't exist already. */
263 parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
264 if (GTK_WIDGET_TOPLEVEL (parent)) {
265 priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent));
267 priv->dialog = hildon_picker_dialog_new (NULL);
270 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog),
271 HILDON_TOUCH_SELECTOR (priv->selector));
272 if (priv->done_button_text) {
273 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
274 priv->done_button_text);
277 gtk_window_set_modal (GTK_WINDOW (priv->dialog),
278 gtk_window_get_modal (GTK_WINDOW (parent)));
279 gtk_window_set_title (GTK_WINDOW (priv->dialog),
280 hildon_button_get_title (HILDON_BUTTON (button)));
281 g_signal_connect (priv->dialog, "response",
282 G_CALLBACK (hildon_picker_button_on_dialog_response),
284 g_signal_connect (priv->dialog, "delete-event",
285 G_CALLBACK (gtk_widget_hide_on_delete),
289 if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) {
290 g_warning ("There are no elements in the selector. Nothing to show.");
292 gtk_window_present (GTK_WINDOW (priv->dialog));
297 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
302 _selection_changed (HILDON_PICKER_BUTTON (user_data));
306 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
310 _selection_changed (HILDON_PICKER_BUTTON (user_data));
314 hildon_picker_button_class_init (HildonPickerButtonClass * klass)
316 GObjectClass *object_class = G_OBJECT_CLASS (klass);
317 GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
319 g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate));
321 object_class->get_property = hildon_picker_button_get_property;
322 object_class->set_property = hildon_picker_button_set_property;
323 object_class->finalize = hildon_picker_button_finalize;
325 button_class->clicked = hildon_picker_button_clicked;
327 g_object_class_install_property (object_class,
329 g_param_spec_object ("touch-selector",
330 "HildonTouchSelector widget",
331 "HildonTouchSelector widget to be launched on button clicked",
332 HILDON_TYPE_TOUCH_SELECTOR,
334 g_object_class_install_property (object_class,
335 PROP_DONE_BUTTON_TEXT,
336 g_param_spec_string ("done-button-text",
337 "HildonPickerDialog \"done\" button text",
338 "The text for the \"done\" button in the dialog launched",
343 * HildonPickerButton::value-changed:
344 * @widget: the widget that received the signal
346 * The ::value-changed signal is emitted each time the user chooses a different
347 * item from the #HildonTouchSelector related, and the value label gets updated.
351 picker_button_signals[VALUE_CHANGED] =
352 g_signal_new ("value-changed",
353 G_TYPE_FROM_CLASS (klass),
354 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
357 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
361 hildon_picker_button_init (HildonPickerButton * self)
363 HildonPickerButtonPrivate *priv;
365 priv = GET_PRIVATE (self);
368 priv->selector = NULL;
369 priv->done_button_text = NULL;
370 priv->disable_value_changed = FALSE;
372 hildon_button_set_style (HILDON_BUTTON (self),
373 HILDON_BUTTON_STYLE_PICKER);
377 _current_selector_empty (HildonPickerButton *button)
379 HildonPickerButtonPrivate *priv;
380 HildonTouchSelector *selector = NULL;
381 GtkTreeModel *model = NULL;
385 priv = GET_PRIVATE (button);
386 selector = HILDON_TOUCH_SELECTOR (priv->selector);
388 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE);
390 if (hildon_touch_selector_has_multiple_selection (selector)) {
393 for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) {
394 model = hildon_touch_selector_get_model (selector, i);
396 if (gtk_tree_model_get_iter_first (model, &iter)) {
405 * hildon_picker_button_new:
406 * @size: One of #HildonSizeType, specifying the size of the new button.
407 * @arrangement: one of #HildonButtonArrangement, specifying the placement of the
410 * Creates a new #HildonPickerButton. See hildon_button_new() for details on the
413 * Returns: a newly created #HildonPickerButton
418 hildon_picker_button_new (HildonSizeType size,
419 HildonButtonArrangement arrangement)
423 button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
424 "arrangement", arrangement, "size", size,
431 * hildon_picker_button_set_selector:
432 * @button: a #HildonPickerButton
433 * @selector: a #HildonTouchSelector
435 * Sets @selector as the #HildonTouchSelector to be shown in the
436 * #HildonPickerDialog that @button brings up.
441 hildon_picker_button_set_selector (HildonPickerButton * button,
442 HildonTouchSelector * selector)
444 HildonPickerButtonPrivate *priv;
447 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
448 g_return_if_fail (!selector || HILDON_IS_TOUCH_SELECTOR (selector));
450 priv = GET_PRIVATE (button);
452 if (priv->selector) {
453 g_signal_handlers_disconnect_by_func (priv->selector,
454 hildon_picker_button_selector_selection_changed,
456 g_signal_handlers_disconnect_by_func (priv->selector,
457 hildon_picker_button_selector_columns_changed,
459 g_object_unref (priv->selector);
462 priv->selector = GTK_WIDGET (selector);
465 g_object_ref (selector);
467 g_signal_connect (G_OBJECT (selector), "changed",
468 G_CALLBACK (hildon_picker_button_selector_selection_changed),
471 g_signal_connect (G_OBJECT (selector), "columns-changed",
472 G_CALLBACK (hildon_picker_button_selector_columns_changed),
475 value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
479 value = g_strdup ("");
481 hildon_button_set_value (HILDON_BUTTON (button), value);
482 hildon_picker_button_value_changed (button);
488 * hildon_picker_button_get_selector:
489 * @button: a #HildonPickerButton
491 * Retrieves the #HildonTouchSelector associated to @button.
493 * Returns: a #HildonTouchSelector
497 HildonTouchSelector *
498 hildon_picker_button_get_selector (HildonPickerButton * button)
500 HildonPickerButtonPrivate *priv;
502 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
504 priv = GET_PRIVATE (button);
506 return HILDON_TOUCH_SELECTOR (priv->selector);
510 * hildon_picker_button_get_active:
511 * @button: a #HildonPickerButton
513 * Returns the index of the currently active item, or -1 if there's no
514 * active item. If the selector has several columns, only the first
517 * Returns: an integer which is the index of the currently active item, or -1 if there's no active item.
522 hildon_picker_button_get_active (HildonPickerButton * button)
524 HildonTouchSelector *sel;
525 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1);
527 sel = hildon_picker_button_get_selector (button);
529 return hildon_touch_selector_get_active (sel, 0);
533 * hildon_picker_button_set_active:
534 * @button: a #HildonPickerButton
535 * @index: the index of the item to select, or -1 to have no active item
537 * Sets the active item of the #HildonTouchSelector associated to
538 * @button to @index. If the selector has several columns, only the
544 hildon_picker_button_set_active (HildonPickerButton * button,
547 HildonTouchSelector *sel;
549 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
551 sel = hildon_picker_button_get_selector (button);
552 hildon_touch_selector_set_active (sel, 0, index);
554 text = hildon_touch_selector_get_current_text (sel);
555 hildon_button_set_value (HILDON_BUTTON (button), text);
560 * hildon_picker_button_get_done_button_text:
561 * @button: a #HildonPickerButton
563 * Gets the text used in the #HildonPickerDialog that is launched by
564 * @button. If no custom text is set, then %NULL is returned.
566 * Returns: the custom string to be used, or %NULL if the default
567 * #HildonPickerDialog::done-button-text is to be used.
572 hildon_picker_button_get_done_button_text (HildonPickerButton *button)
574 HildonPickerButtonPrivate *priv;
576 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
578 priv = GET_PRIVATE (button);
580 return priv->done_button_text;
584 * hildon_picker_button_set_done_button_text:
585 * @button: a #HildonPickerButton
586 * @done_button_text: a string
588 * Sets a custom string to be used in the "done" button in #HildonPickerDialog.
589 * If unset, the default HildonPickerButton::done-button-text property
590 * value will be used.
595 hildon_picker_button_set_done_button_text (HildonPickerButton *button,
596 const gchar *done_button_text)
598 HildonPickerButtonPrivate *priv;
600 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
601 g_return_if_fail (done_button_text != NULL);
603 priv = GET_PRIVATE (button);
605 g_free (priv->done_button_text);
606 priv->done_button_text = g_strdup (done_button_text);
609 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
610 priv->done_button_text);