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-pannable-area.h"
58 #include "hildon-touch-selector.h"
60 #define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \
61 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
63 G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX)
65 #define CENTER_ON_SELECTED_ITEM_DELAY 50
68 * Struct to maintain the data of each column. The columns are the elements
69 * of the widget that belongs properly to the selection behaviour. As
70 * the selector contents are arranged in a #GtkHBox, you can add more widgets, like buttons etc.
71 * between the columns, but this doesn't belongs to the selection
74 typedef struct _SelectorColumn SelectorColumn;
75 struct _SelectorColumn
77 HildonTouchSelector *parent; /* the selector that contains this column */
79 GtkTreeView *tree_view;
81 GtkWidget *panarea; /* the pannable widget */
84 struct _HildonTouchSelectorPrivate
86 GSList *columns; /* the selection columns */
87 GtkWidget *hbox; /* the container for the selector's columns */
89 HildonTouchSelectorPrintFunc print_func;
94 PROP_HAS_MULTIPLE_SELECTION = 1
103 static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 };
105 static void hildon_touch_selector_get_property (GObject * object,
107 GValue * value, GParamSpec * pspec);
110 static void hildon_touch_selector_map (GtkWidget * widget);
113 static void hildon_touch_selector_remove (GtkContainer * container,
115 /* private functions */
116 static void _selection_changed_cb (GtkTreeSelection * selection,
118 static gchar *_default_print_func (HildonTouchSelector * selector);
120 static SelectorColumn *_create_new_column (HildonTouchSelector * selector,
121 GtkTreeModel * model,
122 GtkCellRenderer * renderer,
124 static gboolean _hildon_touch_selector_center_on_selected_items (gpointer data);
127 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
128 gint num_column, GtkTreeModel * model);
130 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector);
133 hildon_touch_selector_class_init (HildonTouchSelectorClass * class)
135 GObjectClass *gobject_class;
136 GtkObjectClass *object_class;
137 GtkWidgetClass *widget_class;
138 GtkContainerClass *container_class;
140 gobject_class = (GObjectClass *) class;
141 object_class = (GtkObjectClass *) class;
142 widget_class = (GtkWidgetClass *) class;
143 container_class = (GtkContainerClass *) class;
147 gobject_class->get_property = hildon_touch_selector_get_property;
150 widget_class->map = hildon_touch_selector_map;
153 container_class->remove = hildon_touch_selector_remove;
155 /* HildonTouchSelector */
156 class->set_model = _hildon_touch_selector_set_model;
158 class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection;
162 * HildonTouchSelector::changed:
163 * @widget: the object which received the signal
165 * The changed signal is emitted when the active
166 * item is changed. This can be due to the user selecting
167 * a different item from the list, or due to a
168 * call to hildon_touch_selector_set_active_iter() on
169 * one of the columns.
172 hildon_touch_selector_signals[CHANGED] =
173 g_signal_new ("changed",
174 G_OBJECT_CLASS_TYPE (class),
176 G_STRUCT_OFFSET (HildonTouchSelectorClass, changed),
178 gtk_marshal_NONE__INT, G_TYPE_NONE, 1, G_TYPE_INT);
181 g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION,
182 g_param_spec_boolean ("has-multiple-selection",
183 "has multiple selection",
184 "Whether the widget has multiple "
185 "selection (like multiple columns, "
186 "multiselection mode, or multiple "
187 "internal widgets) and therefore "
188 "it may need a confirmation button, "
193 /* style properties */
194 g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate));
198 hildon_touch_selector_get_property (GObject * object,
200 GValue * value, GParamSpec * pspec)
203 case PROP_HAS_MULTIPLE_SELECTION:
204 g_value_set_boolean (value,
205 hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object)));
208 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
214 hildon_touch_selector_init (HildonTouchSelector * selector)
216 selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
218 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
219 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
221 selector->priv->columns = NULL;
223 selector->priv->print_func = NULL;
224 selector->priv->hbox = gtk_hbox_new (FALSE, 0);
226 gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
228 gtk_widget_show (selector->priv->hbox);
230 /* FIXME: this is the correct height? A fixed height is the correct
232 gtk_widget_set_size_request (GTK_WIDGET (selector), -1, 320);
236 hildon_touch_selector_map (GtkWidget * widget)
238 GTK_WIDGET_CLASS (hildon_touch_selector_parent_class)->map (widget);
240 g_timeout_add (CENTER_ON_SELECTED_ITEM_DELAY,
241 _hildon_touch_selector_center_on_selected_items, widget);
244 /*------------------------------ GtkContainer ------------------------------ */
247 * Required in order to free the column at the columns list
250 hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
252 HildonTouchSelector *selector = NULL;
255 SelectorColumn *current_column = NULL;
256 gint num_columns = 0;
258 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container));
260 selector = HILDON_TOUCH_SELECTOR (container);
261 num_columns = hildon_touch_selector_get_num_columns (selector);
263 /* Check if the widget is inside a column and remove
265 iter = selector->priv->columns;
268 current_column = (SelectorColumn *) iter->data;
269 if (widget == current_column->panarea) {
270 current_column = g_slist_nth_data (selector->priv->columns, position);
272 selector->priv->columns = g_slist_remove (selector->priv->columns,
274 g_free (current_column);
280 iter = g_slist_next (iter);
282 if (position >= num_columns) {
283 g_debug ("This widget was not inside the selector column");
286 GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget);
289 /* ------------------------------ PRIVATE METHODS ---------------------------- */
291 * default_print_func:
292 * @selector: a #HildonTouchSelector
294 * Default print function
296 * Returns: a new string that represent the selected items
299 _default_print_func (HildonTouchSelector * selector)
301 gchar *result = NULL;
303 gint num_columns = 0;
305 GtkTreeModel *model = NULL;
306 gchar *current_string = NULL;
308 HildonTouchSelectorSelectionMode mode;
310 GtkTreePath *current_path = NULL;
311 GList *selected_rows = NULL;
312 gint initial_value = 0;
314 num_columns = hildon_touch_selector_get_num_columns (selector);
316 mode = hildon_touch_selector_get_column_selection_mode (selector);
318 if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
319 && (num_columns > 0)) {
320 /* In this case we get the first column first */
321 selected_rows = hildon_touch_selector_get_selected_rows (selector, 0);
322 model = hildon_touch_selector_get_model (selector, 0);
324 result = g_strdup_printf ("(");
326 for (item = selected_rows; item; item = g_list_next (item)) {
327 current_path = item->data;
328 gtk_tree_model_get_iter (model, &iter, current_path);
330 gtk_tree_model_get (model, &iter, 0, ¤t_string, -1);
332 if (i < g_list_length (selected_rows) - 1) {
333 aux = g_strconcat (result, current_string, ",", NULL);
337 aux = g_strconcat (result, current_string, NULL);
344 aux = g_strconcat (result, ")", NULL);
348 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
349 g_list_free (selected_rows);
355 for (i = initial_value; i < num_columns; i++) {
356 model = hildon_touch_selector_get_model (selector, i);
357 if (hildon_touch_selector_get_active_iter (selector, i, &iter)) {
359 gtk_tree_model_get (model, &iter, 0, ¤t_string, -1);
361 aux = g_strconcat (result, ":", current_string, NULL);
365 result = g_strdup_printf ("%s", current_string);
374 _selection_changed_cb (GtkTreeSelection * selection, gpointer user_data)
376 HildonTouchSelector *selector = NULL;
377 SelectorColumn *column = NULL;
378 gint num_column = -1;
380 column = (SelectorColumn *) user_data;
381 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->parent));
383 selector = column->parent;
385 num_column = g_slist_index (selector->priv->columns, column);
387 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, num_column);
391 static SelectorColumn *
392 _create_new_column (HildonTouchSelector * selector,
393 GtkTreeModel * model,
394 GtkCellRenderer * renderer, va_list args)
396 SelectorColumn *new_column = NULL;
397 GtkTreeViewColumn *tree_column = NULL;
399 GtkTreeView *tv = NULL;
400 GtkWidget *panarea = NULL;
401 GtkTreeSelection *selection = NULL;
406 tree_column = gtk_tree_view_column_new ();
407 gtk_tree_view_column_pack_start (tree_column, renderer, TRUE);
409 attribute = va_arg (args, gchar *);
410 while (attribute != NULL) {
411 value = va_arg (args, gint);
412 gtk_tree_view_column_add_attribute (tree_column, renderer, attribute,
414 attribute = va_arg (args, gchar *);
417 tv = g_object_new (GTK_TYPE_TREE_VIEW, "model", model, "name", "fremantle-widget", /* FIXME: is this always this name? */
418 "hildon-ui-mode", HILDON_UI_MODE_EDIT,
419 "rules-hint", TRUE, NULL);
421 gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column);
423 new_column = (SelectorColumn *) g_malloc0 (sizeof (SelectorColumn));
424 new_column->parent = selector;
426 panarea = hildon_pannable_area_new ();
428 g_value_init (&val, G_TYPE_INT);
429 g_value_set_int (&val, HILDON_PANNABLE_AREA_INDICATOR_MODE_HIDE);
430 g_object_set_property (G_OBJECT (panarea), "vindicator-mode", &val);
432 g_value_unset (&val);
433 g_value_init (&val, G_TYPE_BOOLEAN);
434 g_value_set_boolean (&val, FALSE);
435 g_object_set_property (G_OBJECT (panarea), "initial-hint", &val);
437 gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv));
439 new_column->model = model;
440 new_column->tree_view = tv;
441 new_column->panarea = panarea;
443 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
444 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
446 /* select the first item */
447 if (gtk_tree_model_get_iter_first (model, &iter)) {
448 gtk_tree_selection_select_iter (selection, &iter);
451 gtk_widget_grab_focus (GTK_WIDGET (tv));
453 /* connect to the changed signal connection */
454 g_signal_connect (G_OBJECT (selection), "changed",
455 G_CALLBACK (_selection_changed_cb), new_column);
460 /* ------------------------------ PUBLIC METHODS ---------------------------- */
463 * hildon_touch_selector_new:
465 * Creates a new empty #HildonTouchSelector.
467 * Returns: a new #HildonTouchSelector.
470 hildon_touch_selector_new (void)
472 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL);
476 * hildon_touch_selector_new_text:
478 * Creates a #HildonTouchSelector with a single text column that
479 * can be populated conveniently through hildon_touch_selector_append_text(),
480 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
482 * Returns: A new #HildonTouchSelector
485 hildon_touch_selector_new_text (void)
490 selector = hildon_touch_selector_new ();
491 store = gtk_list_store_new (1, G_TYPE_STRING);
493 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
494 GTK_TREE_MODEL (store), TRUE);
500 * hildon_touch_selector_append_text:
501 * @selector: A #HildonTouchSelector.
502 * @text: a non %NULL text string.
504 * Appends a new entry in a #HildonTouchSelector created with
505 * hildon_touch_selector_new_text().
508 hildon_touch_selector_append_text (HildonTouchSelector * selector,
514 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
515 g_return_if_fail (text != NULL);
517 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
519 g_return_if_fail (GTK_IS_LIST_STORE (model));
521 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
522 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
526 * hildon_touch_selector_prepend_text:
527 * @selector: A #HildonTouchSelector.
528 * @text: a non %NULL text string.
530 * Prepends a new entry in a #HildonTouchSelector created with
531 * hildon_touch_selector_new_text().
534 hildon_touch_selector_prepend_text (HildonTouchSelector * selector,
540 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
541 g_return_if_fail (text != NULL);
543 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
545 g_return_if_fail (GTK_IS_LIST_STORE (model));
547 gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
548 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
552 * hildon_touch_selector_insert_text:
553 * @selector: a #HildonTouchSelector.
554 * @position: the position to insert @text.
555 * @text: A non %NULL text string.
557 * Inserts a new entry in particular position of a #HildoTouchSelector created
558 * with hildon_touch_selector_new_text().
562 hildon_touch_selector_insert_text (HildonTouchSelector * selector,
563 gint position, const gchar * text)
568 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
569 g_return_if_fail (text != NULL);
570 g_return_if_fail (position >= 0);
572 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
574 g_return_if_fail (GTK_IS_LIST_STORE (model));
576 gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position);
577 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
581 * hildon_touch_selector_append_column
582 * @selector: a #HildonTouchSelector
583 * @model: the #GtkTreeModel with the data of the column
584 * @cell_renderer: The #GtkCellRenderer where to draw each row contents.
585 * @Varargs: a %NULL-terminated pair of attributes and column numbers.
587 * This functions adds a new column to the widget, whose data will
588 * be obtained from the model. Only widgets added this way should used on
589 * the selection logic, i.e., the print function, the #HildonTouchPicker::changed
592 * Contents will be represented in @cell_renderer. You can pass a %NULL-terminated
593 * list of pairs property/value, in the same way you would use
594 * gtk_tree_view_column_set_attributes().
596 * There is a prerequisite to be considered on models used: text data must
597 * be in the first column.
599 * This method basically adds a #GtkTreeView to the widget, using the model and
602 * Returns: %TRUE if a new column was added, %FALSE otherwise
606 hildon_touch_selector_append_column (HildonTouchSelector * selector,
607 GtkTreeModel * model,
608 GtkCellRenderer * cell_renderer, ...)
611 SelectorColumn *new_column = NULL;
613 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
614 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
618 va_start (args, cell_renderer);
619 new_column = _create_new_column (selector, model, cell_renderer, args);
622 selector->priv->columns = g_slist_append (selector->priv->columns,
624 gtk_box_pack_start (GTK_BOX (selector->priv->hbox), new_column->panarea, TRUE, TRUE, 6);
626 gtk_widget_show_all (new_column->panarea);
635 * hildon_touch_selector_append_text_column
636 * @selector: a #HildonTouchSelector
637 * @model: a #GtkTreeModel with data for the column
638 * @center: whether to center the text on the column
640 * Equivalent to hildon_touch_selector_append_column(), but using a
641 * default text cell renderer. This is the most common use case of the
644 * Returns: %TRUE if a new column was added, %FALSE otherwise.
647 hildon_touch_selector_append_text_column (HildonTouchSelector * selector,
648 GtkTreeModel * model, gboolean center)
650 GtkCellRenderer *renderer = NULL;
653 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
654 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
657 renderer = gtk_cell_renderer_text_new ();
660 g_value_init (&val, G_TYPE_FLOAT);
661 g_value_set_float (&val, 0.5);
662 /* FIXME: center the text, this should be configurable */
663 g_object_set_property (G_OBJECT (renderer), "xalign", &val);
666 return hildon_touch_selector_append_column (selector, model, renderer,
674 * hildon_touch_selector_remove_column:
675 * @selector: a #HildonTouchSelector
676 * @column: the position of the column to be removed
678 * Removes a column from @selector.
680 * Returns: %TRUE if the column was removed, %FALSE otherwise
683 hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column)
685 SelectorColumn *current_column = NULL;
687 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
688 g_return_val_if_fail (column <
689 hildon_touch_selector_get_num_columns (selector), FALSE);
691 current_column = g_slist_nth_data (selector->priv->columns, column);
693 gtk_container_remove (GTK_CONTAINER (selector), current_column->panarea);
699 * hildon_touch_selector_set_column_attributes:
700 * @selector: a #HildonTouchSelector
701 * @num_column: the number of the column whose attributes we're setting
702 * @cell_renderer: the #GtkCellRendere we're setting the attributes of
703 * @Varargs: A %NULL-terminated list of attributes.
705 * Sets the attributes for the given column. The attributes must be given
706 * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes().
707 * All existing attributes are removed and replaced with the new ones.
711 hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector,
713 GtkCellRenderer * cell_renderer,
717 GtkTreeViewColumn *tree_column = NULL;
718 SelectorColumn *current_column = NULL;
719 gchar *attribute = NULL;
722 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
723 g_return_if_fail (num_column <
724 hildon_touch_selector_get_num_columns (selector));
726 current_column = g_slist_nth_data (selector->priv->columns, num_column);
728 tree_column = gtk_tree_view_get_column (current_column->tree_view, 0);
729 gtk_tree_view_remove_column (current_column->tree_view, tree_column);
731 tree_column = gtk_tree_view_column_new ();
732 gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE);
734 va_start (args, cell_renderer);
735 attribute = va_arg (args, gchar *);
737 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
739 while (attribute != NULL) {
740 value = va_arg (args, gint);
741 gtk_tree_view_column_add_attribute (tree_column, cell_renderer,
743 attribute = va_arg (args, gchar *);
748 gtk_tree_view_append_column (current_column->tree_view, tree_column);
753 hildon_touch_selector_insert_column (HildonTouchSelector * selector, gint position)
755 g_warning ("Un-implemented!");
762 * hildon_touch_selector_get_num_columns:
763 * @selector: a #HildonTouchSelector
765 * Gets the number of columns in the #HildonTouchSelector.
767 * Returns: the number of columns in @selector.
770 hildon_touch_selector_get_num_columns (HildonTouchSelector * selector)
772 return g_slist_length (selector->priv->columns);
776 * hildon_touch_selector_get_column_selection_mode:
777 * @selector: a #HildonTouchSelector
779 * Gets the selection mode of @selector.
781 * Returns: one of #HildonTouchSelectorSelectionMode
783 HildonTouchSelectorSelectionMode
784 hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector)
786 HildonTouchSelectorSelectionMode result =
787 HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
788 GtkSelectionMode treeview_mode = GTK_SELECTION_SINGLE;
789 SelectorColumn *column = NULL;
790 GtkTreeSelection *selection = NULL;
792 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result);
793 g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0,
796 column = (SelectorColumn *) selector->priv->columns->data;
798 selection = gtk_tree_view_get_selection (column->tree_view);
799 treeview_mode = gtk_tree_selection_get_mode (selection);
802 if (treeview_mode == GTK_SELECTION_MULTIPLE) {
803 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE;
805 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
812 * hildon_touch_selector_set_column_selection_mode:
813 * @selector: a #HildonTouchSelector
814 * @mode: the #HildonTouchSelectorMode for @selector
816 * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode.
819 hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
820 HildonTouchSelectorSelectionMode mode)
822 GtkTreeView *tv = NULL;
823 SelectorColumn *column = NULL;
824 GtkTreeSelection *selection = NULL;
825 GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE;
828 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
829 g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0);
831 column = (SelectorColumn *) (g_slist_nth (selector->priv->columns, 0))->data;
832 tv = column->tree_view;
836 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE:
837 treeview_mode = GTK_SELECTION_SINGLE;
839 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE:
840 treeview_mode = GTK_SELECTION_MULTIPLE;
844 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
845 gtk_tree_selection_set_mode (selection, treeview_mode);
847 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
848 gtk_tree_model_get_iter_first (column->model, &iter);
849 gtk_tree_selection_unselect_all (selection);
850 gtk_tree_selection_select_iter (selection, &iter);
856 * hildon_touch_selector_set_print_func:
857 * @selector: a #HildonTouchSelector
858 * @func: a #HildonTouchSelectorPrintFunc function
860 * Sets the function to be used by hildon_touch_selector_get_current_text()
861 * to produce a text representation of the currently selected items in @selector.
862 * The default function will return a concatenation of comma separated items
863 * selected in each column in @selector. Use this to override this method if you
864 * need a particular representation for your application.
868 hildon_touch_selector_set_print_func (HildonTouchSelector * selector,
869 HildonTouchSelectorPrintFunc func)
871 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
873 selector->priv->print_func = func;
877 * hildon_touch_selector_get_print_func:
878 * @selector: a #HildonTouchSelector
880 * Gets the #HildonTouchSelectorPrintFunc currently used. See
881 * hildon_touch_selector_set_print_func().
883 * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default
884 * one is currently used.
886 HildonTouchSelectorPrintFunc
887 hildon_touch_selector_get_print_func (HildonTouchSelector * selector)
889 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
891 return selector->priv->print_func;
895 * hildon_touch_selector_get_active_iter:
896 * @selector: a #HildonTouchSelector
897 * @column: the column number we want to get the element
898 * @iter: #GtkTreeIter currently selected
900 * Sets @iter to the currently selected node on the nth-column, if selection is set to
901 * %HILDON_TOUCH_SELECTOR_SINGLE. @iter may be %NULL if you just want to test if selection
902 * has any selected items.
904 * This function will not work if selection is in
905 * %HILDON_TOUCH_SELECTOR_MULTIPLE mode.
907 * See gtk_tree_selection_get_selected() for more information.
909 * Returns: %TRUE if @iter was correctly set, %FALSE otherwise
912 hildon_touch_selector_get_active_iter (HildonTouchSelector * selector,
913 gint column, GtkTreeIter * iter)
915 GtkTreeSelection *selection = NULL;
916 SelectorColumn *current_column = NULL;
918 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
919 g_return_val_if_fail (hildon_touch_selector_get_column_selection_mode (selector)
920 == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, FALSE);
921 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
924 current_column = g_slist_nth_data (selector->priv->columns, column);
927 gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->tree_view));
929 return gtk_tree_selection_get_selected (selection, NULL, iter);
933 * hildon_touch_selector_set_active_iter
934 * @selector: a #HildonTouchSelector
935 * @column: the column to selects
936 * @iter: the #GtkTreeIter to be selected
937 * @scroll_to: whether to smoothly scroll to the item
939 * Sets the currently selected item in the column @column to the one pointed by @iter,
940 * optionally smoothly scrolling to it.
944 hildon_touch_selector_set_active_iter (HildonTouchSelector * selector,
945 gint column, GtkTreeIter * iter,
951 SelectorColumn *current_column = NULL;
952 GtkTreeSelection *selection = NULL;
955 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
956 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
958 current_column = g_slist_nth_data (selector->priv->columns, column);
960 selection = gtk_tree_view_get_selection (current_column->tree_view);
961 model = gtk_tree_view_get_model (current_column->tree_view);
962 path = gtk_tree_model_get_path (model, iter);
964 gtk_tree_selection_select_iter (selection, iter);
965 gtk_tree_view_set_cursor (GTK_TREE_VIEW (current_column->tree_view), path, NULL, FALSE);
968 gtk_tree_view_get_background_area (current_column->tree_view,
970 gtk_tree_view_convert_bin_window_to_tree_coords (current_column->tree_view,
971 0, rect.y, NULL, &y);
972 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (current_column->panarea),
975 gtk_tree_path_free (path);
979 * hildon_touch_selector_get_selected_rows:
980 * @selector: a #HildonTouchSelector
981 * @column: the position of the column to get the selected rows from
983 * Creates a list of #GtkTreePath<!-- -->s of all selected rows in a column. Additionally,
984 * if you to plan to modify the model after calling this function, you may
985 * want to convert the returned list into a list of GtkTreeRowReferences. To do this,
986 * you can use gtk_tree_row_reference_new().
988 * See gtk_tree_selection_get_selected_rows() for more information.
990 * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column.
994 hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector,
997 GList *result = NULL;
998 SelectorColumn *current_column = NULL;
999 GtkTreeSelection *selection = NULL;
1001 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1002 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1005 current_column = g_slist_nth_data (selector->priv->columns, column);
1006 selection = gtk_tree_view_get_selection (current_column->tree_view);
1008 result = gtk_tree_selection_get_selected_rows (selection, NULL);
1015 * hildon_touch_selector_get_model:
1016 * @selector: a #HildonTouchSelector
1017 * @column: the position of the column in @selector
1019 * Gets the model of a column of @selector.
1021 * Returns: the #GtkTreeModel for the column @column of @selector.
1024 hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column)
1026 SelectorColumn *current_column = NULL;
1028 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1029 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1032 current_column = g_slist_nth_data (selector->priv->columns, column);
1034 return current_column->model;
1038 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
1039 gint column, GtkTreeModel * model)
1041 SelectorColumn *current_column = NULL;
1042 g_print ("this was actually called\n");
1045 (SelectorColumn *) g_slist_nth_data (selector->priv->columns, column);
1047 current_column->model = model;
1048 gtk_tree_view_set_model (current_column->tree_view, current_column->model);
1052 * hildon_touch_selector_set_model:
1053 * @selector: a #HildonTouchSelector
1054 * @column: the position of the column to set the model to
1055 * @model: a #GtkTreeModel
1057 * Sets the #GtkTreeModel for a particular column in @model.
1060 hildon_touch_selector_set_model (HildonTouchSelector * selector,
1061 gint column, GtkTreeModel * model)
1063 g_return_if_fail (HILDON_TOUCH_SELECTOR (selector));
1064 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1066 HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model);
1070 * hildon_touch_selector_get_current_text:
1071 * @selector: a #HildonTouchSelector
1073 * Returns a string representing the currently selected items for
1074 * each column of @selector. See hildon_touch_selector_set_print_func().
1076 * Returns: a newly allocated string.
1079 hildon_touch_selector_get_current_text (HildonTouchSelector * selector)
1081 gchar *result = NULL;
1082 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1084 if (selector->priv->print_func) {
1085 result = (*selector->priv->print_func) (selector);
1087 result = _default_print_func (selector);
1094 _hildon_touch_selector_center_on_selected_items (gpointer data)
1096 HildonTouchSelector *selector = NULL;
1097 SelectorColumn *column = NULL;
1098 GSList *iter_column = NULL;
1104 HildonTouchSelectorSelectionMode selection_mode;
1106 /* ensure to center on the initial values */
1107 selector = HILDON_TOUCH_SELECTOR (data);
1109 selection_mode = hildon_touch_selector_get_column_selection_mode (selector);
1111 iter_column = selector->priv->columns;
1113 while (iter_column) {
1114 column = (SelectorColumn *) iter_column->data;
1117 && (selection_mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)) {
1120 if (hildon_touch_selector_get_active_iter (selector, i, &iter)) {
1121 path = gtk_tree_model_get_path (column->model, &iter);
1122 gtk_tree_view_get_background_area (GTK_TREE_VIEW
1123 (column->tree_view), path, NULL,
1126 gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW
1127 (column->tree_view), 0,
1130 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA
1131 (column->panarea), -1, y);
1133 gtk_tree_path_free (path);
1135 iter_column = iter_column->next;
1143 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1145 HildonTouchSelectorSelectionMode mode = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1148 n_columns = hildon_touch_selector_get_num_columns (selector);
1149 mode = hildon_touch_selector_get_column_selection_mode (selector);
1151 return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE));
1155 * hildon_touch_selector_has_multiple_selection:
1156 * @selector: A #HildonTouchSelector
1158 * Determines whether @selector is complex enough to actually require an
1159 * extra selection step than only picking an item. This is normally %TRUE
1160 * if @selector has multiple columns, multiple selection, or when it is a
1161 * more complex widget, like %HildonTouchSelectorEntry.
1163 * This information is useful for widgets containing a %HildonTouchSelector,
1164 * like #HildonPickerDialog, that could need a "Done" button, in case that
1165 * its internal #HildonTouchSelector has multiple columns, for instance.
1167 * Returns: %TRUE if @selector requires multiple selection steps.
1170 hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1172 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1174 return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector);