2 * This file is a part of hildon
4 * Copyright (C) 2005, 2008 Nokia Corporation.
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.
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.
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.
22 * SECTION:hildon-touch-selector
23 * @short_description: A selector widget with several columns.
25 * #HildonTouchSelector is a selector widget, that allows users to
26 * select items from one to many predefined lists. It is very similar
27 * to #GtkComboBox, but with several individual pannable columns.
29 * Normally, you would use #HildonTouchSelector together with a
30 * #HildonPickerDialog activated from a button. For the most common
31 * cases, you should use #HildonPickerButton.
33 * The composition of each column in the selector is represented by a
34 * #GtkTreeModel. To add a new column to a #HildonTouchSelector, use
35 * hildon_touch_selector_append_column(). If you want to add a
36 * text-only column, without special attributes, use
37 * hildon_touch_selector_append_text_column().
39 * It is highly recommended that you use only one column
40 * #HildonTouchSelector<!-- -->s.
41 * If you only need a text only, one column selector, you can create it with
42 * hildon_touch_selector_new_text() and populate with
43 * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(),
44 * and hildon_touch_selector_insert_text().
46 * If you need a selector widget that also accepts user inputs, you
47 * can use #HildonTouchSelectorEntry.
57 #include "hildon-gtk.h"
59 #include "hildon-pannable-area.h"
60 #include "hildon-touch-selector.h"
62 #define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \
63 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
65 G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX)
67 #define CENTER_ON_SELECTED_ITEM_DELAY 50
70 * Struct to maintain the data of each column. The columns are the elements
71 * of the widget that belongs properly to the selection behaviour. As
72 * the selector contents are arranged in a #GtkHBox, you can add more widgets, like buttons etc.
73 * between the columns, but this doesn't belongs to the selection
76 typedef struct _SelectorColumn SelectorColumn;
77 struct _SelectorColumn
79 HildonTouchSelector *parent; /* the selector that contains this column */
81 GtkTreeView *tree_view;
83 GtkWidget *panarea; /* the pannable widget */
86 struct _HildonTouchSelectorPrivate
88 GSList *columns; /* the selection columns */
89 GtkWidget *hbox; /* the container for the selector's columns */
91 HildonTouchSelectorPrintFunc print_func;
96 PROP_HAS_MULTIPLE_SELECTION = 1
105 static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 };
107 static void hildon_touch_selector_get_property (GObject * object,
109 GValue * value, GParamSpec * pspec);
112 static void hildon_touch_selector_map (GtkWidget * widget);
115 static void hildon_touch_selector_remove (GtkContainer * container,
117 /* private functions */
118 static void _selection_changed_cb (GtkTreeSelection * selection,
120 static gchar *_default_print_func (HildonTouchSelector * selector);
122 static SelectorColumn *_create_new_column (HildonTouchSelector * selector,
123 GtkTreeModel * model,
124 GtkCellRenderer * renderer,
126 static gboolean _hildon_touch_selector_center_on_selected_items (gpointer data);
129 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
130 gint num_column, GtkTreeModel * model);
132 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector);
135 hildon_touch_selector_class_init (HildonTouchSelectorClass * class)
137 GObjectClass *gobject_class;
138 GtkObjectClass *object_class;
139 GtkWidgetClass *widget_class;
140 GtkContainerClass *container_class;
142 gobject_class = (GObjectClass *) class;
143 object_class = (GtkObjectClass *) class;
144 widget_class = (GtkWidgetClass *) class;
145 container_class = (GtkContainerClass *) class;
149 gobject_class->get_property = hildon_touch_selector_get_property;
152 widget_class->map = hildon_touch_selector_map;
155 container_class->remove = hildon_touch_selector_remove;
157 /* HildonTouchSelector */
158 class->set_model = _hildon_touch_selector_set_model;
160 class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection;
164 * HildonTouchSelector::changed:
165 * @widget: the object which received the signal
167 * The changed signal is emitted when the active
168 * item is changed. This can be due to the user selecting
169 * a different item from the list, or due to a
170 * call to hildon_touch_selector_select_iter() on
171 * one of the columns.
174 hildon_touch_selector_signals[CHANGED] =
175 g_signal_new ("changed",
176 G_OBJECT_CLASS_TYPE (class),
178 G_STRUCT_OFFSET (HildonTouchSelectorClass, changed),
180 gtk_marshal_NONE__INT, G_TYPE_NONE, 1, G_TYPE_INT);
183 g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION,
184 g_param_spec_boolean ("has-multiple-selection",
185 "has multiple selection",
186 "Whether the widget has multiple "
187 "selection (like multiple columns, "
188 "multiselection mode, or multiple "
189 "internal widgets) and therefore "
190 "it may need a confirmation button, "
195 /* style properties */
196 /* We need to ensure fremantle mode for the treeview in order to work
197 properly. This is not about the appearance, this is about behaviour */
198 gtk_rc_parse_string ("style \"fremantle-htst\" {\n"
199 " GtkWidget::hildon-mode = 1\n"
200 "} widget \"*.fremantle-htst\" style \"fremantle-htst\""
201 "widget_class \"*<HildonPannableArea>.GtkTreeView\" style :highest \"fremantle-htst\"");
203 g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate));
207 hildon_touch_selector_get_property (GObject * object,
209 GValue * value, GParamSpec * pspec)
212 case PROP_HAS_MULTIPLE_SELECTION:
213 g_value_set_boolean (value,
214 hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object)));
217 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
223 hildon_touch_selector_init (HildonTouchSelector * selector)
225 selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
227 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
228 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
230 selector->priv->columns = NULL;
232 selector->priv->print_func = NULL;
233 selector->priv->hbox = gtk_hbox_new (FALSE, 0);
235 gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
237 gtk_widget_show (selector->priv->hbox);
239 /* FIXME: this is the correct height? A fixed height is the correct
241 gtk_widget_set_size_request (GTK_WIDGET (selector), -1, 320);
245 hildon_touch_selector_map (GtkWidget * widget)
247 GTK_WIDGET_CLASS (hildon_touch_selector_parent_class)->map (widget);
249 g_timeout_add (CENTER_ON_SELECTED_ITEM_DELAY,
250 _hildon_touch_selector_center_on_selected_items, widget);
253 /*------------------------------ GtkContainer ------------------------------ */
256 * Required in order to free the column at the columns list
259 hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
261 HildonTouchSelector *selector = NULL;
264 SelectorColumn *current_column = NULL;
265 gint num_columns = 0;
267 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container));
269 selector = HILDON_TOUCH_SELECTOR (container);
270 num_columns = hildon_touch_selector_get_num_columns (selector);
272 /* Check if the widget is inside a column and remove
274 iter = selector->priv->columns;
277 current_column = (SelectorColumn *) iter->data;
278 if (widget == current_column->panarea) {
279 current_column = g_slist_nth_data (selector->priv->columns, position);
281 selector->priv->columns = g_slist_remove (selector->priv->columns,
283 g_free (current_column);
289 iter = g_slist_next (iter);
291 if (position >= num_columns) {
292 g_debug ("This widget was not inside the selector column");
295 GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget);
298 /* ------------------------------ PRIVATE METHODS ---------------------------- */
300 * default_print_func:
301 * @selector: a #HildonTouchSelector
303 * Default print function
305 * Returns: a new string that represents the selected items
308 _default_print_func (HildonTouchSelector * selector)
310 gchar *result = NULL;
312 gint num_columns = 0;
314 GtkTreeModel *model = NULL;
315 gchar *current_string = NULL;
317 HildonTouchSelectorSelectionMode mode;
319 GtkTreePath *current_path = NULL;
320 GList *selected_rows = NULL;
321 gint initial_value = 0;
323 num_columns = hildon_touch_selector_get_num_columns (selector);
325 mode = hildon_touch_selector_get_column_selection_mode (selector);
327 if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
328 && (num_columns > 0)) {
329 /* In this case we get the first column first */
330 selected_rows = hildon_touch_selector_get_selected_rows (selector, 0);
331 model = hildon_touch_selector_get_model (selector, 0);
333 result = g_strdup_printf ("(");
335 for (item = selected_rows; item; item = g_list_next (item)) {
336 current_path = item->data;
337 gtk_tree_model_get_iter (model, &iter, current_path);
339 gtk_tree_model_get (model, &iter, 0, ¤t_string, -1);
341 if (i < g_list_length (selected_rows) - 1) {
342 aux = g_strconcat (result, current_string, ",", NULL);
346 aux = g_strconcat (result, current_string, NULL);
353 aux = g_strconcat (result, ")", NULL);
357 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
358 g_list_free (selected_rows);
364 for (i = initial_value; i < num_columns; i++) {
365 model = hildon_touch_selector_get_model (selector, i);
366 if (hildon_touch_selector_get_selected (selector, i, &iter)) {
368 gtk_tree_model_get (model, &iter, 0, ¤t_string, -1);
370 aux = g_strconcat (result, ":", current_string, NULL);
374 result = g_strdup_printf ("%s", current_string);
383 _selection_changed_cb (GtkTreeSelection * selection, gpointer user_data)
385 HildonTouchSelector *selector = NULL;
386 SelectorColumn *column = NULL;
387 gint num_column = -1;
389 column = (SelectorColumn *) user_data;
390 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->parent));
392 selector = column->parent;
394 num_column = g_slist_index (selector->priv->columns, column);
396 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, num_column);
400 static SelectorColumn *
401 _create_new_column (HildonTouchSelector * selector,
402 GtkTreeModel * model,
403 GtkCellRenderer * renderer, va_list args)
405 SelectorColumn *new_column = NULL;
406 GtkTreeViewColumn *tree_column = NULL;
407 GtkTreeView *tv = NULL;
408 GtkWidget *panarea = NULL;
409 GtkTreeSelection *selection = NULL;
414 tree_column = gtk_tree_view_column_new ();
415 gtk_tree_view_column_pack_start (tree_column, renderer, TRUE);
417 attribute = va_arg (args, gchar *);
418 while (attribute != NULL) {
419 value = va_arg (args, gint);
420 gtk_tree_view_column_add_attribute (tree_column, renderer, attribute,
422 attribute = va_arg (args, gchar *);
425 tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT));
426 gtk_tree_view_set_model (tv, model);
427 gtk_tree_view_set_rules_hint (tv, TRUE);
429 gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column);
431 new_column = (SelectorColumn *) g_malloc0 (sizeof (SelectorColumn));
432 new_column->parent = selector;
434 panarea = hildon_pannable_area_new ();
436 g_object_set (G_OBJECT (panarea), "vscrollbar-policy", GTK_POLICY_NEVER,
437 "initial-hint", FALSE, NULL);
439 gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv));
441 new_column->model = model;
442 new_column->tree_view = tv;
443 new_column->panarea = panarea;
445 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
446 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
448 /* select the first item */
449 if (gtk_tree_model_get_iter_first (model, &iter)) {
450 gtk_tree_selection_select_iter (selection, &iter);
453 gtk_widget_grab_focus (GTK_WIDGET (tv));
455 /* connect to the changed signal connection */
456 g_signal_connect (G_OBJECT (selection), "changed",
457 G_CALLBACK (_selection_changed_cb), new_column);
462 /* ------------------------------ PUBLIC METHODS ---------------------------- */
465 * hildon_touch_selector_new:
467 * Creates a new empty #HildonTouchSelector.
469 * Returns: a new #HildonTouchSelector.
472 hildon_touch_selector_new (void)
474 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL);
478 * hildon_touch_selector_new_text:
480 * Creates a #HildonTouchSelector with a single text column that
481 * can be populated conveniently through hildon_touch_selector_append_text(),
482 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
484 * Returns: A new #HildonTouchSelector
487 hildon_touch_selector_new_text (void)
492 selector = hildon_touch_selector_new ();
493 store = gtk_list_store_new (1, G_TYPE_STRING);
495 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
496 GTK_TREE_MODEL (store), TRUE);
502 * hildon_touch_selector_append_text:
503 * @selector: A #HildonTouchSelector.
504 * @text: a non %NULL text string.
506 * Appends a new entry in a #HildonTouchSelector created with
507 * hildon_touch_selector_new_text().
510 hildon_touch_selector_append_text (HildonTouchSelector * selector,
516 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
517 g_return_if_fail (text != NULL);
519 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
521 g_return_if_fail (GTK_IS_LIST_STORE (model));
523 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
524 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
528 * hildon_touch_selector_prepend_text:
529 * @selector: A #HildonTouchSelector.
530 * @text: a non %NULL text string.
532 * Prepends a new entry in a #HildonTouchSelector created with
533 * hildon_touch_selector_new_text().
536 hildon_touch_selector_prepend_text (HildonTouchSelector * selector,
542 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
543 g_return_if_fail (text != NULL);
545 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
547 g_return_if_fail (GTK_IS_LIST_STORE (model));
549 gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
550 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
554 * hildon_touch_selector_insert_text:
555 * @selector: a #HildonTouchSelector.
556 * @position: the position to insert @text.
557 * @text: A non %NULL text string.
559 * Inserts a new entry in particular position of a #HildoTouchSelector created
560 * with hildon_touch_selector_new_text().
564 hildon_touch_selector_insert_text (HildonTouchSelector * selector,
565 gint position, const gchar * text)
570 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
571 g_return_if_fail (text != NULL);
572 g_return_if_fail (position >= 0);
574 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
576 g_return_if_fail (GTK_IS_LIST_STORE (model));
578 gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position);
579 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
583 * hildon_touch_selector_append_column
584 * @selector: a #HildonTouchSelector
585 * @model: the #GtkTreeModel with the data of the column
586 * @cell_renderer: The #GtkCellRenderer where to draw each row contents.
587 * @Varargs: a %NULL-terminated pair of attributes and column numbers.
589 * This functions adds a new column to the widget, whose data will
590 * be obtained from the model. Only widgets added this way should used on
591 * the selection logic, i.e., the print function, the #HildonTouchPicker::changed
594 * Contents will be represented in @cell_renderer. You can pass a %NULL-terminated
595 * list of pairs property/value, in the same way you would use
596 * gtk_tree_view_column_set_attributes().
598 * There is a prerequisite to be considered on models used: text data must
599 * be in the first column.
601 * This method basically adds a #GtkTreeView to the widget, using the model and
604 * Returns: %TRUE if a new column was added, %FALSE otherwise
608 hildon_touch_selector_append_column (HildonTouchSelector * selector,
609 GtkTreeModel * model,
610 GtkCellRenderer * cell_renderer, ...)
613 SelectorColumn *new_column = NULL;
615 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
616 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
620 va_start (args, cell_renderer);
621 new_column = _create_new_column (selector, model, cell_renderer, args);
624 selector->priv->columns = g_slist_append (selector->priv->columns,
626 gtk_box_pack_start (GTK_BOX (selector->priv->hbox), new_column->panarea, TRUE, TRUE, 6);
628 gtk_widget_show_all (new_column->panarea);
637 * hildon_touch_selector_append_text_column
638 * @selector: a #HildonTouchSelector
639 * @model: a #GtkTreeModel with data for the column
640 * @center: whether to center the text on the column
642 * Equivalent to hildon_touch_selector_append_column(), but using a
643 * default text cell renderer. This is the most common use case of the
646 * Returns: %TRUE if a new column was added, %FALSE otherwise.
649 hildon_touch_selector_append_text_column (HildonTouchSelector * selector,
650 GtkTreeModel * model, gboolean center)
652 GtkCellRenderer *renderer = NULL;
655 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
656 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
659 renderer = gtk_cell_renderer_text_new ();
662 g_value_init (&val, G_TYPE_FLOAT);
663 g_value_set_float (&val, 0.5);
664 /* FIXME: center the text, this should be configurable */
665 g_object_set_property (G_OBJECT (renderer), "xalign", &val);
668 return hildon_touch_selector_append_column (selector, model, renderer,
676 * hildon_touch_selector_remove_column:
677 * @selector: a #HildonTouchSelector
678 * @column: the position of the column to be removed
680 * Removes a column from @selector.
682 * Returns: %TRUE if the column was removed, %FALSE otherwise
685 hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column)
687 SelectorColumn *current_column = NULL;
688 HildonTouchSelectorPrivate *priv;
690 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
691 g_return_val_if_fail (column <
692 hildon_touch_selector_get_num_columns (selector), FALSE);
694 priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
695 current_column = g_slist_nth_data (priv->columns, column);
697 gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->panarea);
698 priv->columns = g_slist_remove (priv->columns, current_column);
699 g_free (current_column);
705 * hildon_touch_selector_set_column_attributes:
706 * @selector: a #HildonTouchSelector
707 * @num_column: the number of the column whose attributes we're setting
708 * @cell_renderer: the #GtkCellRendere we're setting the attributes of
709 * @Varargs: A %NULL-terminated list of attributes.
711 * Sets the attributes for the given column. The attributes must be given
712 * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes().
713 * All existing attributes are removed and replaced with the new ones.
717 hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector,
719 GtkCellRenderer * cell_renderer,
723 GtkTreeViewColumn *tree_column = NULL;
724 SelectorColumn *current_column = NULL;
725 gchar *attribute = NULL;
728 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
729 g_return_if_fail (num_column <
730 hildon_touch_selector_get_num_columns (selector));
732 current_column = g_slist_nth_data (selector->priv->columns, num_column);
734 tree_column = gtk_tree_view_get_column (current_column->tree_view, 0);
735 gtk_tree_view_remove_column (current_column->tree_view, tree_column);
737 tree_column = gtk_tree_view_column_new ();
738 gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE);
740 va_start (args, cell_renderer);
741 attribute = va_arg (args, gchar *);
743 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
745 while (attribute != NULL) {
746 value = va_arg (args, gint);
747 gtk_tree_view_column_add_attribute (tree_column, cell_renderer,
749 attribute = va_arg (args, gchar *);
754 gtk_tree_view_append_column (current_column->tree_view, tree_column);
758 * hildon_touch_selector_get_num_columns:
759 * @selector: a #HildonTouchSelector
761 * Gets the number of columns in the #HildonTouchSelector.
763 * Returns: the number of columns in @selector.
766 hildon_touch_selector_get_num_columns (HildonTouchSelector * selector)
768 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
770 return g_slist_length (selector->priv->columns);
774 * hildon_touch_selector_get_column_selection_mode:
775 * @selector: a #HildonTouchSelector
777 * Gets the selection mode of @selector.
779 * Returns: one of #HildonTouchSelectorSelectionMode
781 HildonTouchSelectorSelectionMode
782 hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector)
784 HildonTouchSelectorSelectionMode result =
785 HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
786 GtkSelectionMode treeview_mode = GTK_SELECTION_SINGLE;
787 SelectorColumn *column = NULL;
788 GtkTreeSelection *selection = NULL;
790 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result);
791 g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0,
794 column = (SelectorColumn *) selector->priv->columns->data;
796 selection = gtk_tree_view_get_selection (column->tree_view);
797 treeview_mode = gtk_tree_selection_get_mode (selection);
800 if (treeview_mode == GTK_SELECTION_MULTIPLE) {
801 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE;
803 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
810 * hildon_touch_selector_set_column_selection_mode:
811 * @selector: a #HildonTouchSelector
812 * @mode: the #HildonTouchSelectorMode for @selector
814 * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode.
817 hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
818 HildonTouchSelectorSelectionMode mode)
820 GtkTreeView *tv = NULL;
821 SelectorColumn *column = NULL;
822 GtkTreeSelection *selection = NULL;
823 GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE;
826 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
827 g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0);
829 column = (SelectorColumn *) (g_slist_nth (selector->priv->columns, 0))->data;
830 tv = column->tree_view;
834 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE:
835 treeview_mode = GTK_SELECTION_SINGLE;
837 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE:
838 treeview_mode = GTK_SELECTION_MULTIPLE;
842 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
843 gtk_tree_selection_set_mode (selection, treeview_mode);
845 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
846 gtk_tree_model_get_iter_first (column->model, &iter);
847 gtk_tree_selection_unselect_all (selection);
848 gtk_tree_selection_select_iter (selection, &iter);
854 * hildon_touch_selector_set_print_func:
855 * @selector: a #HildonTouchSelector
856 * @func: a #HildonTouchSelectorPrintFunc function
858 * Sets the function to be used by hildon_touch_selector_get_current_text()
859 * to produce a text representation of the currently selected items in @selector.
860 * The default function will return a concatenation of comma separated items
861 * selected in each column in @selector. Use this to override this method if you
862 * need a particular representation for your application.
866 hildon_touch_selector_set_print_func (HildonTouchSelector * selector,
867 HildonTouchSelectorPrintFunc func)
869 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
871 selector->priv->print_func = func;
875 * hildon_touch_selector_get_print_func:
876 * @selector: a #HildonTouchSelector
878 * Gets the #HildonTouchSelectorPrintFunc currently used. See
879 * hildon_touch_selector_set_print_func().
881 * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default
882 * one is currently used.
884 HildonTouchSelectorPrintFunc
885 hildon_touch_selector_get_print_func (HildonTouchSelector * selector)
887 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
889 return selector->priv->print_func;
893 * hildon_touch_selector_set_active:
894 * @selector: a #HildonTouchSelector
895 * @column: column number
896 * @index: the index of the item to select, or -1 to have no active item
898 * Sets the active item of the #HildonTouchSelector to @index. The
899 * column number is taken from @column.
901 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
904 hildon_touch_selector_set_active (HildonTouchSelector *selector,
908 GtkTreeSelection *selection = NULL;
909 SelectorColumn *current_column = NULL;
910 HildonTouchSelectorSelectionMode mode;
913 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
914 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
915 mode = hildon_touch_selector_get_column_selection_mode (selector);
916 g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
918 current_column = g_slist_nth_data (selector->priv->columns, column);
920 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->tree_view));
921 path = gtk_tree_path_new_from_indices (index, -1);
922 gtk_tree_selection_unselect_all (selection);
924 gtk_tree_selection_select_path (selection, path);
926 gtk_tree_path_free (path);
930 * hildon_touch_selector_get_active:
931 * @selector: a #HildonTouchSelector
932 * @column: column number
934 * Returns the index of the currently active item in column number
935 * @column, or -1 if there's no active item.
937 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
939 * Returns: an integer which is the index of the currently active
940 * item, or -1 if there's no active item.
943 hildon_touch_selector_get_active (HildonTouchSelector *selector,
946 GtkTreeSelection *selection = NULL;
947 SelectorColumn *current_column = NULL;
948 HildonTouchSelectorSelectionMode mode;
954 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
955 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1);
956 mode = hildon_touch_selector_get_column_selection_mode (selector);
957 g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1);
959 current_column = g_slist_nth_data (selector->priv->columns, column);
961 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->tree_view));
962 model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_column->tree_view));
964 gtk_tree_selection_get_selected (selection, NULL, &iter);
965 path = gtk_tree_model_get_path (model, &iter);
966 index = (gtk_tree_path_get_indices (path))[0];
968 gtk_tree_path_free (path);
974 * hildon_touch_selector_get_selected:
975 * @selector: a #HildonTouchSelector
976 * @column: the column number we want to get the element
977 * @iter: #GtkTreeIter currently selected
979 * Sets @iter to the currently selected node on the nth-column, if selection is
980 * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with
981 * a column different that the first one. @iter may be %NULL if you just want to
982 * test if selection has any selected items.
984 * This function will not work if selection is in
985 * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one.
987 * See gtk_tree_selection_get_selected() for more information.
989 * Returns: %TRUE if @iter was correctly set, %FALSE otherwise
992 hildon_touch_selector_get_selected (HildonTouchSelector * selector,
993 gint column, GtkTreeIter * iter)
995 GtkTreeSelection *selection = NULL;
996 SelectorColumn *current_column = NULL;
997 HildonTouchSelectorSelectionMode mode;
999 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1000 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1002 mode = hildon_touch_selector_get_column_selection_mode (selector);
1003 g_return_val_if_fail
1004 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) ||
1005 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)),
1008 current_column = g_slist_nth_data (selector->priv->columns, column);
1011 gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->tree_view));
1013 return gtk_tree_selection_get_selected (selection, NULL, iter);
1017 * hildon_touch_selector_select_iter
1018 * @selector: a #HildonTouchSelector
1019 * @column: the column to selects
1020 * @iter: the #GtkTreeIter to be selected
1021 * @scroll_to: whether to smoothly scroll to the item
1023 * Sets the currently selected item in the column @column to the one pointed by @iter,
1024 * optionally smoothly scrolling to it.
1028 hildon_touch_selector_select_iter (HildonTouchSelector * selector,
1029 gint column, GtkTreeIter * iter,
1033 GtkTreeModel *model;
1035 SelectorColumn *current_column = NULL;
1036 GtkTreeSelection *selection = NULL;
1039 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1040 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1042 current_column = g_slist_nth_data (selector->priv->columns, column);
1044 selection = gtk_tree_view_get_selection (current_column->tree_view);
1045 model = gtk_tree_view_get_model (current_column->tree_view);
1046 path = gtk_tree_model_get_path (model, iter);
1048 gtk_tree_selection_select_iter (selection, iter);
1051 gtk_tree_view_get_background_area (current_column->tree_view,
1053 gtk_tree_view_convert_bin_window_to_tree_coords (current_column->tree_view,
1054 0, rect.y, NULL, &y);
1055 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (current_column->panarea),
1058 gtk_tree_path_free (path);
1062 * hildon_touch_selector_unselect_iter
1063 * @selector: a #HildonTouchSelector
1064 * @column: the column to unselects from
1065 * @iter: the #GtkTreeIter to be unselected
1067 * Unselect the item pointed by @iter in the column @column
1071 void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector,
1075 SelectorColumn *current_column = NULL;
1076 GtkTreeSelection *selection = NULL;
1078 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1079 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1081 current_column = g_slist_nth_data (selector->priv->columns, column);
1082 selection = gtk_tree_view_get_selection (current_column->tree_view);
1083 gtk_tree_selection_unselect_iter (selection, iter);
1087 * hildon_touch_selector_get_selected_rows:
1088 * @selector: a #HildonTouchSelector
1089 * @column: the position of the column to get the selected rows from
1091 * Creates a list of #GtkTreePath<!-- -->s of all selected rows in a column. Additionally,
1092 * if you to plan to modify the model after calling this function, you may
1093 * want to convert the returned list into a list of GtkTreeRowReferences. To do this,
1094 * you can use gtk_tree_row_reference_new().
1096 * See gtk_tree_selection_get_selected_rows() for more information.
1098 * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column.
1102 hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector,
1105 GList *result = NULL;
1106 SelectorColumn *current_column = NULL;
1107 GtkTreeSelection *selection = NULL;
1109 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1110 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1113 current_column = g_slist_nth_data (selector->priv->columns, column);
1114 selection = gtk_tree_view_get_selection (current_column->tree_view);
1116 result = gtk_tree_selection_get_selected_rows (selection, NULL);
1123 * hildon_touch_selector_get_model:
1124 * @selector: a #HildonTouchSelector
1125 * @column: the position of the column in @selector
1127 * Gets the model of a column of @selector.
1129 * Returns: the #GtkTreeModel for the column @column of @selector.
1132 hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column)
1134 SelectorColumn *current_column = NULL;
1136 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1137 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1140 current_column = g_slist_nth_data (selector->priv->columns, column);
1142 return current_column->model;
1146 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
1147 gint column, GtkTreeModel * model)
1149 SelectorColumn *current_column = NULL;
1152 (SelectorColumn *) g_slist_nth_data (selector->priv->columns, column);
1154 current_column->model = model;
1155 gtk_tree_view_set_model (current_column->tree_view, current_column->model);
1159 * hildon_touch_selector_set_model:
1160 * @selector: a #HildonTouchSelector
1161 * @column: the position of the column to set the model to
1162 * @model: a #GtkTreeModel
1164 * Sets the #GtkTreeModel for a particular column in @model.
1167 hildon_touch_selector_set_model (HildonTouchSelector * selector,
1168 gint column, GtkTreeModel * model)
1170 g_return_if_fail (HILDON_TOUCH_SELECTOR (selector));
1171 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1173 HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model);
1177 * hildon_touch_selector_get_current_text:
1178 * @selector: a #HildonTouchSelector
1180 * Returns a string representing the currently selected items for
1181 * each column of @selector. See hildon_touch_selector_set_print_func().
1183 * Returns: a newly allocated string.
1186 hildon_touch_selector_get_current_text (HildonTouchSelector * selector)
1188 gchar *result = NULL;
1189 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1191 if (selector->priv->print_func) {
1192 result = (*selector->priv->print_func) (selector);
1194 result = _default_print_func (selector);
1201 _hildon_touch_selector_center_on_selected_items (gpointer data)
1203 HildonTouchSelector *selector = NULL;
1204 SelectorColumn *column = NULL;
1205 GSList *iter_column = NULL;
1211 HildonTouchSelectorSelectionMode selection_mode;
1213 /* ensure to center on the initial values */
1214 selector = HILDON_TOUCH_SELECTOR (data);
1216 selection_mode = hildon_touch_selector_get_column_selection_mode (selector);
1218 iter_column = selector->priv->columns;
1220 while (iter_column) {
1221 column = (SelectorColumn *) iter_column->data;
1224 && (selection_mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)) {
1227 if (hildon_touch_selector_get_selected (selector, i, &iter)) {
1228 path = gtk_tree_model_get_path (column->model, &iter);
1229 gtk_tree_view_get_background_area (GTK_TREE_VIEW
1230 (column->tree_view), path, NULL,
1233 gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW
1234 (column->tree_view), 0,
1237 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA
1238 (column->panarea), -1, y);
1240 gtk_tree_path_free (path);
1242 iter_column = iter_column->next;
1250 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1252 HildonTouchSelectorSelectionMode mode = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1255 n_columns = hildon_touch_selector_get_num_columns (selector);
1256 mode = hildon_touch_selector_get_column_selection_mode (selector);
1258 return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE));
1262 * hildon_touch_selector_has_multiple_selection:
1263 * @selector: A #HildonTouchSelector
1265 * Determines whether @selector is complex enough to actually require an
1266 * extra selection step than only picking an item. This is normally %TRUE
1267 * if @selector has multiple columns, multiple selection, or when it is a
1268 * more complex widget, like %HildonTouchSelectorEntry.
1270 * This information is useful for widgets containing a %HildonTouchSelector,
1271 * like #HildonPickerDialog, that could need a "Done" button, in case that
1272 * its internal #HildonTouchSelector has multiple columns, for instance.
1274 * Returns: %TRUE if @selector requires multiple selection steps.
1277 hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1279 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1281 return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector);