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"
174 #include "hildon-touch-selector-private.h"
176 #define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj) \
177 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
179 G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX)
182 * IMPLEMENTATION NOTES:
183 * Struct to maintain the data of each column. The columns are the elements
184 * of the widget that belongs properly to the selection behaviour. Although
185 * internally the columns are arranged in a private #GtkHBox, as the selector
186 * itself is a #GtkVBox, you can add more widgets, like buttons etc., so
187 * you finally could have a widget with more elements that the columns, but
188 * this doesn't belongs to the selection logic
190 struct _HildonTouchSelectorColumnPrivate
192 HildonTouchSelector *parent; /* the selector that contains this column */
195 GtkTreeView *tree_view;
196 gulong realize_handler;
197 GtkTreePath *initial_path;
199 GtkWidget *panarea; /* the pannable widget */
202 struct _HildonTouchSelectorPrivate
204 GSList *columns; /* the selection columns */
205 GtkWidget *hbox; /* the container for the selector's columns */
206 gboolean initial_scroll; /* whether initial fancy scrolling to selection */
208 gboolean changed_blocked;
210 HildonTouchSelectorPrintFunc print_func;
211 gpointer print_user_data;
212 GDestroyNotify print_destroy_func;
217 PROP_HAS_MULTIPLE_SELECTION = 1,
228 static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 };
231 hildon_touch_selector_dispose (GObject * object);
234 hildon_touch_selector_get_property (GObject * object,
239 hildon_touch_selector_set_property (GObject *object,
246 static void hildon_touch_selector_remove (GtkContainer * container,
248 /* private functions */
249 static void _row_tapped_cb (GtkTreeView * tree_view,
252 static gchar *_default_print_func (HildonTouchSelector * selector,
255 static HildonTouchSelectorColumn *_create_new_column (HildonTouchSelector * selector,
256 GtkTreeModel * model,
257 gboolean *emit_changed,
258 GtkCellRenderer * renderer,
261 on_realize_cb (GtkWidget *widget,
264 on_row_changed (GtkTreeModel *model,
270 hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
274 _hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
275 HildonTouchSelectorColumn *column);
277 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
279 GtkTreeModel * model);
281 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector);
284 hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector,
287 /* GtkCellLayout implementation (HildonTouchSelectorColumn)*/
288 static void hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface);
290 static void hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
291 GtkCellRenderer *cell,
293 static void hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
294 GtkCellRenderer *cell,
296 static void hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout);
297 static void hildon_touch_selector_column_cell_layout_add_attribute(GtkCellLayout *cell_layout,
298 GtkCellRenderer *cell,
299 const gchar *attribute,
301 static void hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
302 GtkCellRenderer *cell,
303 GtkCellLayoutDataFunc func,
305 GDestroyNotify destroy);
306 static void hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
307 GtkCellRenderer *cell);
308 static void hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout,
309 GtkCellRenderer *cell,
311 static GList *hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout);
315 hildon_touch_selector_class_init (HildonTouchSelectorClass * class)
317 GObjectClass *gobject_class;
318 GtkObjectClass *object_class;
319 GtkContainerClass *container_class;
321 gobject_class = G_OBJECT_CLASS (class);
322 object_class = GTK_OBJECT_CLASS (class);
323 container_class = GTK_CONTAINER_CLASS (class);
326 gobject_class->dispose = hildon_touch_selector_dispose;
327 gobject_class->get_property = hildon_touch_selector_get_property;
328 gobject_class->set_property = hildon_touch_selector_set_property;
333 container_class->remove = hildon_touch_selector_remove;
335 /* HildonTouchSelector */
336 class->changed = NULL;
337 class->set_model = _hildon_touch_selector_set_model;
339 class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection;
343 * HildonTouchSelector::changed:
344 * @widget: the object which received the signal
345 * @column: the number of the column that has changed
347 * The "changed" signal is emitted when the active item on any column is changed.
348 * This can be due to the user selecting a different item from the list, or
349 * due to a call to hildon_touch_selector_select_iter() on one of the columns.
353 hildon_touch_selector_signals[CHANGED] =
354 g_signal_new ("changed",
355 G_OBJECT_CLASS_TYPE (class),
357 G_STRUCT_OFFSET (HildonTouchSelectorClass, changed),
359 g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
362 * HildonTouchSelector::columns-changed:
363 * @selector: the object which received the signal
365 * The "columns-changed" signal is emitted when the number
366 * of columns in the #HildonTouchSelector change.
370 hildon_touch_selector_signals[COLUMNS_CHANGED] =
371 g_signal_new ("columns-changed",
372 G_OBJECT_CLASS_TYPE (class),
373 G_SIGNAL_RUN_LAST, 0,
375 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
379 g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION,
380 g_param_spec_boolean ("has-multiple-selection",
381 "has multiple selection",
382 "Whether the widget has multiple "
383 "selection (like multiple columns, "
384 "multiselection mode, or multiple "
385 "internal widgets) and therefore "
386 "it may need a confirmation button, "
391 g_object_class_install_property (G_OBJECT_CLASS (gobject_class),
393 g_param_spec_boolean ("initial-scroll",
395 "Whether to scroll to the"
396 "current selection when"
397 "the selector is first"
400 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
402 /* style properties */
403 /* We need to ensure fremantle mode for the treeview in order to work
404 properly. This is not about the appearance, this is about behaviour */
405 gtk_rc_parse_string ("style \"fremantle-htst\" {\n"
406 " GtkWidget::hildon-mode = 1\n"
407 "} widget \"*.fremantle-htst\" style \"fremantle-htst\""
408 "widget_class \"*<HildonPannableArea>.GtkTreeView\" style :highest \"fremantle-htst\"");
410 g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate));
414 hildon_touch_selector_get_property (GObject * object,
416 GValue * value, GParamSpec * pspec)
418 HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
421 case PROP_HAS_MULTIPLE_SELECTION:
422 g_value_set_boolean (value,
423 hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object)));
425 case PROP_INITIAL_SCROLL:
426 g_value_set_boolean (value, priv->initial_scroll);
429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
435 hildon_touch_selector_set_property (GObject *object, guint prop_id,
436 const GValue *value, GParamSpec *pspec)
438 HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
441 case PROP_INITIAL_SCROLL:
442 priv->initial_scroll = g_value_get_boolean (value);
445 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
452 hildon_touch_selector_init (HildonTouchSelector * selector)
454 selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
456 GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
457 gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
459 selector->priv->columns = NULL;
461 selector->priv->print_func = NULL;
462 selector->priv->print_user_data = NULL;
463 selector->priv->print_destroy_func = NULL;
464 selector->priv->initial_scroll = TRUE;
465 selector->priv->hbox = gtk_hbox_new (FALSE, 0);
467 selector->priv->changed_blocked = FALSE;
469 gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
471 gtk_widget_show (selector->priv->hbox);
475 hildon_touch_selector_dispose (GObject * object)
477 GObjectClass *gobject_class;
479 hildon_touch_selector_set_print_func_full (HILDON_TOUCH_SELECTOR (object),
482 gobject_class = G_OBJECT_CLASS (hildon_touch_selector_parent_class);
484 if (gobject_class->dispose)
485 (* gobject_class->dispose) (object);
489 * IMPLEMENTATION NOTES:
490 * Some people sent questions regarding a missing dispose/finalize function on
491 * this widget that could lead to leak memory, so we will clarify this topic.
493 * This is not required as #HildonTouchSelector extends #GtkContainer. When the
494 * widget is freed, the #GtkContainer freeing memory functions are called. This
495 * process includes remove each widget individually, so all the widgets are
498 * In the same way, this widget redefines gtk_container->remove function, in
499 * order to free the column related information if it is required.
501 * Please take a look to hildon_touch_selector_remove for more information.
504 /*------------------------------ GtkContainer ------------------------------ */
507 * Required in order to free the column at the columns list
510 hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
512 HildonTouchSelector *selector = NULL;
514 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container));
515 selector = HILDON_TOUCH_SELECTOR (container);
517 /* Remove the extra data related to the columns, if required. */
518 if (widget == selector->priv->hbox) {
519 g_slist_foreach (selector->priv->columns, (GFunc) g_object_unref, NULL);
521 g_slist_free (selector->priv->columns);
523 selector->priv->columns = NULL;
525 g_debug ("Freeing a widget outside the columns logic");
528 /* Now remove the widget itself from the container */
529 GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget);
532 /* ------------------------------ PRIVATE METHODS ---------------------------- */
534 hildon_touch_selector_block_changed (HildonTouchSelector *selector)
536 selector->priv->changed_blocked = TRUE;
540 hildon_touch_selector_unblock_changed (HildonTouchSelector *selector)
542 selector->priv->changed_blocked = FALSE;
546 hildon_touch_selector_emit_value_changed (HildonTouchSelector *selector,
549 if (!selector->priv->changed_blocked) {
550 g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
555 * default_print_func:
556 * @selector: a #HildonTouchSelector
558 * Default print function
560 * Returns: a new string that represents the selected items
565 _default_print_func (HildonTouchSelector * selector, gpointer user_data)
567 gchar *result = NULL;
569 gint num_columns = 0;
571 GtkTreeModel *model = NULL;
572 gchar *current_string = NULL;
574 HildonTouchSelectorSelectionMode mode;
576 GtkTreePath *current_path = NULL;
577 GList *selected_rows = NULL;
578 gint initial_value = 0;
579 gint text_column = -1;
580 HildonTouchSelectorColumn *column = NULL;
582 num_columns = hildon_touch_selector_get_num_columns (selector);
584 mode = hildon_touch_selector_get_column_selection_mode (selector);
586 if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
587 && (num_columns > 0)) {
588 /* In this case we get the first column first */
589 selected_rows = hildon_touch_selector_get_selected_rows (selector, 0);
590 model = hildon_touch_selector_get_model (selector, 0);
591 column = hildon_touch_selector_get_column (selector, 0);
592 g_object_get (G_OBJECT(column), "text-column", &text_column, NULL);
594 result = g_strdup_printf ("(");
596 for (item = selected_rows; item; item = g_list_next (item)) {
597 current_path = item->data;
598 gtk_tree_model_get_iter (model, &iter, current_path);
600 if (text_column != -1) {
601 gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1);
604 if (i < g_list_length (selected_rows) - 1) {
605 aux = g_strconcat (result, current_string, ",", NULL);
609 aux = g_strconcat (result, current_string, NULL);
614 if (current_string) {
615 g_free (current_string);
616 current_string = NULL;
622 aux = g_strconcat (result, ")", NULL);
626 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
627 g_list_free (selected_rows);
633 for (i = initial_value; i < num_columns; i++) {
634 model = hildon_touch_selector_get_model (selector, i);
635 column = hildon_touch_selector_get_column (selector, i);
636 g_object_get (G_OBJECT(column), "text-column", &text_column, NULL);
638 if (hildon_touch_selector_get_selected (selector, i, &iter)) {
639 if (text_column == -1 ) {
640 g_warning ("Trying to use the default print function in HildonTouchSelector, but "
641 "\"text-column\" property is not set for HildonTouchSelectorColumn %p.", column);
642 current_string = NULL;
644 gtk_tree_model_get (model, &iter, text_column, ¤t_string, -1);
648 result = current_string;
650 aux = g_strconcat (result, ":", current_string, NULL);
652 g_free (current_string);
653 current_string = NULL;
663 _row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data)
665 HildonTouchSelector *selector = NULL;
666 HildonTouchSelectorColumn *column = NULL;
667 gint num_column = -1;
669 column = HILDON_TOUCH_SELECTOR_COLUMN (user_data);
670 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->priv->parent));
672 selector = column->priv->parent;
674 num_column = g_slist_index (selector->priv->columns, column);
676 hildon_touch_selector_emit_value_changed (selector, num_column);
680 static HildonTouchSelectorColumn *
681 _create_new_column (HildonTouchSelector * selector,
682 GtkTreeModel * model,
683 gboolean *emit_changed,
684 GtkCellRenderer * renderer, va_list args)
686 HildonTouchSelectorColumn *new_column = NULL;
687 GtkTreeViewColumn *tree_column = NULL;
688 GtkTreeView *tv = NULL;
689 GtkWidget *panarea = NULL;
690 GtkTreeSelection *selection = NULL;
695 tree_column = gtk_tree_view_column_new ();
697 if (renderer != NULL) {
698 gtk_tree_view_column_pack_start (tree_column, renderer, TRUE);
700 attribute = va_arg (args, gchar *);
701 while (attribute != NULL) {
702 value = va_arg (args, gint);
703 gtk_tree_view_column_add_attribute (tree_column, renderer, attribute,
705 attribute = va_arg (args, gchar *);
710 tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (HILDON_UI_MODE_EDIT));
712 tv = GTK_TREE_VIEW (gtk_tree_view_new ());
713 #endif /* MAEMO_GTK */
715 gtk_tree_view_set_enable_search (tv, FALSE);
716 GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (tv), GTK_CAN_FOCUS);
718 gtk_tree_view_set_model (tv, model);
719 g_signal_connect (model, "row-changed",
720 G_CALLBACK (on_row_changed), selector);
721 gtk_tree_view_set_rules_hint (tv, TRUE);
723 gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column);
725 new_column = g_object_new (HILDON_TYPE_TOUCH_SELECTOR_COLUMN, NULL);
726 new_column->priv->parent = selector;
728 panarea = hildon_pannable_area_new ();
730 g_object_set (G_OBJECT (panarea),
731 "initial-hint", FALSE, NULL);
733 gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv));
735 new_column->priv->model = model;
736 new_column->priv->tree_view = tv;
737 new_column->priv->panarea = panarea;
738 new_column->priv->realize_handler = 0;
739 new_column->priv->initial_path = NULL;
741 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
742 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
744 /* select the first item */
745 *emit_changed = FALSE;
746 if (gtk_tree_model_get_iter_first (model, &iter)) {
747 gtk_tree_selection_select_iter (selection, &iter);
748 *emit_changed = TRUE;
751 gtk_widget_grab_focus (GTK_WIDGET (tv));
753 /* connect to the hildon-row-tapped signal connection */
754 g_signal_connect (G_OBJECT (tv), "hildon-row-tapped",
755 G_CALLBACK (_row_tapped_cb), new_column);
761 /* ------------------------ HildonTouchSelectorColumn implementation ---------------------- */
762 G_DEFINE_TYPE_WITH_CODE (HildonTouchSelectorColumn, hildon_touch_selector_column, G_TYPE_OBJECT,
763 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
764 hildon_touch_selector_column_cell_layout_init))
772 hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass);
775 hildon_touch_selector_column_get_property (GObject *object, guint property_id,
776 GValue *value, GParamSpec *pspec);
779 hildon_touch_selector_column_set_property (GObject *object, guint property_id,
780 const GValue *value, GParamSpec *pspec);
783 hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column,
786 hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column);
790 hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass)
792 GObjectClass *gobject_class = NULL;
794 gobject_class = G_OBJECT_CLASS (klass);
796 g_type_class_add_private (gobject_class, sizeof (HildonTouchSelectorColumnPrivate));
799 gobject_class->get_property = hildon_touch_selector_column_get_property;
800 gobject_class->set_property = hildon_touch_selector_column_set_property;
802 g_object_class_install_property (G_OBJECT_CLASS(klass),
804 g_param_spec_int ("text-column",
806 "A column in the data source model to get the strings from.",
814 hildon_touch_selector_column_init (HildonTouchSelectorColumn *column)
816 column->priv = G_TYPE_INSTANCE_GET_PRIVATE (column, HILDON_TYPE_TOUCH_SELECTOR_COLUMN,
817 HildonTouchSelectorColumnPrivate);
818 column->priv->text_column = -1;
822 hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column,
825 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column));
826 g_return_if_fail (text_column >= -1);
828 column->priv->text_column = text_column;
830 g_object_notify (G_OBJECT (column), "text-column");
834 hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column)
836 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column), -1);
838 return column->priv->text_column;
842 hildon_touch_selector_column_get_property (GObject *object, guint property_id,
843 GValue *value, GParamSpec *pspec)
845 switch (property_id) {
846 case PROP_TEXT_COLUMN:
847 g_value_set_int (value,
848 hildon_touch_selector_column_get_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object)));
851 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
856 hildon_touch_selector_column_set_property (GObject *object, guint property_id,
857 const GValue *value, GParamSpec *pspec)
859 switch (property_id) {
860 case PROP_TEXT_COLUMN:
861 hildon_touch_selector_column_set_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object),
862 g_value_get_int (value));
865 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
869 /* ------------------------ GtkCellLayout implementation -------------------- */
871 hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface *iface)
873 iface->pack_start = hildon_touch_selector_column_cell_layout_pack_start;
874 iface->pack_end = hildon_touch_selector_column_cell_layout_pack_end;
875 iface->clear = hildon_touch_selector_column_cell_layout_clear;
876 iface->add_attribute = hildon_touch_selector_column_cell_layout_add_attribute;
877 iface->set_cell_data_func = hildon_touch_selector_column_cell_layout_set_cell_data_func;
878 iface->clear_attributes = hildon_touch_selector_column_cell_layout_clear_attributes;
879 iface->reorder = hildon_touch_selector_column_cell_layout_reorder;
880 iface->get_cells = hildon_touch_selector_column_cell_layout_get_cells;
884 hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
885 GtkCellRenderer *cell,
888 HildonTouchSelectorColumn *sel_column = NULL;
889 GtkTreeViewColumn *view_column = NULL;
891 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
892 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
894 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
896 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(view_column), cell, expand);
901 hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
902 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_pack_end (GTK_CELL_LAYOUT(view_column), cell, expand);
917 hildon_touch_selector_column_cell_layout_clear (GtkCellLayout *cell_layout)
919 HildonTouchSelectorColumn *sel_column = NULL;
920 GtkTreeViewColumn *view_column = NULL;
922 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
923 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
925 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
927 gtk_cell_layout_clear (GTK_CELL_LAYOUT(view_column));
931 hildon_touch_selector_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
932 GtkCellRenderer *cell,
933 const gchar *attribute,
936 HildonTouchSelectorColumn *sel_column = NULL;
937 GtkTreeViewColumn *view_column = NULL;
939 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
940 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
942 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
944 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(view_column), cell, attribute, column);
949 hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
950 GtkCellRenderer *cell,
951 GtkCellLayoutDataFunc func,
953 GDestroyNotify destroy)
955 HildonTouchSelectorColumn *sel_column = NULL;
956 GtkTreeViewColumn *view_column = NULL;
958 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
959 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
961 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
963 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(view_column), cell, func,
968 hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
969 GtkCellRenderer *cell)
971 HildonTouchSelectorColumn *sel_column = NULL;
972 GtkTreeViewColumn *view_column = NULL;
974 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
975 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
977 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
979 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (view_column), cell);
983 hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout *cell_layout,
984 GtkCellRenderer *cell,
987 HildonTouchSelectorColumn *sel_column = NULL;
988 GtkTreeViewColumn *view_column = NULL;
990 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
991 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
993 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
995 gtk_cell_layout_reorder (GTK_CELL_LAYOUT(view_column), cell, position);
999 hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout *cell_layout)
1001 HildonTouchSelectorColumn *sel_column = NULL;
1002 GtkTreeViewColumn *view_column = NULL;
1004 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout), NULL);
1005 sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1007 view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1009 return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(view_column));
1012 /* ------------------------------ PUBLIC METHODS ---------------------------- */
1015 * hildon_touch_selector_new:
1017 * Creates a new empty #HildonTouchSelector.
1019 * Returns: a new #HildonTouchSelector.
1024 hildon_touch_selector_new (void)
1026 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL);
1030 * hildon_touch_selector_new_text:
1032 * Creates a #HildonTouchSelector with a single text column that
1033 * can be populated conveniently through hildon_touch_selector_append_text(),
1034 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
1036 * Returns: A new #HildonTouchSelector
1041 hildon_touch_selector_new_text (void)
1043 GtkWidget *selector;
1044 GtkListStore *store;
1045 HildonTouchSelectorColumn *column = NULL;
1047 selector = hildon_touch_selector_new ();
1048 store = gtk_list_store_new (1, G_TYPE_STRING);
1050 column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
1051 GTK_TREE_MODEL (store), TRUE);
1053 g_object_set (G_OBJECT (column), "text-column", 0, NULL);
1059 * hildon_touch_selector_append_text:
1060 * @selector: A #HildonTouchSelector.
1061 * @text: a non %NULL text string.
1063 * Appends a new entry in a #HildonTouchSelector created with
1064 * hildon_touch_selector_new_text().
1069 hildon_touch_selector_append_text (HildonTouchSelector * selector,
1073 GtkTreeModel *model;
1075 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1076 g_return_if_fail (text != NULL);
1078 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1080 g_return_if_fail (GTK_IS_LIST_STORE (model));
1082 gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1083 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1087 * hildon_touch_selector_prepend_text:
1088 * @selector: A #HildonTouchSelector.
1089 * @text: a non %NULL text string.
1091 * Prepends a new entry in a #HildonTouchSelector created with
1092 * hildon_touch_selector_new_text().
1097 hildon_touch_selector_prepend_text (HildonTouchSelector * selector,
1101 GtkTreeModel *model;
1103 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1104 g_return_if_fail (text != NULL);
1106 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1108 g_return_if_fail (GTK_IS_LIST_STORE (model));
1110 gtk_list_store_prepend (GTK_LIST_STORE (model), &iter);
1111 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1115 * hildon_touch_selector_insert_text:
1116 * @selector: a #HildonTouchSelector.
1117 * @position: the position to insert @text.
1118 * @text: A non %NULL text string.
1120 * Inserts a new entry in a particular position of a
1121 * #HildonTouchSelector created with hildon_touch_selector_new_text().
1126 hildon_touch_selector_insert_text (HildonTouchSelector * selector,
1127 gint position, const gchar * text)
1130 GtkTreeModel *model;
1132 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1133 g_return_if_fail (text != NULL);
1134 g_return_if_fail (position >= 0);
1136 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1138 g_return_if_fail (GTK_IS_LIST_STORE (model));
1140 gtk_list_store_insert (GTK_LIST_STORE (model), &iter, position);
1141 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, text, -1);
1145 * hildon_touch_selector_append_column
1146 * @selector: a #HildonTouchSelector
1147 * @model: the #GtkTreeModel with the data of the column
1148 * @cell_renderer: The #GtkCellRenderer where to draw each row contents.
1149 * @Varargs: a %NULL-terminated pair of attributes and column numbers.
1151 * This functions adds a new column to the widget, whose data will
1152 * be obtained from the model. Only widgets added this way should used on
1153 * the selection logic, i.e., the print function, the #HildonTouchPicker::changed
1156 * You can optionally pass a #GtkCellRenderer in @cell_renderer,
1157 * together with a %NULL-terminated list of pairs property/value, in
1158 * the same way you would use gtk_tree_view_column_set_attributes().
1159 * This will pack @cell_renderer at the start of the column, expanded by default.
1160 * If you prefer not to add it this way, you can simply pass %NULL to @cell_renderer
1161 * and use the #GtkCellLayout interface on the returned #HildonTouchSelectorColumn
1162 * to set your renderers.
1164 * There is a prerequisite to be considered on models used: text data must
1165 * be in the first column.
1167 * This method basically adds a #GtkTreeView to the widget, using the model and
1168 * the data received.
1170 * Returns: the new column added added, %NULL otherwise.
1175 HildonTouchSelectorColumn*
1176 hildon_touch_selector_append_column (HildonTouchSelector * selector,
1177 GtkTreeModel * model,
1178 GtkCellRenderer * cell_renderer, ...)
1181 HildonTouchSelectorColumn *new_column = NULL;
1182 gboolean emit_changed = FALSE;
1185 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1186 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1188 if (model != NULL) {
1190 va_start (args, cell_renderer);
1191 new_column = _create_new_column (selector, model, &emit_changed, cell_renderer, args);
1194 selector->priv->columns = g_slist_append (selector->priv->columns,
1196 gtk_box_pack_start (GTK_BOX (selector->priv->hbox),
1197 new_column->priv->panarea,
1200 gtk_widget_show_all (new_column->priv->panarea);
1202 if (selector->priv->initial_scroll) {
1203 _hildon_touch_selector_center_on_selected_items (selector, new_column);
1210 g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1212 colnum = g_slist_length (selector->priv->columns);
1213 hildon_touch_selector_emit_value_changed (selector, colnum);
1220 * hildon_touch_selector_append_text_column
1221 * @selector: a #HildonTouchSelector
1222 * @model: a #GtkTreeModel with data for the column
1223 * @center: whether to center the text on the column
1225 * Equivalent to hildon_touch_selector_append_column(), but using a
1226 * default text cell renderer. This is the most common use case of the
1229 * Returns: the new column added, NULL otherwise.
1233 HildonTouchSelectorColumn*
1234 hildon_touch_selector_append_text_column (HildonTouchSelector * selector,
1235 GtkTreeModel * model, gboolean center)
1237 gfloat xalign = center ? 0.5 : 0.0;
1238 GtkCellRenderer *renderer;
1240 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1241 g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1243 renderer = gtk_cell_renderer_text_new ();
1245 g_object_set (renderer,
1250 return hildon_touch_selector_append_column (selector, model, renderer,
1255 * hildon_touch_selector_remove_column:
1256 * @selector: a #HildonTouchSelector
1257 * @column: the position of the column to be removed
1259 * Removes a column from @selector.
1261 * Returns: %TRUE if the column was removed, %FALSE otherwise
1266 hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column)
1268 HildonTouchSelectorColumn *current_column = NULL;
1269 HildonTouchSelectorPrivate *priv;
1271 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1272 g_return_val_if_fail (column <
1273 hildon_touch_selector_get_num_columns (selector), FALSE);
1275 priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
1276 current_column = g_slist_nth_data (priv->columns, column);
1278 gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->priv->panarea);
1279 priv->columns = g_slist_remove (priv->columns, current_column);
1280 g_object_unref (current_column);
1282 g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1288 * hildon_touch_selector_set_column_attributes:
1289 * @selector: a #HildonTouchSelector
1290 * @num_column: the number of the column whose attributes we're setting
1291 * @cell_renderer: the #GtkCellRendere we're setting the attributes of
1292 * @Varargs: A %NULL-terminated list of attributes.
1294 * Sets the attributes for the given column. The attributes must be given
1295 * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes().
1296 * All existing attributes are removed and replaced with the new ones.
1298 * Deprecated: #HildonTouchSelectorColumn implements #GtkCellLayout, use this
1299 * interface instead. See
1300 * hildon_touch_selector_get_column().
1305 hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector,
1307 GtkCellRenderer * cell_renderer,
1311 GtkTreeViewColumn *tree_column = NULL;
1312 HildonTouchSelectorColumn *current_column = NULL;
1313 gchar *attribute = NULL;
1316 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1317 g_return_if_fail (num_column <
1318 hildon_touch_selector_get_num_columns (selector));
1320 current_column = g_slist_nth_data (selector->priv->columns, num_column);
1322 tree_column = gtk_tree_view_get_column (current_column->priv->tree_view, 0);
1323 gtk_tree_view_remove_column (current_column->priv->tree_view, tree_column);
1325 tree_column = gtk_tree_view_column_new ();
1326 gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE);
1328 va_start (args, cell_renderer);
1329 attribute = va_arg (args, gchar *);
1331 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1333 while (attribute != NULL) {
1334 value = va_arg (args, gint);
1335 gtk_tree_view_column_add_attribute (tree_column, cell_renderer,
1337 attribute = va_arg (args, gchar *);
1342 gtk_tree_view_append_column (current_column->priv->tree_view, tree_column);
1346 * hildon_touch_selector_get_num_columns:
1347 * @selector: a #HildonTouchSelector
1349 * Gets the number of columns in the #HildonTouchSelector.
1351 * Returns: the number of columns in @selector.
1356 hildon_touch_selector_get_num_columns (HildonTouchSelector * selector)
1358 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1360 return g_slist_length (selector->priv->columns);
1364 * hildon_touch_selector_get_column_selection_mode:
1365 * @selector: a #HildonTouchSelector
1367 * Gets the selection mode of @selector.
1369 * Returns: one of #HildonTouchSelectorSelectionMode
1373 HildonTouchSelectorSelectionMode
1374 hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector)
1376 HildonTouchSelectorSelectionMode result =
1377 HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1378 GtkSelectionMode treeview_mode = GTK_SELECTION_BROWSE;
1379 HildonTouchSelectorColumn *column = NULL;
1380 GtkTreeSelection *selection = NULL;
1382 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result);
1383 g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0,
1386 column = HILDON_TOUCH_SELECTOR_COLUMN (selector->priv->columns->data);
1388 selection = gtk_tree_view_get_selection (column->priv->tree_view);
1389 treeview_mode = gtk_tree_selection_get_mode (selection);
1392 if (treeview_mode == GTK_SELECTION_MULTIPLE) {
1393 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE;
1395 result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1402 * hildon_touch_selector_set_column_selection_mode:
1403 * @selector: a #HildonTouchSelector
1404 * @mode: the #HildonTouchSelectorMode for @selector
1406 * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode.
1411 hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
1412 HildonTouchSelectorSelectionMode mode)
1414 GtkTreeView *tv = NULL;
1415 HildonTouchSelectorColumn *column = NULL;
1416 GtkTreeSelection *selection = NULL;
1417 GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE;
1419 HildonTouchSelectorSelectionMode current_mode;
1421 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1422 g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0);
1424 current_mode = hildon_touch_selector_get_column_selection_mode (selector);
1426 if (current_mode == mode) {
1430 column = HILDON_TOUCH_SELECTOR_COLUMN ((g_slist_nth (selector->priv->columns, 0))->data);
1431 tv = column->priv->tree_view;
1435 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE:
1436 treeview_mode = GTK_SELECTION_BROWSE;
1438 case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE:
1439 treeview_mode = GTK_SELECTION_MULTIPLE;
1443 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1444 gtk_tree_selection_set_mode (selection, treeview_mode);
1446 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1447 gtk_tree_model_get_iter_first (column->priv->model, &iter);
1448 gtk_tree_selection_unselect_all (selection);
1449 gtk_tree_selection_select_iter (selection, &iter);
1451 /* the column changed was the first one */
1452 hildon_touch_selector_emit_value_changed (selector, 0);
1458 * hildon_touch_selector_set_print_func:
1459 * @selector: a #HildonTouchSelector
1460 * @func: a #HildonTouchSelectorPrintFunc function
1462 * Sets the function to be used by hildon_touch_selector_get_current_text()
1463 * to produce a text representation of the currently selected items in @selector.
1464 * The default function will return a concatenation of comma separated items
1465 * selected in each column in @selector. Use this to override this method if you
1466 * need a particular representation for your application.
1471 hildon_touch_selector_set_print_func (HildonTouchSelector * selector,
1472 HildonTouchSelectorPrintFunc func)
1474 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1476 hildon_touch_selector_set_print_func_full (selector, func, NULL, NULL);
1480 * hildon_touch_selector_set_print_func_full:
1481 * @selector: a #HildonTouchSelector
1482 * @func: a #HildonTouchSelectorPrintFunc function
1483 * @user_data: a pointer to user data or %NULL
1484 * @destroy_func: a callback for freeing the user data or %NULL
1486 * Sets the function to be used by hildon_touch_selector_get_current_text()
1487 * to produce a text representation of the currently selected items in @selector.
1488 * The default function will return a concatenation of comma separated items
1489 * selected in each column in @selector. Use this to override this method if you
1490 * need a particular representation for your application.
1495 hildon_touch_selector_set_print_func_full (HildonTouchSelector *selector,
1496 HildonTouchSelectorPrintFunc func,
1498 GDestroyNotify destroy_func)
1500 gpointer old_user_data;
1501 GDestroyNotify old_destroy_func;
1503 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1505 old_user_data = selector->priv->print_user_data;
1506 old_destroy_func = selector->priv->print_destroy_func;
1508 selector->priv->print_func = func;
1509 selector->priv->print_user_data = user_data;
1510 selector->priv->print_destroy_func = destroy_func;
1512 if (old_destroy_func && old_user_data != user_data)
1513 (*old_destroy_func) (old_user_data);
1517 * hildon_touch_selector_get_print_func:
1518 * @selector: a #HildonTouchSelector
1520 * Gets the #HildonTouchSelectorPrintFunc currently used. See
1521 * hildon_touch_selector_set_print_func().
1523 * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default
1524 * one is currently used.
1526 HildonTouchSelectorPrintFunc
1527 hildon_touch_selector_get_print_func (HildonTouchSelector * selector)
1529 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1531 return selector->priv->print_func;
1535 * hildon_touch_selector_set_active:
1536 * @selector: a #HildonTouchSelector
1537 * @column: column number
1538 * @index: the index of the item to select, or -1 to have no active item
1540 * Sets the active item of the #HildonTouchSelector to @index. The
1541 * column number is taken from @column.
1543 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1548 hildon_touch_selector_set_active (HildonTouchSelector *selector,
1552 GtkTreeSelection *selection = NULL;
1553 HildonTouchSelectorColumn *current_column = NULL;
1554 HildonTouchSelectorSelectionMode mode;
1557 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1558 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1559 mode = hildon_touch_selector_get_column_selection_mode (selector);
1560 g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
1562 current_column = g_slist_nth_data (selector->priv->columns, column);
1564 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1565 path = gtk_tree_path_new_from_indices (index, -1);
1566 gtk_tree_selection_unselect_all (selection);
1568 gtk_tree_selection_select_path (selection, path);
1570 hildon_touch_selector_emit_value_changed (selector, column);
1572 gtk_tree_path_free (path);
1576 * hildon_touch_selector_get_active:
1577 * @selector: a #HildonTouchSelector
1578 * @column: column number
1580 * Returns the index of the currently active item in column number
1581 * @column, or -1 if there's no active item.
1583 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1585 * Returns: an integer which is the index of the currently active
1586 * item, or -1 if there's no active item.
1591 hildon_touch_selector_get_active (HildonTouchSelector *selector,
1594 GtkTreeSelection *selection = NULL;
1595 HildonTouchSelectorColumn *current_column = NULL;
1596 HildonTouchSelectorSelectionMode mode;
1597 GtkTreeModel *model;
1602 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1603 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1);
1604 mode = hildon_touch_selector_get_column_selection_mode (selector);
1605 g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1);
1607 current_column = g_slist_nth_data (selector->priv->columns, column);
1609 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1610 g_return_val_if_fail (gtk_tree_selection_get_selected (selection, NULL, &iter), -1);
1612 model = gtk_tree_view_get_model (GTK_TREE_VIEW (current_column->priv->tree_view));
1613 path = gtk_tree_model_get_path (model, &iter);
1614 index = (gtk_tree_path_get_indices (path))[0];
1616 gtk_tree_path_free (path);
1622 * hildon_touch_selector_get_selected:
1623 * @selector: a #HildonTouchSelector
1624 * @column: the column number we want to get the element
1625 * @iter: #GtkTreeIter currently selected
1627 * Sets @iter to the currently selected node on the nth-column, if selection is
1628 * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with
1629 * a column different that the first one. @iter may be %NULL if you just want to
1630 * test if selection has any selected items.
1632 * This function will not work if selection is in
1633 * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one.
1635 * See gtk_tree_selection_get_selected() for more information.
1637 * Returns: %TRUE if @iter was correctly set, %FALSE otherwise
1642 hildon_touch_selector_get_selected (HildonTouchSelector * selector,
1643 gint column, GtkTreeIter * iter)
1645 GtkTreeSelection *selection = NULL;
1646 HildonTouchSelectorColumn *current_column = NULL;
1647 HildonTouchSelectorSelectionMode mode;
1649 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1650 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1652 mode = hildon_touch_selector_get_column_selection_mode (selector);
1653 g_return_val_if_fail
1654 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) ||
1655 ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)),
1658 current_column = g_slist_nth_data (selector->priv->columns, column);
1661 gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1663 return gtk_tree_selection_get_selected (selection, NULL, iter);
1667 * hildon_touch_selector_select_iter
1668 * @selector: a #HildonTouchSelector
1669 * @column: the column to selects
1670 * @iter: the #GtkTreeIter to be selected
1671 * @scroll_to: whether to smoothly scroll to the item
1673 * Sets the currently selected item in the column @column to the one pointed by @iter,
1674 * optionally smoothly scrolling to it.
1679 hildon_touch_selector_select_iter (HildonTouchSelector * selector,
1680 gint column, GtkTreeIter * iter,
1684 GtkTreeModel *model;
1685 HildonTouchSelectorColumn *current_column = NULL;
1686 GtkTreeView *tv = NULL;
1687 GtkTreeSelection *selection = NULL;
1689 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1690 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1692 current_column = g_slist_nth_data (selector->priv->columns, column);
1694 tv = current_column->priv->tree_view;
1695 selection = gtk_tree_view_get_selection (tv);
1696 model = gtk_tree_view_get_model (tv);
1697 path = gtk_tree_model_get_path (model, iter);
1699 gtk_tree_selection_select_iter (selection, iter);
1702 hildon_touch_selector_scroll_to (current_column, tv, path);
1705 hildon_touch_selector_emit_value_changed (selector, column);
1707 gtk_tree_path_free (path);
1711 * hildon_touch_selector_unselect_iter
1712 * @selector: a #HildonTouchSelector
1713 * @column: the column to unselects from
1714 * @iter: the #GtkTreeIter to be unselected
1716 * Unselect the item pointed by @iter in the column @column
1721 void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector,
1725 HildonTouchSelectorColumn *current_column = NULL;
1726 GtkTreeSelection *selection = NULL;
1728 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1729 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1731 current_column = g_slist_nth_data (selector->priv->columns, column);
1732 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1733 gtk_tree_selection_unselect_iter (selection, iter);
1735 hildon_touch_selector_emit_value_changed (selector, column);
1739 * hildon_touch_selector_unselect_all:
1740 * @selector: a #HildonTouchSelector
1741 * @column: the position of the column to get the selected rows from
1743 * Unselects all the selected items in the column @column.
1748 hildon_touch_selector_unselect_all (HildonTouchSelector * selector,
1751 HildonTouchSelectorColumn *current_column = NULL;
1752 GtkTreeSelection *selection = NULL;
1754 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1755 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1757 current_column = g_slist_nth_data (selector->priv->columns, column);
1758 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1759 gtk_tree_selection_unselect_all (selection);
1761 hildon_touch_selector_emit_value_changed (selector, column);
1765 * hildon_touch_selector_get_selected_rows:
1766 * @selector: a #HildonTouchSelector
1767 * @column: the position of the column to get the selected rows from
1769 * Creates a list of #GtkTreePath<!-- -->s of all selected rows in a column. Additionally,
1770 * if you to plan to modify the model after calling this function, you may
1771 * want to convert the returned list into a list of GtkTreeRowReferences. To do this,
1772 * you can use gtk_tree_row_reference_new().
1774 * See gtk_tree_selection_get_selected_rows() for more information.
1776 * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column.
1781 hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector,
1784 GList *result = NULL;
1785 HildonTouchSelectorColumn *current_column = NULL;
1786 GtkTreeSelection *selection = NULL;
1788 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1789 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1792 current_column = g_slist_nth_data (selector->priv->columns, column);
1793 selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
1795 result = gtk_tree_selection_get_selected_rows (selection, NULL);
1801 * hildon_touch_selector_get_model:
1802 * @selector: a #HildonTouchSelector
1803 * @column: the position of the column in @selector
1805 * Gets the model of a column of @selector.
1807 * Returns: the #GtkTreeModel for the column @column of @selector.
1812 hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column)
1814 HildonTouchSelectorColumn *current_column = NULL;
1816 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1817 g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
1820 current_column = g_slist_nth_data (selector->priv->columns, column);
1822 return current_column->priv->model;
1826 on_row_changed (GtkTreeModel *model,
1831 HildonTouchSelector *selector;
1832 HildonTouchSelectorColumn *current_column;
1837 selector = HILDON_TOUCH_SELECTOR (userdata);
1839 for (col = selector->priv->columns; col != NULL; col = col->next) {
1840 current_column = HILDON_TOUCH_SELECTOR_COLUMN (col->data);
1841 if (current_column->priv->model == model &&
1842 gtk_tree_selection_path_is_selected (gtk_tree_view_get_selection (current_column->priv->tree_view),
1844 hildon_touch_selector_emit_value_changed (selector, column);
1851 _hildon_touch_selector_set_model (HildonTouchSelector * selector,
1852 gint column, GtkTreeModel * model)
1854 HildonTouchSelectorColumn *current_column = NULL;
1857 HILDON_TOUCH_SELECTOR_COLUMN (g_slist_nth_data (selector->priv->columns, column));
1859 if (current_column->priv->model) {
1860 g_signal_handlers_disconnect_by_func (current_column->priv->model,
1861 on_row_changed, selector);
1863 current_column->priv->model = model;
1864 gtk_tree_view_set_model (current_column->priv->tree_view,
1865 current_column->priv->model);
1866 g_signal_connect (model, "row-changed",
1867 G_CALLBACK (on_row_changed), selector);
1871 * hildon_touch_selector_set_model:
1872 * @selector: a #HildonTouchSelector
1873 * @column: the position of the column to set the model to
1874 * @model: a #GtkTreeModel
1876 * Sets the #GtkTreeModel for a particular column in @model.
1881 hildon_touch_selector_set_model (HildonTouchSelector * selector,
1882 gint column, GtkTreeModel * model)
1884 g_return_if_fail (HILDON_TOUCH_SELECTOR (selector));
1885 g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1887 HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model);
1891 * hildon_touch_selector_get_current_text:
1892 * @selector: a #HildonTouchSelector
1894 * Returns a string representing the currently selected items for
1895 * each column of @selector. See hildon_touch_selector_set_print_func().
1897 * Returns: a newly allocated string.
1902 hildon_touch_selector_get_current_text (HildonTouchSelector * selector)
1904 gchar *result = NULL;
1905 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1907 if (selector->priv->print_func) {
1908 result = (*selector->priv->print_func) (selector, selector->priv->print_user_data);
1910 result = _default_print_func (selector, NULL);
1917 search_nearest_element (HildonPannableArea *panarea,
1919 GList *selected_rows,
1920 GtkTreePath **nearest_path)
1922 GtkAdjustment *adj = NULL;
1923 gdouble target_value = 0;
1926 GtkTreePath *path = NULL;
1928 gdouble nearest_distance = -1;
1929 gdouble current_distance = -1;
1930 GtkTreePath *result_path = NULL;
1932 g_assert (nearest_path != NULL);
1934 if (selected_rows == NULL) {
1935 *nearest_path = NULL;
1939 adj = hildon_pannable_area_get_vadjustment (panarea);
1940 g_return_if_fail (adj != NULL);
1942 /* we add this in order to check the nearest to the center of
1944 target_value = gtk_adjustment_get_value (adj) + adj->page_size/2;
1946 path = result_path = selected_rows->data;
1947 gtk_tree_view_get_background_area (tv, path, NULL, &rect);
1948 gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
1949 nearest_distance = abs (target_value - y);
1951 for (iter = selected_rows->next; iter; iter = g_list_next (iter)) {
1952 gtk_tree_view_get_background_area (tv, path, NULL, &rect);
1953 gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
1954 current_distance = abs (target_value - y);
1955 if (current_distance < nearest_distance) {
1956 nearest_distance = current_distance;
1961 *nearest_path = result_path;
1965 on_realize_cb (GtkWidget *widget,
1968 HildonTouchSelectorColumn *column = NULL;
1972 column = HILDON_TOUCH_SELECTOR_COLUMN (data);
1974 if (column->priv->initial_path) {
1975 gtk_tree_view_get_background_area (GTK_TREE_VIEW (column->priv->tree_view),
1976 column->priv->initial_path, NULL, &rect);
1977 gtk_tree_view_convert_bin_window_to_tree_coords
1978 (GTK_TREE_VIEW (column->priv->tree_view),
1979 0, rect.y, NULL, &y);
1981 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (column->priv->panarea),
1984 gtk_tree_path_free (column->priv->initial_path);
1986 column->priv->initial_path = NULL;
1990 g_signal_handler_disconnect (column->priv->panarea,
1991 column->priv->realize_handler);
1997 hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
2001 if (GTK_WIDGET_REALIZED (column->priv->panarea)) {
2005 gtk_tree_view_get_background_area (tv,
2007 gtk_tree_view_convert_bin_window_to_tree_coords (tv,
2008 0, rect.y, NULL, &y);
2010 hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA
2011 (column->priv->panarea), -1, y);
2013 if (column->priv->realize_handler != 0) {
2015 if (column->priv->initial_path) {
2016 gtk_tree_path_free (column->priv->initial_path);
2017 column->priv->initial_path = NULL;
2020 g_signal_handler_disconnect (column->priv->panarea,
2021 column->priv->realize_handler);
2022 column->priv->realize_handler = 0;
2025 column->priv->initial_path = gtk_tree_path_copy (path);
2026 column->priv->realize_handler =
2027 g_signal_connect_after (G_OBJECT (column->priv->panarea), "realize",
2028 G_CALLBACK (on_realize_cb),
2035 * Center on the selected item of a concrete column
2037 * Returns: TRUE if was able to do that
2041 _hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
2042 HildonTouchSelectorColumn *column)
2044 GtkTreePath *path = NULL;
2045 GList *selected_rows = NULL;
2046 gint num_column = -1;
2048 num_column = g_slist_index (selector->priv->columns, column);
2050 selected_rows = hildon_touch_selector_get_selected_rows (selector, num_column);
2051 if (selected_rows) {
2052 search_nearest_element (HILDON_PANNABLE_AREA (column->priv->panarea),
2053 GTK_TREE_VIEW (column->priv->tree_view),
2058 hildon_touch_selector_scroll_to (column,
2059 GTK_TREE_VIEW (column->priv->tree_view),
2065 g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
2066 g_list_free (selected_rows);
2073 _hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
2075 HildonTouchSelectorSelectionMode mode;
2078 n_columns = hildon_touch_selector_get_num_columns (selector);
2079 mode = hildon_touch_selector_get_column_selection_mode (selector);
2081 return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE));
2085 * hildon_touch_selector_has_multiple_selection:
2086 * @selector: A #HildonTouchSelector
2088 * Determines whether @selector is complex enough to actually require an
2089 * extra selection step than only picking an item. This is normally %TRUE
2090 * if @selector has multiple columns, multiple selection, or when it is a
2091 * more complex widget, like #HildonTouchSelectorEntry.
2093 * This information is useful for widgets containing a #HildonTouchSelector,
2094 * like #HildonPickerDialog, that could need a "Done" button, in case that
2095 * its internal #HildonTouchSelector has multiple columns, for instance.
2097 * Returns: %TRUE if @selector requires multiple selection steps.
2102 hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
2104 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
2106 return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector);
2111 * hildon_touch_selector_get_column:
2112 * @selector: A #HildonTouchSelector
2113 * @column: a column number
2115 * Use this method to retrieve a #HildonTouchSelectorColumn. Then, you can use
2116 * the #GtkCellLayout interface to set up the layout of the column.
2118 * Returns: the @column<!-- -->-th #HildonTouchSelectorColumn in @selector
2122 HildonTouchSelectorColumn *
2123 hildon_touch_selector_get_column (HildonTouchSelector * selector,
2126 gint num_columns = -1;
2128 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
2129 num_columns = hildon_touch_selector_get_num_columns (selector);
2130 g_return_val_if_fail (column < num_columns && column >= 0, NULL);
2132 return g_slist_nth_data (selector->priv->columns, column);
2137 * hildon_touch_selector_center_on_selected:
2138 * @selector: a #HildonTouchSelector
2140 * Ensures all the columns in a #HildonTouchSelector show a selected
2141 * item. If one of the columns is in
2142 * %HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE mode, that column
2143 * will be scrolled to ensure the selected item that is closest to the
2144 * currently visible area is shown.
2149 hildon_touch_selector_center_on_selected (HildonTouchSelector *selector)
2151 GSList *iter = NULL;
2153 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2155 for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) {
2156 _hildon_touch_selector_center_on_selected_items (selector,
2157 HILDON_TOUCH_SELECTOR_COLUMN (iter->data));