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.
49 * The current selection has a string representation. In the most common cases,
50 * each column model will contain a text column. You can configure
51 * which column in particular using the #HildonTouchSelectorColumn property
52 * #HildonTouchSelectorColumn:text-column
54 * You can get this string representation using
55 * hildon_touch_selector_get_current_text().
56 * You can configure how the selection is printed with
57 * hildon_touch_selector_set_print_func(), that sets the current hildon touch
58 * selector print function. The widget has a default print function, that
59 * uses the #HildonTouchSelectorColumn:text-column property on each
60 * #HildonTouchSelectorColumn to compose the final representation.
62 * If you create the selector using hildon_touch_selector_new_text() you
63 * don't need to take care of this property, as the model is created internally.
64 * If you create the selector using hildon_touch_selector_new(), you
65 * need to specify properly the property for your custom model in order to get a
66 * non-empty string representation, or define your custom print function.
69 * <title>Creating a HildonTouchSelector</title>
72 * selection_changed (HildonTouchSelector * selector,
73 * gpointer *user_data)
75 * gchar *current_selection = NULL;
77 * current_selection = hildon_touch_selector_get_current_text (selector);
78 * g_debug ("Current selection : %s", current_selection);
82 * create_customized_selector ()
84 * GtkWidget *selector = NULL;
85 * GSList *icon_list = NULL;
86 * GtkListStore *store_icons = NULL;
87 * GSList *item = NULL;
88 * GtkCellRenderer *renderer = NULL;
89 * HildonTouchSelectorColumn *column = NULL;
91 * selector = hildon_touch_selector_new ();
93 * icon_list = gtk_stock_list_ids ();
95 * store_icons = gtk_list_store_new (1, G_TYPE_STRING);
96 * for (item = icon_list; item; item = g_slist_next (item)) {
98 * gchar *label = item->data;
100 * gtk_list_store_append (store_icons, &iter);
101 * gtk_list_store_set (store_icons, &iter, 0, label, -1);
104 * g_slist_free (icon_list);
106 * renderer = gtk_cell_renderer_pixbuf_new ();
107 * gtk_cell_renderer_set_fixed_size (renderer, -1, 100);
109 * column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
110 * GTK_TREE_MODEL (store_icons),
111 * renderer, "stock-id", 0, NULL);
113 * g_object_set (G_OBJECT (column), "text-column", 0, NULL);
115 * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
116 * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE);
118 * g_signal_connect (G_OBJECT (selector), "changed",
119 * G_CALLBACK (selection_changed), NULL);
125 * create_simple_selector ()
127 * GtkWidget *selector = NULL;
130 * selector = hildon_touch_selector_new_text ();
131 * hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
132 * HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE);
134 * g_signal_connect (G_OBJECT (selector), "changed",
135 * G_CALLBACK (selection_changed), NULL);
137 * for (i = 1; i <= 10 ; i++) {
138 * gchar *label = g_strdup_printf ("Item &percnt;d", i);
140 * hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
153 * SECTION:hildon-touch-selector-column
154 * @short_description: A visible column in a #HildonTouchSelector
156 * #HildonTouchSelectorColumn object represents a visible column in
157 * #HildonTouchSelector. It allows to manage the cell renderers related to each
161 #undef HILDON_DISABLE_DEPRECATED
170 #include "hildon-gtk.h"
172 #include "hildon-pannable-area.h"
173 #include "hildon-touch-selector.h"
175 #define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \
176 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
178 G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX)
181 * IMPLEMENTATION NOTES:
182 * Struct to maintain the data of each column. The columns are the elements
183 * of the widget that belongs properly to the selection behaviour. Although
184 * internally the columns are arranged in a private #GtkHBox, as the selector
185 * itself is a #GtkVBox, you can add more widgets, like buttons etc., so
186 * you finally could have a widget with more elements that the columns, but
187 * this doesn't belongs to the selection logic
189 struct _HildonTouchSelectorColumnPrivate
191 HildonTouchSelector *parent; /* the selector that contains this column */
194 GtkTreeView *tree_view;
195 gulong realize_handler;
196 GtkTreePath *initial_path;
198 GtkWidget *panarea; /* the pannable widget */
201 struct _HildonTouchSelectorPrivate
203 GSList *columns; /* the selection columns */
204 GtkWidget *hbox; /* the container for the selector's columns */
205 gboolean initial_scroll; /* whether initial fancy scrolling to selection */
207 HildonTouchSelectorPrintFunc print_func;
212 PROP_HAS_MULTIPLE_SELECTION = 1,
223 static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 };
226 hildon_touch_selector_get_property (GObject * object,
231 hildon_touch_selector_set_property (GObject *object,
238 static void hildon_touch_selector_remove (GtkContainer * container,
240 /* private functions */
241 static void _row_tapped_cb (GtkTreeView * tree_view,
244 static gchar *_default_print_func (HildonTouchSelector * selector);
246 static HildonTouchSelectorColumn *_create_new_column (HildonTouchSelector * selector,
247 GtkTreeModel * model,
248 gboolean *emit_changed,
249 GtkCellRenderer * renderer,
252 on_realize_cb (GtkWidget *widget,
255 hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
259 _hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
260 HildonTouchSelectorColumn *column);
262 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
264 GtkTreeModel * model);
266 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector);
268 /* GtkCellLayout implementation (HildonTouchSelectorColumn)*/
269 static void hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface);
271 static void hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
272 GtkCellRenderer *cell,
274 static void hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
275 GtkCellRenderer *cell,
277 static void hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout);
278 static void hildon_touch_selector_column_cell_layout_add_attribute(GtkCellLayout *cell_layout,
279 GtkCellRenderer *cell,
280 const gchar *attribute,
282 static void hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
283 GtkCellRenderer *cell,
284 GtkCellLayoutDataFunc func,
286 GDestroyNotify destroy);
287 static void hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
288 GtkCellRenderer *cell);
289 static void hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout,
290 GtkCellRenderer *cell,
292 static GList *hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout);
296 hildon_touch_selector_class_init (HildonTouchSelectorClass * class)
298 GObjectClass *gobject_class;
299 GtkObjectClass *object_class;
300 GtkContainerClass *container_class;
302 gobject_class = G_OBJECT_CLASS (class);
303 object_class = GTK_OBJECT_CLASS (class);
304 container_class = GTK_CONTAINER_CLASS (class);
307 gobject_class->get_property = hildon_touch_selector_get_property;
308 gobject_class->set_property = hildon_touch_selector_set_property;
313 container_class->remove = hildon_touch_selector_remove;
315 /* HildonTouchSelector */
316 class->changed = NULL;
317 class->set_model = _hildon_touch_selector_set_model;
319 class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection;
323 * HildonTouchSelector::changed:
324 * @widget: the object which received the signal
325 * @column: the number of the column that has changed
327 * The "changed" signal is emitted when the active item on any column is changed.
328 * This can be due to the user selecting a different item from the list, or
329 * due to a call to hildon_touch_selector_select_iter() on one of the columns.
332 hildon_touch_selector_signals[CHANGED] =
333 g_signal_new ("changed",
334 G_OBJECT_CLASS_TYPE (class),
336 G_STRUCT_OFFSET (HildonTouchSelectorClass, changed),
338 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
341 * HildonTouchSelector::columns-changed:
342 * @selector: the object which received the signal
344 * The "columns-changed" signal is emitted when the number
345 * of columns in the #HildonTouchSelector change.
348 hildon_touch_selector_signals[COLUMNS_CHANGED] =
349 g_signal_new ("columns-changed",
350 G_OBJECT_CLASS_TYPE (class),
351 G_SIGNAL_RUN_LAST, 0,
353 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
357 g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION,
358 g_param_spec_boolean ("has-multiple-selection",
359 "has multiple selection",
360 "Whether the widget has multiple "
361 "selection (like multiple columns, "
362 "multiselection mode, or multiple "
363 "internal widgets) and therefore "
364 "it may need a confirmation button, "
369 g_object_class_install_property (G_OBJECT_CLASS (gobject_class),
371 g_param_spec_boolean ("initial-scroll",
373 "Whether to scroll to the"
374 "current selection when"
375 "the selector is first"
378 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
380 /* style properties */
381 /* We need to ensure fremantle mode for the treeview in order to work
382 properly. This is not about the appearance, this is about behaviour */
383 gtk_rc_parse_string ("style \"fremantle-htst\" {\n"
384 " GtkWidget::hildon-mode = 1\n"
385 "} widget \"*.fremantle-htst\" style \"fremantle-htst\""
386 "widget_class \"*<HildonPannableArea>.GtkTreeView\" style :highest \"fremantle-htst\"");
388 g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate));
392 hildon_touch_selector_get_property (GObject * object,
394 GValue * value, GParamSpec * pspec)
396 HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
399 case PROP_HAS_MULTIPLE_SELECTION:
400 g_value_set_boolean (value,
401 hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object)));
403 case PROP_INITIAL_SCROLL:
404 g_value_set_boolean (value, priv->initial_scroll);
407 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
413 hildon_touch_selector_set_property (GObject *object, guint prop_id,
414 const GValue *value, GParamSpec *pspec)
416 HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
419 case PROP_INITIAL_SCROLL:
420 priv->initial_scroll = g_value_get_boolean (value);
423 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
430 hildon_touch_selector_init (HildonTouchSelector * selector)
432 selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
434 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
435 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
437 selector->priv->columns = NULL;
439 selector->priv->print_func = NULL;
440 selector->priv->initial_scroll = TRUE;
441 selector->priv->hbox = gtk_hbox_new (FALSE, 0);
443 gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
445 gtk_widget_show (selector->priv->hbox);
449 * IMPLEMENTATION NOTES:
450 * Some people sent questions regarding a missing dispose/finalize function on
451 * this widget that could lead to leak memory, so we will clarify this topic.
453 * This is not required as #HildonTouchSelector extends #GtkContainer. When the
454 * widget is freed, the #GtkContainer freeing memory functions are called. This
455 * process includes remove each widget individually, so all the widgets are
458 * In the same way, this widget redefines gtk_container->remove function, in
459 * order to free the column related information if it is required.
461 * Please take a look to hildon_touch_selector_remove for more information.
464 /*------------------------------ GtkContainer ------------------------------ */
467 * Required in order to free the column at the columns list
470 hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
472 HildonTouchSelector *selector = NULL;
474 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container));
475 selector = HILDON_TOUCH_SELECTOR (container);
477 /* Remove the extra data related to the columns, if required. */
478 if (widget == selector->priv->hbox) {
479 g_slist_foreach (selector->priv->columns, (GFunc) g_object_unref, NULL);
481 g_slist_free (selector->priv->columns);
483 selector->priv->columns = NULL;
485 g_debug ("Freeing a widget outside the columns logic");
488 /* Now remove the widget itself from the container */
489 GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget);
492 /* ------------------------------ PRIVATE METHODS ---------------------------- */
494 * default_print_func:
495 * @selector: a #HildonTouchSelector
497 * Default print function
499 * Returns: a new string that represents the selected items
504 _default_print_func (HildonTouchSelector * selector)
506 gchar *result = NULL;
508 gint num_columns = 0;
510 GtkTreeModel *model = NULL;
511 gchar *current_string = NULL;
513 HildonTouchSelectorSelectionMode mode;
515 GtkTreePath *current_path = NULL;
516 GList *selected_rows = NULL;
517 gint initial_value = 0;
518 gint text_column = -1;
519 HildonTouchSelectorColumn *column = NULL;
521 num_columns = hildon_touch_selector_get_num_columns (selector);
523 mode = hildon_touch_selector_get_column_selection_mode (selector);
525 if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
526 && (num_columns > 0)) {
527 /* In this case we get the first column first */
528 selected_rows = hildon_touch_selector_get_selected_rows (selector, 0);
529 model = hildon_touch_selector_get_model (selector, 0);
530 column = hildon_touch_selector_get_column (selector, 0);
531 g_object_get (G_OBJECT(column), "text-column", &text_column, NULL);
533 result = g_strdup_printf ("(");
535 for (item = selected_rows; item; item = g_list_next (item)) {
536 current_path = item->data;
537 gtk_tree_model_get_iter (model, &iter, current_path);
539 if (text_column != -1) {
540 gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1);
543 if (i < g_list_length (selected_rows) - 1) {
544 aux = g_strconcat (result, current_string, ",", NULL);
548 aux = g_strconcat (result, current_string, NULL);
553 if (current_string) {
554 g_free (current_string);
555 current_string = NULL;
561 aux = g_strconcat (result, ")", NULL);
565 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
566 g_list_free (selected_rows);
572 for (i = initial_value; i < num_columns; i++) {
573 model = hildon_touch_selector_get_model (selector, i);
574 column = hildon_touch_selector_get_column (selector, i);
575 g_object_get (G_OBJECT(column), "text-column", &text_column, NULL);
577 if (hildon_touch_selector_get_selected (selector, i, &iter)) {
578 if (text_column == -1 ) {
579 g_warning ("Trying to use the default print function in HildonTouchSelector, but "
580 "\"text-column\" property is not set for HildonTouchSelectorColumn %p.", column);
581 current_string = NULL;
583 gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1);
587 aux = g_strconcat (result, ":", current_string, NULL);
591 result = current_string;
600 _row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data)
602 HildonTouchSelector *selector = NULL;
603 HildonTouchSelectorColumn *column = NULL;
604 gint num_column = -1;
606 column = HILDON_TOUCH_SELECTOR_COLUMN (user_data);
607 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->priv->parent));
609 selector = column->priv->parent;
611 num_column = g_slist_index (selector->priv->columns, column);
613 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, num_column);
617 static HildonTouchSelectorColumn *
618 _create_new_column (HildonTouchSelector * selector,
619 GtkTreeModel * model,
620 gboolean *emit_changed,
621 GtkCellRenderer * renderer, va_list args)
623 HildonTouchSelectorColumn *new_column = NULL;
624 GtkTreeViewColumn *tree_column = NULL;
625 GtkTreeView *tv = NULL;
626 GtkWidget *panarea = NULL;
627 GtkTreeSelection *selection = NULL;
632 tree_column = gtk_tree_view_column_new ();
634 if (renderer != NULL) {
635 gtk_tree_view_column_pack_start (tree_column, renderer, TRUE);
637 attribute = va_arg (args, gchar *);
638 while (attribute != NULL) {
639 value = va_arg (args, gint);
640 gtk_tree_view_column_add_attribute (tree_column, renderer, attribute,
642 attribute = va_arg (args, gchar *);
647 tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT));
649 tv = GTK_TREE_VIEW (gtk_tree_view_new ());
650 #endif /* MAEMO_GTK */
652 gtk_tree_view_set_enable_search (tv, FALSE);
654 gtk_tree_view_set_model (tv, model);
655 gtk_tree_view_set_rules_hint (tv, TRUE);
657 gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column);
659 new_column = g_object_new (HILDON_TYPE_TOUCH_SELECTOR_COLUMN, NULL);
660 new_column->priv->parent = selector;
662 panarea = hildon_pannable_area_new ();
664 g_object_set (G_OBJECT (panarea),
665 "initial-hint", FALSE, NULL);
667 gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv));
669 new_column->priv->model = model;
670 new_column->priv->tree_view = tv;
671 new_column->priv->panarea = panarea;
672 new_column->priv->realize_handler = 0;
673 new_column->priv->initial_path = NULL;
675 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
676 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
678 /* select the first item */
679 *emit_changed = FALSE;
680 if (gtk_tree_model_get_iter_first (model, &iter)) {
681 gtk_tree_selection_select_iter (selection, &iter);
682 *emit_changed = TRUE;
685 gtk_widget_grab_focus (GTK_WIDGET (tv));
687 /* connect to the hildon-row-tapped signal connection */
688 g_signal_connect (G_OBJECT (tv), "hildon-row-tapped",
689 G_CALLBACK (_row_tapped_cb), new_column);
695 /* ------------------------ HildonTouchSelectorColumn implementation ---------------------- */
696 G_DEFINE_TYPE_WITH_CODE (HildonTouchSelectorColumn, hildon_touch_selector_column, G_TYPE_OBJECT,
697 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
698 hildon_touch_selector_column_cell_layout_init))
706 hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass);
709 hildon_touch_selector_column_get_property (GObject *object, guint property_id,
710 GValue *value, GParamSpec *pspec);
713 hildon_touch_selector_column_set_property (GObject *object, guint property_id,
714 const GValue *value, GParamSpec *pspec);
717 hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column,
720 hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column);
724 hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass)
726 GObjectClass *gobject_class = NULL;
728 gobject_class = G_OBJECT_CLASS (klass);
730 g_type_class_add_private (gobject_class, sizeof (HildonTouchSelectorColumnPrivate));
733 gobject_class->get_property = hildon_touch_selector_column_get_property;
734 gobject_class->set_property = hildon_touch_selector_column_set_property;
736 g_object_class_install_property (G_OBJECT_CLASS(klass),
738 g_param_spec_int ("text-column",
740 "A column in the data source model to get the strings from.",
748 hildon_touch_selector_column_init (HildonTouchSelectorColumn *column)
750 column->priv = G_TYPE_INSTANCE_GET_PRIVATE (column, HILDON_TYPE_TOUCH_SELECTOR_COLUMN,
751 HildonTouchSelectorColumnPrivate);
752 column->priv->text_column = -1;
756 hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column,
759 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column));
760 g_return_if_fail (text_column >= -1);
762 column->priv->text_column = text_column;
764 g_object_notify (G_OBJECT (column), "text-column");
768 hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column)
770 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column), -1);
772 return column->priv->text_column;
776 hildon_touch_selector_column_get_property (GObject *object, guint property_id,
777 GValue *value, GParamSpec *pspec)
779 switch (property_id) {
780 case PROP_TEXT_COLUMN:
781 g_value_set_int (value,
782 hildon_touch_selector_column_get_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object)));
785 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
790 hildon_touch_selector_column_set_property (GObject *object, guint property_id,
791 const GValue *value, GParamSpec *pspec)
793 switch (property_id) {
794 case PROP_TEXT_COLUMN:
795 hildon_touch_selector_column_set_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object),
796 g_value_get_int (value));
799 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
803 /* ------------------------ GtkCellLayout implementation -------------------- */
805 hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface)
807 iface->pack_start = hildon_touch_selector_column_cell_layout_pack_start;
808 iface->pack_end = hildon_touch_selector_column_cell_layout_pack_end;
809 iface->clear = hildon_touch_selector_column_cell_layout_clear;
810 iface->add_attribute = hildon_touch_selector_column_cell_layout_add_attribute;
811 iface->set_cell_data_func = hildon_touch_selector_column_cell_layout_set_cell_data_func;
812 iface->clear_attributes = hildon_touch_selector_column_cell_layout_clear_attributes;
813 iface->reorder = hildon_touch_selector_column_cell_layout_reorder;
814 iface->get_cells = hildon_touch_selector_column_cell_layout_get_cells;
818 hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
819 GtkCellRenderer *cell,
822 HildonTouchSelectorColumn *sel_column = NULL;
823 GtkTreeViewColumn *view_column = NULL;
825 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
826 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
828 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
830 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(view_column), cell, expand);
835 hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
836 GtkCellRenderer *cell,
839 HildonTouchSelectorColumn *sel_column = NULL;
840 GtkTreeViewColumn *view_column = NULL;
842 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
843 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
845 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
847 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT(view_column), cell, expand);
851 hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout)
853 HildonTouchSelectorColumn *sel_column = NULL;
854 GtkTreeViewColumn *view_column = NULL;
856 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
857 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
859 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
861 gtk_cell_layout_clear (GTK_CELL_LAYOUT(view_column));
865 hildon_touch_selector_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
866 GtkCellRenderer *cell,
867 const gchar *attribute,
870 HildonTouchSelectorColumn *sel_column = NULL;
871 GtkTreeViewColumn *view_column = NULL;
873 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
874 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
876 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
878 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(view_column), cell, attribute, column);
883 hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
884 GtkCellRenderer *cell,
885 GtkCellLayoutDataFunc func,
887 GDestroyNotify destroy)
889 HildonTouchSelectorColumn *sel_column = NULL;
890 GtkTreeViewColumn *view_column = NULL;
892 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
893 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
895 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
897 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(view_column), cell, func,
902 hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
903 GtkCellRenderer *cell)
905 HildonTouchSelectorColumn *sel_column = NULL;
906 GtkTreeViewColumn *view_column = NULL;
908 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
909 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
911 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
913 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (view_column), cell);
917 hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout,
918 GtkCellRenderer *cell,
921 HildonTouchSelectorColumn *sel_column = NULL;
922 GtkTreeViewColumn *view_column = NULL;
924 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
925 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
927 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
929 gtk_cell_layout_reorder (GTK_CELL_LAYOUT(view_column), cell, position);
933 hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout)
935 HildonTouchSelectorColumn *sel_column = NULL;
936 GtkTreeViewColumn *view_column = NULL;
938 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout), NULL);
939 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
941 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
943 return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(view_column));
946 /* ------------------------------ PUBLIC METHODS ---------------------------- */
949 * hildon_touch_selector_new:
951 * Creates a new empty #HildonTouchSelector.
953 * Returns: a new #HildonTouchSelector.
958 hildon_touch_selector_new (void)
960 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL);
964 * hildon_touch_selector_new_text:
966 * Creates a #HildonTouchSelector with a single text column that
967 * can be populated conveniently through hildon_touch_selector_append_text(),
968 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
970 * Returns: A new #HildonTouchSelector
975 hildon_touch_selector_new_text (void)
979 HildonTouchSelectorColumn *column = NULL;
981 selector = hildon_touch_selector_new ();
982 store = gtk_list_store_new (1, G_TYPE_STRING);
984 column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
985 GTK_TREE_MODEL (store), TRUE);
987 g_object_set (G_OBJECT (column), "text-column", 0, NULL);
993 * hildon_touch_selector_append_text:
994 * @selector: A #HildonTouchSelector.
995 * @text: a non %NULL text string.
997 * Appends a new entry in a #HildonTouchSelector created with
998 * hildon_touch_selector_new_text().
1003 hildon_touch_selector_append_text (HildonTouchSelector * selector,
1007 GtkTreeModel *model;
1009 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1010 g_return_if_fail (text != NULL);
1012 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1014 g_return_if_fail (GTK_IS_LIST_STORE (model));
1016 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1017 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1021 * hildon_touch_selector_prepend_text:
1022 * @selector: A #HildonTouchSelector.
1023 * @text: a non %NULL text string.
1025 * Prepends a new entry in a #HildonTouchSelector created with
1026 * hildon_touch_selector_new_text().
1031 hildon_touch_selector_prepend_text (HildonTouchSelector * selector,
1035 GtkTreeModel *model;
1037 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1038 g_return_if_fail (text != NULL);
1040 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1042 g_return_if_fail (GTK_IS_LIST_STORE (model));
1044 gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
1045 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1049 * hildon_touch_selector_insert_text:
1050 * @selector: a #HildonTouchSelector.
1051 * @position: the position to insert @text.
1052 * @text: A non %NULL text string.
1054 * Inserts a new entry in particular position of a #HildoTouchSelector created
1055 * with hildon_touch_selector_new_text().
1060 hildon_touch_selector_insert_text (HildonTouchSelector * selector,
1061 gint position, const gchar * text)
1064 GtkTreeModel *model;
1066 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1067 g_return_if_fail (text != NULL);
1068 g_return_if_fail (position >= 0);
1070 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1072 g_return_if_fail (GTK_IS_LIST_STORE (model));
1074 gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position);
1075 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1079 * hildon_touch_selector_append_column
1080 * @selector: a #HildonTouchSelector
1081 * @model: the #GtkTreeModel with the data of the column
1082 * @cell_renderer: The #GtkCellRenderer where to draw each row contents.
1083 * @Varargs: a %NULL-terminated pair of attributes and column numbers.
1085 * This functions adds a new column to the widget, whose data will
1086 * be obtained from the model. Only widgets added this way should used on
1087 * the selection logic, i.e., the print function, the #HildonTouchPicker::changed
1090 * You can optionally pass a #GtkCellRenderer in @cell_renderer,
1091 * together with a %NULL-terminated list of pairs property/value, in
1092 * the same way you would use gtk_tree_view_column_set_attributes().
1093 * This will pack @cell_renderer at the start of the column, expanded by default.
1094 * If you prefer not to add it this way, you can simply pass %NULL to @cell_renderer
1095 * and use the #GtkCellLayout interface on the returned #HildonTouchSelectorColumn
1096 * to set your renderers.
1098 * There is a prerequisite to be considered on models used: text data must
1099 * be in the first column.
1101 * This method basically adds a #GtkTreeView to the widget, using the model and
1102 * the data received.
1104 * Returns: the new column added added, %NULL otherwise.
1109 HildonTouchSelectorColumn*
1110 hildon_touch_selector_append_column (HildonTouchSelector * selector,
1111 GtkTreeModel * model,
1112 GtkCellRenderer * cell_renderer, ...)
1115 HildonTouchSelectorColumn *new_column = NULL;
1116 gboolean emit_changed = FALSE;
1119 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1120 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1122 if (model != NULL) {
1124 va_start (args, cell_renderer);
1125 new_column = _create_new_column (selector, model, &emit_changed, cell_renderer, args);
1128 selector->priv->columns = g_slist_append (selector->priv->columns,
1130 gtk_box_pack_start (GTK_BOX (selector->priv->hbox),
1131 new_column->priv->panarea,
1134 gtk_widget_show_all (new_column->priv->panarea);
1136 if (selector->priv->initial_scroll) {
1137 _hildon_touch_selector_center_on_selected_items (selector, new_column);
1144 g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1146 colnum = g_slist_length (selector->priv->columns);
1147 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, colnum);
1154 * hildon_touch_selector_append_text_column
1155 * @selector: a #HildonTouchSelector
1156 * @model: a #GtkTreeModel with data for the column
1157 * @center: whether to center the text on the column
1159 * Equivalent to hildon_touch_selector_append_column(), but using a
1160 * default text cell renderer. This is the most common use case of the
1163 * Returns: the new column added, NULL otherwise.
1167 HildonTouchSelectorColumn*
1168 hildon_touch_selector_append_text_column (HildonTouchSelector * selector,
1169 GtkTreeModel * model, gboolean center)
1171 GtkCellRenderer *renderer = NULL;
1172 GValue val = { 0, };
1174 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1175 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1177 if (model != NULL) {
1178 renderer = gtk_cell_renderer_text_new ();
1181 g_value_init (&val, G_TYPE_FLOAT);
1182 g_value_set_float (&val, 0.5);
1183 g_object_set_property (G_OBJECT (renderer), "xalign", &val);
1186 return hildon_touch_selector_append_column (selector, model, renderer,
1194 * hildon_touch_selector_remove_column:
1195 * @selector: a #HildonTouchSelector
1196 * @column: the position of the column to be removed
1198 * Removes a column from @selector.
1200 * Returns: %TRUE if the column was removed, %FALSE otherwise
1205 hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column)
1207 HildonTouchSelectorColumn *current_column = NULL;
1208 HildonTouchSelectorPrivate *priv;
1210 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1211 g_return_val_if_fail (column <
1212 hildon_touch_selector_get_num_columns (selector), FALSE);
1214 priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
1215 current_column = g_slist_nth_data (priv->columns, column);
1217 gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->priv->panarea);
1218 priv->columns = g_slist_remove (priv->columns, current_column);
1219 g_object_unref (current_column);
1221 g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1227 * hildon_touch_selector_set_column_attributes:
1228 * @selector: a #HildonTouchSelector
1229 * @num_column: the number of the column whose attributes we're setting
1230 * @cell_renderer: the #GtkCellRendere we're setting the attributes of
1231 * @Varargs: A %NULL-terminated list of attributes.
1233 * Sets the attributes for the given column. The attributes must be given
1234 * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes().
1235 * All existing attributes are removed and replaced with the new ones.
1237 * Deprecated: #HildonTouchSelectorColumn implements #GtkCellLayout, use this
1238 * interface instead. See
1239 * hildon_touch_selector_get_column().
1244 hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector,
1246 GtkCellRenderer * cell_renderer,
1250 GtkTreeViewColumn *tree_column = NULL;
1251 HildonTouchSelectorColumn *current_column = NULL;
1252 gchar *attribute = NULL;
1255 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1256 g_return_if_fail (num_column <
1257 hildon_touch_selector_get_num_columns (selector));
1259 current_column = g_slist_nth_data (selector->priv->columns, num_column);
1261 tree_column = gtk_tree_view_get_column (current_column->priv->tree_view, 0);
1262 gtk_tree_view_remove_column (current_column->priv->tree_view, tree_column);
1264 tree_column = gtk_tree_view_column_new ();
1265 gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE);
1267 va_start (args, cell_renderer);
1268 attribute = va_arg (args, gchar *);
1270 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1272 while (attribute != NULL) {
1273 value = va_arg (args, gint);
1274 gtk_tree_view_column_add_attribute (tree_column, cell_renderer,
1276 attribute = va_arg (args, gchar *);
1281 gtk_tree_view_append_column (current_column->priv->tree_view, tree_column);
1285 * hildon_touch_selector_get_num_columns:
1286 * @selector: a #HildonTouchSelector
1288 * Gets the number of columns in the #HildonTouchSelector.
1290 * Returns: the number of columns in @selector.
1295 hildon_touch_selector_get_num_columns (HildonTouchSelector * selector)
1297 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1299 return g_slist_length (selector->priv->columns);
1303 * hildon_touch_selector_get_column_selection_mode:
1304 * @selector: a #HildonTouchSelector
1306 * Gets the selection mode of @selector.
1308 * Returns: one of #HildonTouchSelectorSelectionMode
1312 HildonTouchSelectorSelectionMode
1313 hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector)
1315 HildonTouchSelectorSelectionMode result =
1316 HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1317 GtkSelectionMode treeview_mode = GTK_SELECTION_BROWSE;
1318 HildonTouchSelectorColumn *column = NULL;
1319 GtkTreeSelection *selection = NULL;
1321 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result);
1322 g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0,
1325 column = HILDON_TOUCH_SELECTOR_COLUMN (selector->priv->columns->data);
1327 selection = gtk_tree_view_get_selection (column->priv->tree_view);
1328 treeview_mode = gtk_tree_selection_get_mode (selection);
1331 if (treeview_mode == GTK_SELECTION_MULTIPLE) {
1332 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE;
1334 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1341 * hildon_touch_selector_set_column_selection_mode:
1342 * @selector: a #HildonTouchSelector
1343 * @mode: the #HildonTouchSelectorMode for @selector
1345 * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode.
1350 hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
1351 HildonTouchSelectorSelectionMode mode)
1353 GtkTreeView *tv = NULL;
1354 HildonTouchSelectorColumn *column = NULL;
1355 GtkTreeSelection *selection = NULL;
1356 GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE;
1358 HildonTouchSelectorSelectionMode current_mode;
1360 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1361 g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0);
1363 current_mode = hildon_touch_selector_get_column_selection_mode (selector);
1365 if (current_mode == mode) {
1369 column = HILDON_TOUCH_SELECTOR_COLUMN ((g_slist_nth (selector->priv->columns, 0))->data);
1370 tv = column->priv->tree_view;
1374 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE:
1375 treeview_mode = GTK_SELECTION_BROWSE;
1377 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE:
1378 treeview_mode = GTK_SELECTION_MULTIPLE;
1382 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1383 gtk_tree_selection_set_mode (selection, treeview_mode);
1385 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1386 gtk_tree_model_get_iter_first (column->priv->model, &iter);
1387 gtk_tree_selection_unselect_all (selection);
1388 gtk_tree_selection_select_iter (selection, &iter);
1390 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
1396 * hildon_touch_selector_set_print_func:
1397 * @selector: a #HildonTouchSelector
1398 * @func: a #HildonTouchSelectorPrintFunc function
1400 * Sets the function to be used by hildon_touch_selector_get_current_text()
1401 * to produce a text representation of the currently selected items in @selector.
1402 * The default function will return a concatenation of comma separated items
1403 * selected in each column in @selector. Use this to override this method if you
1404 * need a particular representation for your application.
1409 hildon_touch_selector_set_print_func (HildonTouchSelector * selector,
1410 HildonTouchSelectorPrintFunc func)
1412 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1414 selector->priv->print_func = func;
1418 * hildon_touch_selector_get_print_func:
1419 * @selector: a #HildonTouchSelector
1421 * Gets the #HildonTouchSelectorPrintFunc currently used. See
1422 * hildon_touch_selector_set_print_func().
1424 * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default
1425 * one is currently used.
1427 HildonTouchSelectorPrintFunc
1428 hildon_touch_selector_get_print_func (HildonTouchSelector * selector)
1430 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1432 return selector->priv->print_func;
1436 * hildon_touch_selector_set_active:
1437 * @selector: a #HildonTouchSelector
1438 * @column: column number
1439 * @index: the index of the item to select, or -1 to have no active item
1441 * Sets the active item of the #HildonTouchSelector to @index. The
1442 * column number is taken from @column.
1444 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1449 hildon_touch_selector_set_active (HildonTouchSelector *selector,
1453 GtkTreeSelection *selection = NULL;
1454 HildonTouchSelectorColumn *current_column = NULL;
1455 HildonTouchSelectorSelectionMode mode;
1458 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1459 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1460 mode = hildon_touch_selector_get_column_selection_mode (selector);
1461 g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
1463 current_column = g_slist_nth_data (selector->priv->columns, column);
1465 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1466 path = gtk_tree_path_new_from_indices (index, -1);
1467 gtk_tree_selection_unselect_all (selection);
1469 gtk_tree_selection_select_path (selection, path);
1471 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
1473 gtk_tree_path_free (path);
1477 * hildon_touch_selector_get_active:
1478 * @selector: a #HildonTouchSelector
1479 * @column: column number
1481 * Returns the index of the currently active item in column number
1482 * @column, or -1 if there's no active item.
1484 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1486 * Returns: an integer which is the index of the currently active
1487 * item, or -1 if there's no active item.
1492 hildon_touch_selector_get_active (HildonTouchSelector *selector,
1495 GtkTreeSelection *selection = NULL;
1496 HildonTouchSelectorColumn *current_column = NULL;
1497 HildonTouchSelectorSelectionMode mode;
1498 GtkTreeModel *model;
1503 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1504 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1);
1505 mode = hildon_touch_selector_get_column_selection_mode (selector);
1506 g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1);
1508 current_column = g_slist_nth_data (selector->priv->columns, column);
1510 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1511 model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_column->priv->tree_view));
1513 gtk_tree_selection_get_selected (selection, NULL, &iter);
1514 path = gtk_tree_model_get_path (model, &iter);
1515 index = (gtk_tree_path_get_indices (path))[0];
1517 gtk_tree_path_free (path);
1523 * hildon_touch_selector_get_selected:
1524 * @selector: a #HildonTouchSelector
1525 * @column: the column number we want to get the element
1526 * @iter: #GtkTreeIter currently selected
1528 * Sets @iter to the currently selected node on the nth-column, if selection is
1529 * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with
1530 * a column different that the first one. @iter may be %NULL if you just want to
1531 * test if selection has any selected items.
1533 * This function will not work if selection is in
1534 * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one.
1536 * See gtk_tree_selection_get_selected() for more information.
1538 * Returns: %TRUE if @iter was correctly set, %FALSE otherwise
1543 hildon_touch_selector_get_selected (HildonTouchSelector * selector,
1544 gint column, GtkTreeIter * iter)
1546 GtkTreeSelection *selection = NULL;
1547 HildonTouchSelectorColumn *current_column = NULL;
1548 HildonTouchSelectorSelectionMode mode;
1550 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1551 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1553 mode = hildon_touch_selector_get_column_selection_mode (selector);
1554 g_return_val_if_fail
1555 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) ||
1556 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)),
1559 current_column = g_slist_nth_data (selector->priv->columns, column);
1562 gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1564 return gtk_tree_selection_get_selected (selection, NULL, iter);
1568 * hildon_touch_selector_select_iter
1569 * @selector: a #HildonTouchSelector
1570 * @column: the column to selects
1571 * @iter: the #GtkTreeIter to be selected
1572 * @scroll_to: whether to smoothly scroll to the item
1574 * Sets the currently selected item in the column @column to the one pointed by @iter,
1575 * optionally smoothly scrolling to it.
1580 hildon_touch_selector_select_iter (HildonTouchSelector * selector,
1581 gint column, GtkTreeIter * iter,
1585 GtkTreeModel *model;
1586 HildonTouchSelectorColumn *current_column = NULL;
1587 GtkTreeView *tv = NULL;
1588 GtkTreeSelection *selection = NULL;
1590 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1591 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1593 current_column = g_slist_nth_data (selector->priv->columns, column);
1595 tv = current_column->priv->tree_view;
1596 selection = gtk_tree_view_get_selection (tv);
1597 model = gtk_tree_view_get_model (tv);
1598 path = gtk_tree_model_get_path (model, iter);
1600 gtk_tree_selection_select_iter (selection, iter);
1603 hildon_touch_selector_scroll_to (current_column, tv, path);
1606 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
1608 gtk_tree_path_free (path);
1612 * hildon_touch_selector_unselect_iter
1613 * @selector: a #HildonTouchSelector
1614 * @column: the column to unselects from
1615 * @iter: the #GtkTreeIter to be unselected
1617 * Unselect the item pointed by @iter in the column @column
1622 void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector,
1626 HildonTouchSelectorColumn *current_column = NULL;
1627 GtkTreeSelection *selection = NULL;
1629 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1630 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1632 current_column = g_slist_nth_data (selector->priv->columns, column);
1633 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1634 gtk_tree_selection_unselect_iter (selection, iter);
1636 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
1640 * hildon_touch_selector_unselect_all:
1641 * @selector: a #HildonTouchSelector
1642 * @column: the position of the column to get the selected rows from
1644 * Unselects all the selected items in the column @column.
1649 hildon_touch_selector_unselect_all (HildonTouchSelector * selector,
1652 HildonTouchSelectorColumn *current_column = NULL;
1653 GtkTreeSelection *selection = NULL;
1655 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1656 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1658 current_column = g_slist_nth_data (selector->priv->columns, column);
1659 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1660 gtk_tree_selection_unselect_all (selection);
1662 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
1666 * hildon_touch_selector_get_selected_rows:
1667 * @selector: a #HildonTouchSelector
1668 * @column: the position of the column to get the selected rows from
1670 * Creates a list of #GtkTreePath<!-- -->s of all selected rows in a column. Additionally,
1671 * if you to plan to modify the model after calling this function, you may
1672 * want to convert the returned list into a list of GtkTreeRowReferences. To do this,
1673 * you can use gtk_tree_row_reference_new().
1675 * See gtk_tree_selection_get_selected_rows() for more information.
1677 * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column.
1682 hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector,
1685 GList *result = NULL;
1686 HildonTouchSelectorColumn *current_column = NULL;
1687 GtkTreeSelection *selection = NULL;
1689 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1690 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1693 current_column = g_slist_nth_data (selector->priv->columns, column);
1694 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1696 result = gtk_tree_selection_get_selected_rows (selection, NULL);
1702 * hildon_touch_selector_get_model:
1703 * @selector: a #HildonTouchSelector
1704 * @column: the position of the column in @selector
1706 * Gets the model of a column of @selector.
1708 * Returns: the #GtkTreeModel for the column @column of @selector.
1713 hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column)
1715 HildonTouchSelectorColumn *current_column = NULL;
1717 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1718 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1721 current_column = g_slist_nth_data (selector->priv->columns, column);
1723 return current_column->priv->model;
1727 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
1728 gint column, GtkTreeModel * model)
1730 HildonTouchSelectorColumn *current_column = NULL;
1733 HILDON_TOUCH_SELECTOR_COLUMN (g_slist_nth_data (selector->priv->columns, column));
1735 current_column->priv->model = model;
1736 gtk_tree_view_set_model (current_column->priv->tree_view,
1737 current_column->priv->model);
1741 * hildon_touch_selector_set_model:
1742 * @selector: a #HildonTouchSelector
1743 * @column: the position of the column to set the model to
1744 * @model: a #GtkTreeModel
1746 * Sets the #GtkTreeModel for a particular column in @model.
1751 hildon_touch_selector_set_model (HildonTouchSelector * selector,
1752 gint column, GtkTreeModel * model)
1754 g_return_if_fail (HILDON_TOUCH_SELECTOR (selector));
1755 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1757 HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model);
1761 * hildon_touch_selector_get_current_text:
1762 * @selector: a #HildonTouchSelector
1764 * Returns a string representing the currently selected items for
1765 * each column of @selector. See hildon_touch_selector_set_print_func().
1767 * Returns: a newly allocated string.
1772 hildon_touch_selector_get_current_text (HildonTouchSelector * selector)
1774 gchar *result = NULL;
1775 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1777 if (selector->priv->print_func) {
1778 result = (*selector->priv->print_func) (selector);
1780 result = _default_print_func (selector);
1787 search_nearest_element (HildonPannableArea *panarea,
1789 GList *selected_rows,
1790 GtkTreePath **nearest_path)
1792 GtkAdjustment *adj = NULL;
1793 gdouble target_value = 0;
1796 GtkTreePath *path = NULL;
1798 gdouble nearest_distance = -1;
1799 gdouble current_distance = -1;
1800 GtkTreePath *result_path = NULL;
1802 g_assert (nearest_path != NULL);
1804 if (selected_rows == NULL) {
1805 *nearest_path = NULL;
1809 adj = hildon_pannable_area_get_vadjustment (panarea);
1810 g_return_if_fail (adj != NULL);
1812 /* we add this in order to check the nearest to the center of
1814 target_value = gtk_adjustment_get_value (adj) + adj->page_size/2;
1816 path = result_path = selected_rows->data;
1817 gtk_tree_view_get_background_area (tv, path, NULL, &rect);
1818 gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
1819 nearest_distance = abs (target_value - y);
1821 for (iter = selected_rows->next; iter; iter = g_list_next (iter)) {
1822 gtk_tree_view_get_background_area (tv, path, NULL, &rect);
1823 gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
1824 current_distance = abs (target_value - y);
1825 if (current_distance < nearest_distance) {
1826 nearest_distance = current_distance;
1831 *nearest_path = result_path;
1835 on_realize_cb (GtkWidget *widget,
1838 HildonTouchSelectorColumn *column = NULL;
1842 column = HILDON_TOUCH_SELECTOR_COLUMN (data);
1844 if (column->priv->initial_path) {
1845 gtk_tree_view_get_background_area (GTK_TREE_VIEW (column->priv->tree_view),
1846 column->priv->initial_path, NULL, &rect);
1847 gtk_tree_view_convert_bin_window_to_tree_coords
1848 (GTK_TREE_VIEW (column->priv->tree_view),
1849 0, rect.y, NULL, &y);
1851 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (column->priv->panarea),
1854 gtk_tree_path_free (column->priv->initial_path);
1856 column->priv->initial_path = NULL;
1860 g_signal_handler_disconnect (column->priv->panarea,
1861 column->priv->realize_handler);
1867 hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
1871 if (GTK_WIDGET_REALIZED (column->priv->panarea)) {
1875 gtk_tree_view_get_background_area (tv,
1877 gtk_tree_view_convert_bin_window_to_tree_coords (tv,
1878 0, rect.y, NULL, &y);
1880 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA
1881 (column->priv->panarea), -1, y);
1883 if (column->priv->realize_handler != 0) {
1885 if (column->priv->initial_path) {
1886 gtk_tree_path_free (column->priv->initial_path);
1887 column->priv->initial_path = NULL;
1890 g_signal_handler_disconnect (column->priv->panarea,
1891 column->priv->realize_handler);
1892 column->priv->realize_handler = 0;
1895 column->priv->initial_path = gtk_tree_path_copy (path);
1896 column->priv->realize_handler =
1897 g_signal_connect_after (G_OBJECT (column->priv->panarea), "realize",
1898 G_CALLBACK (on_realize_cb),
1905 * Center on the selected item of a concrete column
1907 * Returns: TRUE if was able to do that
1911 _hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
1912 HildonTouchSelectorColumn *column)
1914 GtkTreePath *path = NULL;
1915 GList *selected_rows = NULL;
1916 gint num_column = -1;
1918 num_column = g_slist_index (selector->priv->columns, column);
1920 selected_rows = hildon_touch_selector_get_selected_rows (selector, num_column);
1921 if (selected_rows) {
1922 search_nearest_element (HILDON_PANNABLE_AREA (column->priv->panarea),
1923 GTK_TREE_VIEW (column->priv->tree_view),
1928 hildon_touch_selector_scroll_to (column,
1929 GTK_TREE_VIEW (column->priv->tree_view),
1935 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
1936 g_list_free (selected_rows);
1943 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1945 HildonTouchSelectorSelectionMode mode;
1948 n_columns = hildon_touch_selector_get_num_columns (selector);
1949 mode = hildon_touch_selector_get_column_selection_mode (selector);
1951 return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE));
1955 * hildon_touch_selector_has_multiple_selection:
1956 * @selector: A #HildonTouchSelector
1958 * Determines whether @selector is complex enough to actually require an
1959 * extra selection step than only picking an item. This is normally %TRUE
1960 * if @selector has multiple columns, multiple selection, or when it is a
1961 * more complex widget, like #HildonTouchSelectorEntry.
1963 * This information is useful for widgets containing a #HildonTouchSelector,
1964 * like #HildonPickerDialog, that could need a "Done" button, in case that
1965 * its internal #HildonTouchSelector has multiple columns, for instance.
1967 * Returns: %TRUE if @selector requires multiple selection steps.
1972 hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
1974 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1976 return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector);
1981 * hildon_touch_selector_get_column:
1982 * @selector: A #HildonTouchSelector
1983 * @column: a column number
1985 * Use this method to retrieve a #HildonTouchSelectorColumn. Then, you can use
1986 * the #GtkCellLayout interface to set up the layout of the column.
1988 * Returns: the @column<!-- -->-th #HildonTouchSelectorColumn in @selector
1992 HildonTouchSelectorColumn *
1993 hildon_touch_selector_get_column (HildonTouchSelector * selector,
1996 gint num_columns = -1;
1998 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1999 num_columns = hildon_touch_selector_get_num_columns (selector);
2000 g_return_val_if_fail (column < num_columns && column >= 0, NULL);
2002 return g_slist_nth_data (selector->priv->columns, column);
2007 * hildon_touch_selector_center_on_selected:
2008 * @selector: a #HildonTouchSelector
2010 * Ensures all the columns in a #HildonTouchSelector show a selected
2011 * item. If one of the columns is in
2012 * %HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE mode, that column
2013 * will be scrolled to ensure the selected item that is closest to the
2014 * currently visible area is shown.
2019 hildon_touch_selector_center_on_selected (HildonTouchSelector *selector)
2021 GSList *iter = NULL;
2023 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2025 for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) {
2026 _hildon_touch_selector_center_on_selected_items (selector,
2027 HILDON_TOUCH_SELECTOR_COLUMN (iter->data));