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
193 hildon_picker_button_value_changed (HildonPickerButton *button)
195 HildonPickerButtonPrivate *priv;
196 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
197 priv = GET_PRIVATE (button);
199 if (!priv->disable_value_changed)
200 g_signal_emit (button, picker_button_signals[VALUE_CHANGED], 0);
204 hildon_picker_button_disable_value_changed (HildonPickerButton *button,
207 HildonPickerButtonPrivate *priv;
208 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
209 priv = GET_PRIVATE (button);
211 priv->disable_value_changed = disable;
215 _selection_changed (HildonPickerButton *button)
217 HildonPickerButtonPrivate *priv = GET_PRIVATE (button);
219 if (!GTK_IS_WINDOW (priv->dialog) ||
220 !GTK_WIDGET_VISIBLE (GTK_WINDOW (priv->dialog))) {
221 gchar *value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
223 hildon_button_set_value (HILDON_BUTTON (button), value);
225 hildon_picker_button_value_changed (button);
231 hildon_picker_button_on_dialog_response (GtkDialog *dialog,
235 HildonPickerButton *button;
236 HildonPickerButtonPrivate *priv;
239 button = HILDON_PICKER_BUTTON (user_data);
240 priv = GET_PRIVATE (button);
242 if (response == GTK_RESPONSE_OK) {
243 value = hildon_touch_selector_get_current_text
244 (HILDON_TOUCH_SELECTOR (priv->selector));
245 hildon_button_set_value (HILDON_BUTTON (button), value);
247 hildon_picker_button_value_changed (button);
250 gtk_widget_hide (GTK_WIDGET (dialog));
254 hildon_picker_button_clicked (GtkButton * button)
257 HildonPickerButtonPrivate *priv;
259 priv = GET_PRIVATE (HILDON_PICKER_BUTTON (button));
261 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (priv->selector));
263 /* Create the dialog if it doesn't exist already. */
265 parent = gtk_widget_get_toplevel (GTK_WIDGET (button));
266 if (GTK_WIDGET_TOPLEVEL (parent)) {
267 priv->dialog = hildon_picker_dialog_new (GTK_WINDOW (parent));
269 priv->dialog = hildon_picker_dialog_new (NULL);
272 hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (priv->dialog),
273 HILDON_TOUCH_SELECTOR (priv->selector));
274 if (priv->done_button_text) {
275 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
276 priv->done_button_text);
279 gtk_window_set_modal (GTK_WINDOW (priv->dialog),
280 gtk_window_get_modal (GTK_WINDOW (parent)));
281 gtk_window_set_title (GTK_WINDOW (priv->dialog),
282 hildon_button_get_title (HILDON_BUTTON (button)));
283 g_signal_connect (priv->dialog, "response",
284 G_CALLBACK (hildon_picker_button_on_dialog_response),
286 g_signal_connect (priv->dialog, "delete-event",
287 G_CALLBACK (gtk_widget_hide_on_delete),
291 if (_current_selector_empty (HILDON_PICKER_BUTTON (button))) {
292 g_warning ("There are no elements in the selector. Nothing to show.");
294 gtk_window_present (GTK_WINDOW (priv->dialog));
299 hildon_picker_button_selector_selection_changed (HildonTouchSelector * selector,
304 _selection_changed (HILDON_PICKER_BUTTON (user_data));
308 hildon_picker_button_selector_columns_changed (HildonTouchSelector * selector,
312 _selection_changed (HILDON_PICKER_BUTTON (user_data));
316 hildon_picker_button_class_init (HildonPickerButtonClass * klass)
318 GObjectClass *object_class = G_OBJECT_CLASS (klass);
319 GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
321 g_type_class_add_private (klass, sizeof (HildonPickerButtonPrivate));
323 object_class->get_property = hildon_picker_button_get_property;
324 object_class->set_property = hildon_picker_button_set_property;
325 object_class->finalize = hildon_picker_button_finalize;
327 button_class->clicked = hildon_picker_button_clicked;
329 g_object_class_install_property (object_class,
331 g_param_spec_object ("touch-selector",
332 "HildonTouchSelector widget",
333 "HildonTouchSelector widget to be launched on button clicked",
334 HILDON_TYPE_TOUCH_SELECTOR,
336 g_object_class_install_property (object_class,
337 PROP_DONE_BUTTON_TEXT,
338 g_param_spec_string ("done-button-text",
339 "HildonPickerDialog \"done\" button text",
340 "The text for the \"done\" button in the dialog launched",
345 * HildonPickerButton::value-changed:
346 * @widget: the widget that received the signal
348 * The ::value-changed signal is emitted each time the user chooses a different
349 * item from the #HildonTouchSelector related, and the value label gets updated.
353 picker_button_signals[VALUE_CHANGED] =
354 g_signal_new ("value-changed",
355 G_TYPE_FROM_CLASS (klass),
356 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
359 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, NULL);
363 hildon_picker_button_init (HildonPickerButton * self)
365 HildonPickerButtonPrivate *priv;
367 priv = GET_PRIVATE (self);
370 priv->selector = NULL;
371 priv->done_button_text = NULL;
372 priv->disable_value_changed = FALSE;
374 hildon_button_set_style (HILDON_BUTTON (self),
375 HILDON_BUTTON_STYLE_PICKER);
379 _current_selector_empty (HildonPickerButton *button)
381 HildonPickerButtonPrivate *priv;
382 HildonTouchSelector *selector = NULL;
383 GtkTreeModel *model = NULL;
387 priv = GET_PRIVATE (button);
388 selector = HILDON_TOUCH_SELECTOR (priv->selector);
390 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), TRUE);
392 if (hildon_touch_selector_has_multiple_selection (selector)) {
395 for (i=0; i < hildon_touch_selector_get_num_columns (selector); i++) {
396 model = hildon_touch_selector_get_model (selector, i);
398 if (gtk_tree_model_get_iter_first (model, &iter)) {
407 * hildon_picker_button_new:
408 * @size: One of #HildonSizeType, specifying the size of the new button.
409 * @arrangement: one of #HildonButtonArrangement, specifying the placement of the
412 * Creates a new #HildonPickerButton. See hildon_button_new() for details on the
415 * Returns: a newly created #HildonPickerButton
420 hildon_picker_button_new (HildonSizeType size,
421 HildonButtonArrangement arrangement)
425 button = g_object_new (HILDON_TYPE_PICKER_BUTTON,
426 "arrangement", arrangement, "size", size,
433 * hildon_picker_button_set_selector:
434 * @button: a #HildonPickerButton
435 * @selector: a #HildonTouchSelector
437 * Sets @selector as the #HildonTouchSelector to be shown in the
438 * #HildonPickerDialog that @button brings up.
443 hildon_picker_button_set_selector (HildonPickerButton * button,
444 HildonTouchSelector * selector)
446 HildonPickerButtonPrivate *priv;
449 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
450 g_return_if_fail (!selector || HILDON_IS_TOUCH_SELECTOR (selector));
452 priv = GET_PRIVATE (button);
454 if (priv->selector) {
455 g_signal_handlers_disconnect_by_func (priv->selector,
456 hildon_picker_button_selector_selection_changed,
458 g_signal_handlers_disconnect_by_func (priv->selector,
459 hildon_picker_button_selector_columns_changed,
461 g_object_unref (priv->selector);
464 priv->selector = GTK_WIDGET (selector);
467 g_object_ref (selector);
469 g_signal_connect (G_OBJECT (selector), "changed",
470 G_CALLBACK (hildon_picker_button_selector_selection_changed),
473 g_signal_connect (G_OBJECT (selector), "columns-changed",
474 G_CALLBACK (hildon_picker_button_selector_columns_changed),
477 value = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (priv->selector));
481 value = g_strdup ("");
483 hildon_button_set_value (HILDON_BUTTON (button), value);
484 hildon_picker_button_value_changed (button);
490 * hildon_picker_button_get_selector:
491 * @button: a #HildonPickerButton
493 * Retrieves the #HildonTouchSelector associated to @button.
495 * Returns: a #HildonTouchSelector
499 HildonTouchSelector *
500 hildon_picker_button_get_selector (HildonPickerButton * button)
502 HildonPickerButtonPrivate *priv;
504 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
506 priv = GET_PRIVATE (button);
508 return HILDON_TOUCH_SELECTOR (priv->selector);
512 * hildon_picker_button_get_active:
513 * @button: a #HildonPickerButton
515 * Returns the index of the currently active item, or -1 if there's no
516 * active item. If the selector has several columns, only the first
519 * Returns: an integer which is the index of the currently active item, or -1 if there's no active item.
524 hildon_picker_button_get_active (HildonPickerButton * button)
526 HildonTouchSelector *sel;
527 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), -1);
529 sel = hildon_picker_button_get_selector (button);
531 return hildon_touch_selector_get_active (sel, 0);
535 * hildon_picker_button_set_active:
536 * @button: a #HildonPickerButton
537 * @index: the index of the item to select, or -1 to have no active item
539 * Sets the active item of the #HildonTouchSelector associated to
540 * @button to @index. If the selector has several columns, only the
546 hildon_picker_button_set_active (HildonPickerButton * button,
549 HildonTouchSelector *sel;
551 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
553 sel = hildon_picker_button_get_selector (button);
554 hildon_touch_selector_set_active (sel, 0, index);
556 text = hildon_touch_selector_get_current_text (sel);
557 hildon_button_set_value (HILDON_BUTTON (button), text);
562 * hildon_picker_button_get_done_button_text:
563 * @button: a #HildonPickerButton
565 * Gets the text used in the #HildonPickerDialog that is launched by
566 * @button. If no custom text is set, then %NULL is returned.
568 * Returns: the custom string to be used, or %NULL if the default
569 * #HildonPickerDialog::done-button-text is to be used.
574 hildon_picker_button_get_done_button_text (HildonPickerButton *button)
576 HildonPickerButtonPrivate *priv;
578 g_return_val_if_fail (HILDON_IS_PICKER_BUTTON (button), NULL);
580 priv = GET_PRIVATE (button);
582 return priv->done_button_text;
586 * hildon_picker_button_set_done_button_text:
587 * @button: a #HildonPickerButton
588 * @done_button_text: a string
590 * Sets a custom string to be used in the "done" button in #HildonPickerDialog.
591 * If unset, the default HildonPickerButton::done-button-text property
592 * value will be used.
597 hildon_picker_button_set_done_button_text (HildonPickerButton *button,
598 const gchar *done_button_text)
600 HildonPickerButtonPrivate *priv;
602 g_return_if_fail (HILDON_IS_PICKER_BUTTON (button));
603 g_return_if_fail (done_button_text != NULL);
605 priv = GET_PRIVATE (button);
607 g_free (priv->done_button_text);
608 priv->done_button_text = g_strdup (done_button_text);
611 hildon_picker_dialog_set_done_label (HILDON_PICKER_DIALOG (priv->dialog),
612 priv->done_button_text);