1
/*
2
 * This file is a part of hildon
3
 *
4
 * Copyright (C) 2005, 2008 Nokia Corporation.
5
 *
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.
10
 *
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.
15
 *
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.
19
 */
20
21
/**
22
 * SECTION:hildon-touch-selector
23
 * @short_description: A selector widget with several columns.
24
 *
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
28
 * columns. #HildonTouchSelector does not need to be placed in a
29
 * #HildonPannableArea (in fact, doing so will prevent panning).
30
 *
31
 * Normally, you would use #HildonTouchSelector together with a
32
 * #HildonPickerDialog activated from a button. For the most common
33
 * cases, you should use #HildonPickerButton.
34
 *
35
 * The contents of each #HildonTouchSelector column are stored in a
36
 * #GtkTreeModel. To add a new column to a #HildonTouchSelector, use
37
 * hildon_touch_selector_append_column(). If you want to add a
38
 * text-only column, without special attributes, use
39
 * hildon_touch_selector_append_text_column().
40
 *
41
 * It is highly recommended that you use only one column
42
 * #HildonTouchSelector<!-- -->s.
43
 * If you only need a text only, one column selector, you can create it with
44
 * hildon_touch_selector_new_text() and populate with
45
 * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(),
46
 * and hildon_touch_selector_insert_text().
47
 *
48
 * If you need a selector widget that also accepts user inputs, you
49
 * can use #HildonTouchSelectorEntry.
50
 *
51
 * The current selection has a string representation. In the most common cases,
52
 * each column model will contain a text column. You can configure
53
 * which column in particular using the #HildonTouchSelectorColumn property
54
 * #HildonTouchSelectorColumn:text-column
55
 *
56
 * You can get this string representation using
57
 * hildon_touch_selector_get_current_text().
58
 * You can configure how the selection is printed with
59
 * hildon_touch_selector_set_print_func(), that sets the current hildon touch
60
 * selector print function. The widget has a default print function, that
61
 * uses the #HildonTouchSelectorColumn:text-column property on each
62
 * #HildonTouchSelectorColumn to compose the final representation.
63
 *
64
 * If you create the selector using hildon_touch_selector_new_text() you
65
 * don't need to take care of this property, as the model is created internally.
66
 * If you create the selector using hildon_touch_selector_new(), you
67
 * need to specify properly the property for your custom model in order to get a
68
 * non-empty string representation, or define your custom print function.
69
 *
70
 * <example>
71
 * <title>Creating a HildonTouchSelector</title>
72
 * <programlisting>
73
 * void
74
 * selection_changed (HildonTouchSelector *selector,
75
 *                    gint                 column,
76
 *                    gpointer             user_data)
77
 * {
78
 *   gchar *current_selection = NULL;
79
 * <!-- -->
80
 *   current_selection = hildon_touch_selector_get_current_text (selector);
81
 *   g_debug ("Current selection : &percnt;s", current_selection);
82
 * }
83
 * <!-- -->
84
 * static GtkWidget *
85
 * create_customized_selector ()
86
 * {
87
 *   GtkWidget *selector = NULL;
88
 *   GSList *icon_list = NULL;
89
 *   GtkListStore *store_icons = NULL;
90
 *   GSList *item = NULL;
91
 *   GtkCellRenderer *renderer = NULL;
92
 *   HildonTouchSelectorColumn *column = NULL;
93
 * <!-- -->
94
 *   selector = hildon_touch_selector_new ();
95
 * <!-- -->
96
 *   icon_list = gtk_stock_list_ids ();
97
 * <!-- -->
98
 *   store_icons = gtk_list_store_new (1, G_TYPE_STRING);
99
 *   for (item = icon_list; item; item = g_slist_next (item)) {
100
 *     GtkTreeIter iter;
101
 *     gchar *label = item->data;
102
 * <!-- -->
103
 *     gtk_list_store_append (store_icons, &amp;iter);
104
 *     gtk_list_store_set (store_icons, &amp;iter, 0, label, -1);
105
 *     g_free (label);
106
 *   }
107
 *   g_slist_free (icon_list);
108
 * <!-- -->
109
 *   renderer = gtk_cell_renderer_pixbuf_new ();
110
 *   gtk_cell_renderer_set_fixed_size (renderer, -1, 100);
111
 * <!-- -->
112
 *   column = hildon_touch_selector_append_column (HILDON_TOUCH_SELECTOR (selector),
113
 *                                                 GTK_TREE_MODEL (store_icons),
114
 *                                                 renderer, "stock-id", 0, NULL);
115
 * <!-- -->
116
 *   hildon_touch_selector_column_set_text_column (column, 0);
117
 * <!-- -->
118
 *   g_object_unref (store_icons);
119
 * <!-- -->
120
 *   hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
121
 *                                                    HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE);
122
 * <!-- -->
123
 *   g_signal_connect (G_OBJECT (selector), "changed",
124
 *                     G_CALLBACK (selection_changed), NULL);
125
 * <!-- -->
126
 *   return selector;
127
 * }
128
 * <!-- -->
129
 * static GtkWidget *
130
 * create_simple_selector ()
131
 * {
132
 *   GtkWidget *selector = NULL;
133
 *   gint i;
134
 * <!-- -->
135
 *   selector = hildon_touch_selector_new_text ();
136
 *   hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),
137
 *                                                    HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE);
138
 * <!-- -->
139
 *   g_signal_connect (G_OBJECT (selector), "changed",
140
 *                     G_CALLBACK (selection_changed), NULL);
141
 * <!-- -->
142
 *   for (i = 1; i <= 10 ; i++) {
143
 *     gchar *label = g_strdup_printf ("Item &amp;percnt;d", i);
144
 * <!-- -->
145
 *     hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector),
146
 *                                        label);
147
 * <!-- -->
148
 *     g_free (label);
149
 *   }
150
 * <!-- -->
151
 *   return selector;
152
 * }
153
 * </programlisting>
154
 * </example>
155
 */
156
157
/**
158
 * SECTION:hildon-touch-selector-column
159
 * @short_description: A visible column in a #HildonTouchSelector
160
 * @see_also: #HildonTouchSelector
161
 *
162
 * A #HildonTouchSelectorColumn is a column in a
163
 * #HildonTouchSelector. This class implements the #GtkCellLayout interface, allowing
164
 * a flexible management of the cellrenderers in each #HildonTouchSelector column.
165
 */
166
167
#undef HILDON_DISABLE_DEPRECATED
168
169
#ifdef HAVE_CONFIG_H
170
#include <config.h>
171
#endif
172
173
#include <string.h>
174
#include <stdlib.h>
175
#include <glib.h>
176
177
#include "hildon-gtk.h"
178
179
#include "hildon-pannable-area.h"
180
#include "hildon-touch-selector.h"
181
#include "hildon-touch-selector-private.h"
182
#include "hildon-live-search.h"
183
#include "hildon-helper.h"
184
185
#define HILDON_TOUCH_SELECTOR_GET_PRIVATE(obj)                          \
186
  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_TOUCH_SELECTOR, HildonTouchSelectorPrivate))
187
188
G_DEFINE_TYPE (HildonTouchSelector, hildon_touch_selector, GTK_TYPE_VBOX)
189
190
/*
191
 * IMPLEMENTATION NOTES:
192
 * Struct to maintain the data of each column. The columns are the elements
193
 * of the widget that belongs properly to the selection behaviour. Although
194
 * internally the columns are arranged in a private #GtkHBox, as the selector
195
 * itself is a #GtkVBox, you can add more widgets, like buttons etc., so
196
 * you finally could have a widget with more elements that the columns, but
197
 * this doesn't belongs to the selection logic
198
 */
199
struct _HildonTouchSelectorColumnPrivate
200
{
201
  HildonTouchSelector *parent;    /* the selector that contains this column */
202
  GtkTreeModel *model;
203
  gint text_column;
204
  GtkTreeView *tree_view;
205
  gulong realize_handler;
206
  GtkTreePath *initial_path;
207
  GtkTreeModel *filter;
208
  GtkWidget *livesearch;
209
210
  GtkWidget *panarea;           /* the pannable widget */
211
  GtkWidget *vbox;
212
  GtkTreeRowReference *last_activated;
213
};
214
215
struct _HildonTouchSelectorPrivate
216
{
217
  GSList *columns;              /* the selection columns */
218
  GtkWidget *hbox;              /* the container for the selector's columns */
219
  gboolean initial_scroll;      /* whether initial fancy scrolling to selection */
220
  gboolean has_live_search;
221
  GSList *norm_tokens;
222
223
  gboolean changed_blocked;
224
225
  HildonTouchSelectorPrintFunc print_func;
226
  gpointer print_user_data;
227
  GDestroyNotify print_destroy_func;
228
229
  HildonUIMode hildon_ui_mode;
230
};
231
232
enum
233
{
234
  PROP_HAS_MULTIPLE_SELECTION = 1,
235
  PROP_INITIAL_SCROLL,
236
  PROP_HILDON_UI_MODE,
237
  PROP_LIVE_SEARCH
238
};
239
240
enum
241
{
242
  CHANGED,
243
  COLUMNS_CHANGED,
244
  LAST_SIGNAL
245
};
246
247
static gint hildon_touch_selector_signals[LAST_SIGNAL] = { 0 };
248
249
static void
250
hildon_touch_selector_dispose                   (GObject * object);
251
252
static void
253
hildon_touch_selector_get_property              (GObject * object,
254
                                                 guint prop_id,
255
                                                 GValue * value,
256
                                                 GParamSpec * pspec);
257
static void
258
hildon_touch_selector_set_property              (GObject *object,
259
                                                 guint prop_id,
260
                                                 const GValue *value,
261
                                                 GParamSpec *pspec);
262
/* gtkwidget */
263
264
/* gtkcontainer */
265
static void hildon_touch_selector_remove        (GtkContainer * container,
266
                                                 GtkWidget * widget);
267
/* private functions */
268
static void _row_tapped_cb                      (GtkTreeView * tree_view,
269
                                                 GtkTreePath * path,
270
                                                 gpointer user_data);
271
static void
272
hildon_touch_selector_row_activated_cb          (GtkTreeView       *tree_view,
273
                                                 GtkTreePath       *path,
274
                                                 GtkTreeViewColumn *column,
275
                                                 gpointer           user_data);
276
277
static gchar *_default_print_func               (HildonTouchSelector * selector,
278
                                                 gpointer user_data);
279
280
static HildonTouchSelectorColumn *_create_new_column (HildonTouchSelector * selector,
281
                                                 GtkTreeModel * model,
282
                                                 gboolean *emit_changed,
283
                                                 GtkCellRenderer * renderer,
284
                                                 va_list args);
285
static gboolean
286
on_realize_cb                                  (GtkWidget *widget,
287
                                                gpointer data);
288
static void
289
on_row_changed                                 (GtkTreeModel *model,
290
                                                GtkTreePath *path,
291
                                                GtkTreeIter *iter,
292
                                                gpointer userdata);
293
static void
294
on_row_deleted                                 (GtkTreeModel *model,
295
                                                GtkTreePath *path,
296
                                                gpointer userdata);
297
298
static void
299
hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
300
                                 GtkTreeView *tv,
301
                                 GtkTreePath *path);
302
static gboolean
303
_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
304
                                                 HildonTouchSelectorColumn *column);
305
static void
306
_hildon_touch_selector_set_model                (HildonTouchSelector * selector,
307
                                                 gint num_column,
308
                                                 GtkTreeModel * model);
309
static gboolean
310
_hildon_touch_selector_has_multiple_selection   (HildonTouchSelector * selector);
311
312
static void
313
hildon_touch_selector_emit_value_changed        (HildonTouchSelector *selector,
314
                                                 gint column);
315
316
/* GtkCellLayout implementation (HildonTouchSelectorColumn)*/
317
static void hildon_touch_selector_column_cell_layout_init         (GtkCellLayoutIface      *iface);
318
319
static void hildon_touch_selector_column_cell_layout_pack_start   (GtkCellLayout         *cell_layout,
320
                                                                   GtkCellRenderer       *cell,
321
                                                                   gboolean               expand);
322
static void hildon_touch_selector_column_cell_layout_pack_end     (GtkCellLayout         *cell_layout,
323
                                                                   GtkCellRenderer       *cell,
324
                                                                   gboolean               expand);
325
static void hildon_touch_selector_column_cell_layout_clear        (GtkCellLayout         *cell_layout);
326
static void hildon_touch_selector_column_cell_layout_add_attribute(GtkCellLayout         *cell_layout,
327
                                                                   GtkCellRenderer       *cell,
328
                                                                   const gchar           *attribute,
329
                                                                   gint                   column);
330
static void hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
331
                                                                         GtkCellRenderer       *cell,
332
                                                                         GtkCellLayoutDataFunc  func,
333
                                                                         gpointer               func_data,
334
                                                                         GDestroyNotify         destroy);
335
static void hildon_touch_selector_column_cell_layout_clear_attributes   (GtkCellLayout         *cell_layout,
336
                                                                         GtkCellRenderer       *cell);
337
static void hildon_touch_selector_column_cell_layout_reorder       (GtkCellLayout         *cell_layout,
338
                                                                    GtkCellRenderer       *cell,
339
                                                                    gint                   position);
340
static GList *hildon_touch_selector_column_cell_layout_get_cells   (GtkCellLayout         *cell_layout);
341
342
static void
343
hildon_touch_selector_check_ui_mode_coherence   (HildonTouchSelector *selector);
344
345
static void
346
hildon_touch_selector_class_init (HildonTouchSelectorClass * class)
347
{
348
  GObjectClass *gobject_class;
349
  GtkObjectClass *object_class;
350
  GtkContainerClass *container_class;
351
352
  gobject_class = G_OBJECT_CLASS (class);
353
  object_class = GTK_OBJECT_CLASS (class);
354
  container_class = GTK_CONTAINER_CLASS (class);
355
356
  /* GObject */
357
  gobject_class->dispose = hildon_touch_selector_dispose;
358
  gobject_class->get_property = hildon_touch_selector_get_property;
359
  gobject_class->set_property = hildon_touch_selector_set_property;
360
361
  /* GtkWidget */
362
363
  /* GtkContainer */
364
  container_class->remove = hildon_touch_selector_remove;
365
366
  /* HildonTouchSelector */
367
  class->changed = NULL;
368
  class->set_model = _hildon_touch_selector_set_model;
369
370
  class->has_multiple_selection = _hildon_touch_selector_has_multiple_selection;
371
372
  /* signals */
373
  /**
374
   * HildonTouchSelector::changed:
375
   * @widget: the object which received the signal
376
   * @column: the number of the column that has changed
377
   *
378
   * The "changed" signal is emitted when the active item on any column is changed.
379
   * This can be due to the user selecting a different item from the list, or
380
   * due to a call to hildon_touch_selector_select_iter() on one of the columns.
381
   *
382
   * Since: 2.2
383
   */
384
  hildon_touch_selector_signals[CHANGED] =
385
    g_signal_new ("changed",
386
                  G_OBJECT_CLASS_TYPE (class),
387
                  G_SIGNAL_RUN_LAST,
388
                  G_STRUCT_OFFSET (HildonTouchSelectorClass, changed),
389
                  NULL, NULL,
390
                  g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
391
392
  /**
393
   * HildonTouchSelector::columns-changed:
394
   * @selector: the object which received the signal
395
   *
396
   * The "columns-changed" signal is emitted when the number
397
   * of columns in the #HildonTouchSelector change.
398
   *
399
   * Since: 2.2
400
   */
401
  hildon_touch_selector_signals[COLUMNS_CHANGED] =
402
    g_signal_new ("columns-changed",
403
                  G_OBJECT_CLASS_TYPE (class),
404
                  G_SIGNAL_RUN_LAST, 0,
405
                  NULL, NULL,
406
                  g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
407
408
  /* properties */
409
410
  g_object_class_install_property (gobject_class, PROP_HAS_MULTIPLE_SELECTION,
411
                                   g_param_spec_boolean ("has-multiple-selection",
412
                                                         "has multiple selection",
413
                                                         "Whether the widget has multiple "
414
                                                         "selection (like multiple columns, "
415
                                                         "multiselection mode, or multiple "
416
                                                         "internal widgets) and therefore "
417
                                                         "it may need a confirmation button, "
418
                                                         "for instance.",
419
                                                         FALSE,
420
                                                         G_PARAM_READABLE));
421
422
  g_object_class_install_property (G_OBJECT_CLASS (gobject_class),
423
                                   PROP_INITIAL_SCROLL,
424
                                   g_param_spec_boolean ("initial-scroll",
425
                                                         "Initial scroll",
426
                                                         "Whether to scroll to the"
427
                                                         "current selection when"
428
                                                         "the selector is first"
429
                                                         "shown",
430
                                                         TRUE,
431
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
432
433
    /**
434
     * HildonTouchSelector:hildon-ui-mode:
435
     *
436
     * Specifies which UI mode to use in the internal treeviews.  A setting
437
     * of %HILDON_UI_MODE_NORMAL will cause these tree view to disable selections
438
     * and emit row-activated as soon as a row is pressed (unless it is pressed
439
     * to drag the pannable area where the treeview is). You can use the
440
     * method hildon_touch_selector_get_last_activated_row() to get it. When
441
     * %HILDON_UI_MODE_EDIT is set, selections can be made according to the
442
     * setting of the mode on GtkTreeSelection.
443
     *
444
     * Toggling this property will cause the tree view to select an
445
     * appropriate selection mode if not already done.
446
     *
447
     * Since: Hildon 2.2
448
     */
449
  g_object_class_install_property (gobject_class,
450
                                   PROP_HILDON_UI_MODE,
451
                                   g_param_spec_enum ("hildon-ui-mode",
452
                                                      "Hildon UI Mode",
453
                                                      "The Hildon UI mode according "
454
                                                      "to which the touch selector "
455
                                                      "should behave",
456
                                                      HILDON_TYPE_UI_MODE,
457
                                                      HILDON_UI_MODE_EDIT,
458
                                                      G_PARAM_READWRITE));
459
460
  g_object_class_install_property (G_OBJECT_CLASS (gobject_class),
461
                                   PROP_LIVE_SEARCH,
462
                                   g_param_spec_boolean ("live-search",
463
                                                         "Live search",
464
                                                         "Whether the widget should have built-in"
465
                                                         "live search capabilities",
466
                                                         TRUE,
467
                                                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
468
469
  /* style properties */
470
  /* We need to ensure fremantle mode for the treeview in order to work
471
     properly. This is not about the appearance, this is about behaviour */
472
  gtk_rc_parse_string ("style \"fremantle-htst\" {\n"
473
                       "  GtkWidget::hildon-mode = 1\n"
474
                       "} widget \"*.fremantle-htst\" style \"fremantle-htst\""
475
                       "widget_class \"*<HildonPannableArea>.GtkTreeView\" style :highest \"fremantle-htst\"");
476
477
  g_type_class_add_private (object_class, sizeof (HildonTouchSelectorPrivate));
478
}
479
480
static void
481
hildon_touch_selector_get_property (GObject * object,
482
                                    guint prop_id,
483
                                    GValue * value, GParamSpec * pspec)
484
{
485
  HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
486
487
  switch (prop_id) {
488
  case PROP_HAS_MULTIPLE_SELECTION:
489
    g_value_set_boolean (value,
490
                         hildon_touch_selector_has_multiple_selection (HILDON_TOUCH_SELECTOR (object)));
491
    break;
492
  case PROP_INITIAL_SCROLL:
493
    g_value_set_boolean (value, priv->initial_scroll);
494
    break;
495
  case PROP_HILDON_UI_MODE:
496
    g_value_set_enum (value, priv->hildon_ui_mode);
497
    break;
498
  case PROP_LIVE_SEARCH:
499
    g_value_set_boolean (value,
500
                         hildon_touch_selector_get_live_search (HILDON_TOUCH_SELECTOR (object)));
501
    break;
502
  default:
503
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
504
    break;
505
  }
506
}
507
508
static void
509
hildon_touch_selector_set_property (GObject *object, guint prop_id,
510
                                    const GValue *value, GParamSpec *pspec)
511
{
512
  HildonTouchSelectorPrivate *priv = HILDON_TOUCH_SELECTOR (object)->priv;
513
514
  switch (prop_id) {
515
  case PROP_INITIAL_SCROLL:
516
    priv->initial_scroll = g_value_get_boolean (value);
517
    break;
518
  case PROP_HILDON_UI_MODE:
519
    hildon_touch_selector_set_hildon_ui_mode (HILDON_TOUCH_SELECTOR (object),
520
                                              g_value_get_enum (value));
521
    break;
522
  case PROP_LIVE_SEARCH:
523
    hildon_touch_selector_set_live_search (HILDON_TOUCH_SELECTOR (object),
524
                                           g_value_get_boolean (value));
525
    break;
526
  default:
527
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
528
    break;
529
  }
530
}
531
532
533
static void
534
hildon_touch_selector_init (HildonTouchSelector * selector)
535
{
536
  selector->priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
537
538
  GTK_WIDGET_SET_FLAGS (GTK_WIDGET (selector), GTK_NO_WINDOW);
539
  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (selector), FALSE);
540
541
  selector->priv->columns = NULL;
542
543
  selector->priv->norm_tokens = NULL;
544
  selector->priv->print_func = NULL;
545
  selector->priv->print_user_data = NULL;
546
  selector->priv->print_destroy_func = NULL;
547
  selector->priv->initial_scroll = TRUE;
548
  selector->priv->hbox = gtk_hbox_new (FALSE, 0);
549
550
  selector->priv->changed_blocked = FALSE;
551
552
  selector->priv->hildon_ui_mode = HILDON_UI_MODE_EDIT;
553
554
  gtk_box_pack_end (GTK_BOX (selector), selector->priv->hbox,
555
                    TRUE, TRUE, 0);
556
  gtk_widget_show (selector->priv->hbox);
557
}
558
559
static void
560
hildon_touch_selector_dispose (GObject * object)
561
{
562
  GObjectClass *gobject_class;
563
  HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (object);
564
565
  hildon_touch_selector_set_print_func_full (selector,
566
                                             NULL, NULL, NULL);
567
568
  if (selector->priv->norm_tokens != NULL) {
569
      g_slist_foreach (selector->priv->norm_tokens, (GFunc) g_free, NULL);
570
      g_slist_free (selector->priv->norm_tokens);
571
      selector->priv->norm_tokens = NULL;
572
  }
573
574
  gobject_class = G_OBJECT_CLASS (hildon_touch_selector_parent_class);
575
576
  if (gobject_class->dispose)
577
    (* gobject_class->dispose) (object);
578
}
579
580
static void
581
clean_column                                    (HildonTouchSelectorColumn *col,
582
                                                 HildonTouchSelector *selector)
583
{
584
  g_signal_handlers_disconnect_by_func (col->priv->model,
585
                                        on_row_changed, selector);
586
  g_signal_handlers_disconnect_by_func (col->priv->model,
587
                                        on_row_deleted, selector);
588
589
  if (col->priv->last_activated != NULL) {
590
    gtk_tree_row_reference_free (col->priv->last_activated);
591
    col->priv->last_activated = NULL;
592
  }
593
}
594
595
/*
596
 * IMPLEMENTATION NOTES:
597
 * Some people sent questions regarding the fact that the dispose/finalize functions
598
 * doesn't clean the internal widgets that could lead to leak memory, so we will
599
 * clarify this topic.
600
 *
601
 * This is not required as #HildonTouchSelector extends #GtkContainer. When the
602
 * widget is freed, the #GtkContainer freeing memory functions are called. This
603
 * process includes remove each widget individually, so all the widgets are
604
 * properly freed.
605
 *
606
 * In the same way, this widget redefines gtk_container->remove function, in
607
 * order to free the column related information if it is required.
608
 *
609
 * Please take a look to hildon_touch_selector_remove for more information.
610
 */
611
612
/*------------------------------ GtkContainer ------------------------------ */
613
614
/*
615
 * Required in order to free the column at the columns list
616
 */
617
static void
618
hildon_touch_selector_remove (GtkContainer * container, GtkWidget * widget)
619
{
620
  HildonTouchSelector *selector = NULL;
621
622
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (container));
623
  selector = HILDON_TOUCH_SELECTOR (container);
624
625
  /* Remove the extra data related to the columns, if required. */
626
  if (widget == selector->priv->hbox) {
627
    g_slist_foreach (selector->priv->columns, (GFunc) clean_column, selector);
628
    g_slist_foreach (selector->priv->columns, (GFunc) g_object_unref, NULL);
629
630
    g_slist_free (selector->priv->columns);
631
632
    selector->priv->columns = NULL;
633
  }
634
635
  /* Now remove the widget itself from the container */
636
  GTK_CONTAINER_CLASS (hildon_touch_selector_parent_class)->remove (container, widget);
637
}
638
639
/* ------------------------------ PRIVATE METHODS ---------------------------- */
640
void
641
hildon_touch_selector_block_changed             (HildonTouchSelector *selector)
642
{
643
  selector->priv->changed_blocked = TRUE;
644
}
645
646
void
647
hildon_touch_selector_unblock_changed           (HildonTouchSelector *selector)
648
{
649
  selector->priv->changed_blocked = FALSE;
650
}
651
652
static void
653
hildon_touch_selector_emit_value_changed        (HildonTouchSelector *selector,
654
                                                 gint column)
655
{
656
  /* FIXME: it could be good to emit too the GtkTreePath of the element
657
     selected, as now it is required to connect to the signal and then ask
658
     for the element selected. We can't do this API change, in order to avoid
659
     and ABI break */
660
  if (!selector->priv->changed_blocked) {
661
    if (hildon_touch_selector_get_column_selection_mode (selector) == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE &&
662
        selector->priv->columns) {
663
      HildonTouchSelectorColumn *col;
664
      col = (HildonTouchSelectorColumn *) selector->priv->columns->data;
665
      if (col->priv->livesearch) {
666
        hildon_live_search_clean_selection_map (HILDON_LIVE_SEARCH (col->priv->livesearch));
667
      }
668
    }
669
    g_signal_emit (selector, hildon_touch_selector_signals[CHANGED], 0, column);
670
  }
671
}
672
673
static void
674
hildon_touch_selector_check_ui_mode_coherence   (HildonTouchSelector *selector)
675
{
676
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
677
678
  if (hildon_touch_selector_get_num_columns (selector) > 1) {
679
    hildon_touch_selector_set_hildon_ui_mode (selector, HILDON_UI_MODE_EDIT);
680
  }
681
}
682
683
/**
684
 * default_print_func:
685
 * @selector: a #HildonTouchSelector
686
 *
687
 * Default print function
688
 *
689
 * Returns: a new string that represents the selected items
690
 *
691
 * Since: 2.2
692
 **/
693
static gchar *
694
_default_print_func (HildonTouchSelector * selector, gpointer user_data)
695
{
696
  gchar *result = NULL;
697
  gchar *aux = NULL;
698
  gint num_columns = 0;
699
  GtkTreeIter iter;
700
  GtkTreeModel *model = NULL;
701
  gchar *current_string = NULL;
702
  gint i;
703
  HildonTouchSelectorSelectionMode mode;
704
  GList *item = NULL;
705
  GtkTreePath *current_path = NULL;
706
  GList *selected_rows = NULL;
707
  gint initial_value = 0;
708
  gint text_column = -1;
709
  HildonTouchSelectorColumn *column = NULL;
710
711
  num_columns = hildon_touch_selector_get_num_columns (selector);
712
713
  mode = hildon_touch_selector_get_column_selection_mode (selector);
714
715
  if ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
716
      && (num_columns > 0)) {
717
    /* In this case we get the first column first */
718
    selected_rows = hildon_touch_selector_get_selected_rows (selector, 0);
719
    model = hildon_touch_selector_get_model (selector, 0);
720
    column = hildon_touch_selector_get_column (selector, 0);
721
    text_column = hildon_touch_selector_column_get_text_column (column);
722
723
    result = g_strdup_printf ("(");
724
    i = 0;
725
    for (item = selected_rows; item; item = g_list_next (item)) {
726
      current_path = item->data;
727
      gtk_tree_model_get_iter (model, &iter, current_path);
728
729
      if (text_column != -1) {
730
        gtk_tree_model_get (model, &iter, text_column, &current_string, -1);
731
      }
732
733
      if (i < g_list_length (selected_rows) - 1) {
734
        aux = g_strconcat (result, current_string, ",", NULL);
735
        g_free (result);
736
        result = aux;
737
      } else {
738
        aux = g_strconcat (result, current_string, NULL);
739
        g_free (result);
740
        result = aux;
741
      }
742
743
      if (current_string) {
744
        g_free (current_string);
745
        current_string = NULL;
746
      }
747
748
      i++;
749
    }
750
751
    aux = g_strconcat (result, ")", NULL);
752
    g_free (result);
753
    result = aux;
754
755
    g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
756
    g_list_free (selected_rows);
757
    initial_value = 1;
758
  } else {
759
    initial_value = 0;
760
  }
761
762
  for (i = initial_value; i < num_columns; i++) {
763
    model = hildon_touch_selector_get_model (selector, i);
764
    column = hildon_touch_selector_get_column (selector, i);
765
    text_column = hildon_touch_selector_column_get_text_column (column);
766
767
    if (hildon_touch_selector_get_selected (selector, i, &iter)) {
768
      if (text_column == -1 ) {
769
        g_warning ("Trying to use the default print function in HildonTouchSelector, but "
770
                   "\"text-column\" property is not set for HildonTouchSelectorColumn %p.", column);
771
        current_string = NULL;
772
      } else {
773
        gtk_tree_model_get (model, &iter, text_column, &current_string, -1);
774
      }
775
776
      if (i == 0) {
777
        result = current_string;
778
      } else {
779
        aux = g_strconcat (result, ":", current_string, NULL);
780
        g_free (result);
781
        g_free (current_string);
782
        current_string = NULL;
783
        result = aux;
784
      }
785
    }
786
  }
787
788
  return result;
789
}
790
791
static void
792
hildon_touch_selector_row_activated_cb          (GtkTreeView       *tree_view,
793
                                                 GtkTreePath       *path,
794
                                                 GtkTreeViewColumn *column,
795
                                                 gpointer           user_data)
796
{
797
  HildonTouchSelectorColumn *selector_column = NULL;
798
  GtkTreePath *child_path;
799
800
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (user_data));
801
  selector_column = HILDON_TOUCH_SELECTOR_COLUMN (user_data);
802
803
  if (selector_column->priv->last_activated != NULL) {
804
    gtk_tree_row_reference_free (selector_column->priv->last_activated);
805
  }
806
807
  child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (selector_column->priv->filter),
808
                                                                 path);
809
  selector_column->priv->last_activated = gtk_tree_row_reference_new (selector_column->priv->model,
810
                                                                      child_path);
811
  gtk_tree_path_free (child_path);
812
}
813
814
static void
815
_row_tapped_cb (GtkTreeView * tree_view, GtkTreePath * path, gpointer user_data)
816
{
817
  HildonTouchSelector *selector = NULL;
818
  HildonTouchSelectorColumn *column = NULL;
819
  gint num_column = -1;
820
821
  column = HILDON_TOUCH_SELECTOR_COLUMN (user_data);
822
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (column->priv->parent));
823
824
  selector = column->priv->parent;
825
826
  num_column = g_slist_index (selector->priv->columns, column);
827
828
  hildon_touch_selector_emit_value_changed (selector, num_column);
829
}
830
831
832
static HildonTouchSelectorColumn *
833
_create_new_column (HildonTouchSelector * selector,
834
                    GtkTreeModel * model,
835
                    gboolean *emit_changed,
836
                    GtkCellRenderer * renderer, va_list args)
837
{
838
  HildonTouchSelectorColumn *new_column = NULL;
839
  GtkTreeViewColumn *tree_column = NULL;
840
  GtkTreeView *tv = NULL;
841
  GtkTreeModel *filter;
842
  GtkWidget *panarea = NULL;
843
  GtkTreeSelection *selection = NULL;
844
  GtkTreeIter iter;
845
  gchar *attribute;
846
  gint value;
847
848
  tree_column = gtk_tree_view_column_new ();
849
850
  if (renderer != NULL) {
851
    gtk_tree_view_column_pack_start (tree_column, renderer, TRUE);
852
853
    attribute = va_arg (args, gchar *);
854
    while (attribute != NULL) {
855
      value = va_arg (args, gint);
856
      gtk_tree_view_column_add_attribute (tree_column, renderer, attribute,
857
                                          value);
858
      attribute = va_arg (args, gchar *);
859
    }
860
  }
861
862
#ifdef MAEMO_GTK
863
  tv = GTK_TREE_VIEW (hildon_gtk_tree_view_new (selector->priv->hildon_ui_mode));
864
#else
865
  tv = GTK_TREE_VIEW (gtk_tree_view_new ());
866
#endif /* MAEMO_GTK */
867
868
  gtk_tree_view_set_enable_search (tv, FALSE);
869
  if (!selector->priv->has_live_search) {
870
    GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (tv), GTK_CAN_FOCUS);
871
  }
872
873
  filter = gtk_tree_model_filter_new (model, NULL);
874
  gtk_tree_view_set_model (tv, filter);
875
  g_signal_connect (model, "row-changed",
876
                    G_CALLBACK (on_row_changed), selector);
877
  g_signal_connect_after (model, "row-deleted",
878
                          G_CALLBACK (on_row_deleted), selector);
879
  gtk_tree_view_set_rules_hint (tv, TRUE);
880
881
  gtk_tree_view_append_column (GTK_TREE_VIEW (tv), tree_column);
882
883
  new_column = g_object_new (HILDON_TYPE_TOUCH_SELECTOR_COLUMN, NULL);
884
  new_column->priv->parent = selector;
885
886
  panarea = hildon_pannable_area_new ();
887
888
  gtk_container_add (GTK_CONTAINER (panarea), GTK_WIDGET (tv));
889
890
  new_column->priv->model = g_object_ref (model);
891
  new_column->priv->tree_view = tv;
892
  new_column->priv->panarea = panarea;
893
  new_column->priv->filter = filter;
894
  new_column->priv->livesearch = NULL;
895
896
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
897
  gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
898
899
  /* select the first item */
900
  *emit_changed = FALSE;
901
  if ((gtk_tree_model_get_iter_first (filter, &iter))&&
902
      (selector->priv->hildon_ui_mode == HILDON_UI_MODE_EDIT)) {
903
    gtk_tree_selection_select_iter (selection, &iter);
904
    *emit_changed = TRUE;
905
  }
906
907
  /* connect to the hildon-row-tapped signal connection */
908
  g_signal_connect (G_OBJECT (tv), "hildon-row-tapped",
909
                    G_CALLBACK (_row_tapped_cb), new_column);
910
911
  g_signal_connect (G_OBJECT (tv), "row-activated",
912
                    G_CALLBACK (hildon_touch_selector_row_activated_cb), new_column);
913
914
  return new_column;
915
}
916
917
918
/* ------------------------ HildonTouchSelectorColumn implementation ---------------------- */
919
G_DEFINE_TYPE_WITH_CODE (HildonTouchSelectorColumn, hildon_touch_selector_column, G_TYPE_OBJECT,
920
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
921
                                                hildon_touch_selector_column_cell_layout_init))
922
923
enum
924
{
925
  PROP_TEXT_COLUMN = 1
926
};
927
928
static void
929
hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass);
930
931
static void
932
hildon_touch_selector_column_get_property (GObject *object, guint property_id,
933
                                           GValue *value, GParamSpec *pspec);
934
935
static void
936
hildon_touch_selector_column_set_property  (GObject *object, guint property_id,
937
                                            const GValue *value, GParamSpec *pspec);
938
939
static void
940
hildon_touch_selector_column_dispose       (GObject *object);
941
942
static void
943
hildon_touch_selector_column_finalize      (GObject *object);
944
945
static void
946
hildon_touch_selector_column_class_init (HildonTouchSelectorColumnClass *klass)
947
{
948
  GObjectClass *gobject_class = NULL;
949
950
  gobject_class = G_OBJECT_CLASS (klass);
951
952
  g_type_class_add_private (gobject_class, sizeof (HildonTouchSelectorColumnPrivate));
953
954
  /* GObject */
955
  gobject_class->get_property = hildon_touch_selector_column_get_property;
956
  gobject_class->set_property = hildon_touch_selector_column_set_property;
957
  gobject_class->dispose      = hildon_touch_selector_column_dispose;
958
  gobject_class->finalize     = hildon_touch_selector_column_finalize;
959
960
  /**
961
   * HildonTouchSelectorColumn:text-column:
962
   *
963
   * A column in the data source model to get the strings from.
964
   *
965
   * Since: maemo 2.2
966
   **/
967
  g_object_class_install_property (G_OBJECT_CLASS(klass),
968
                                   PROP_TEXT_COLUMN,
969
                                   g_param_spec_int ("text-column",
970
                                                     "Text Column",
971
                                                     "A column in the data source model to get the strings from.",
972
                                                     -1,
973
                                                     G_MAXINT,
974
                                                     -1,
975
                                                     G_PARAM_READWRITE));
976
}
977
978
static void
979
hildon_touch_selector_column_init (HildonTouchSelectorColumn *column)
980
{
981
  column->priv = G_TYPE_INSTANCE_GET_PRIVATE (column, HILDON_TYPE_TOUCH_SELECTOR_COLUMN,
982
                                              HildonTouchSelectorColumnPrivate);
983
  column->priv->text_column = -1;
984
  column->priv->last_activated = NULL;
985
  column->priv->realize_handler = 0;
986
  column->priv->initial_path = NULL;
987
}
988
989
static gboolean
990
hildon_live_search_visible_func (GtkTreeModel *model,
991
                                 GtkTreeIter *iter,
992
                                 gchar *prefix,
993
                                 gpointer userdata)
994
{
995
  gboolean visible = TRUE;
996
  gchar *string, *string_ascii;
997
  GSList *list_iter;
998
  HildonTouchSelectorColumn *col;
999
  HildonTouchSelector *selector;
1000
1001
  col = HILDON_TOUCH_SELECTOR_COLUMN (userdata);
1002
  selector = col->priv->parent;
1003
  gint text_column = GPOINTER_TO_INT (col->priv->text_column);
1004
1005
  gtk_tree_model_get (model, iter, text_column, &string, -1);
1006
  string_ascii = hildon_helper_normalize_string (string);
1007
  list_iter = selector->priv->norm_tokens;
1008
  while (visible && list_iter) {
1009
    visible = (string_ascii != NULL &&
1010
               hildon_helper_smart_match (string_ascii,
1011
                                          (const gchar *)list_iter->data));
1012
    list_iter = list_iter->next;
1013
  }
1014
1015
  g_free (string);
1016
  g_free (string_ascii);
1017
1018
  return visible;
1019
}
1020
1021
static gboolean
1022
on_live_search_refilter (HildonLiveSearch *livesearch,
1023
                         gpointer userdata)
1024
{
1025
    HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (userdata);
1026
1027
    gchar **tokens = g_strsplit (hildon_live_search_get_text (livesearch), " ", -1);
1028
    gchar *token;
1029
    gint i;
1030
1031
    if (selector->priv->norm_tokens != NULL) {
1032
        g_slist_foreach (selector->priv->norm_tokens, (GFunc) g_free, NULL);
1033
        g_slist_free (selector->priv->norm_tokens);
1034
        selector->priv->norm_tokens = NULL;
1035
    }
1036
1037
    for (i = 0; tokens [i] != NULL; i++) {
1038
        token = hildon_helper_normalize_string (tokens[i]);
1039
        if (token != NULL)
1040
            selector->priv->norm_tokens = g_slist_prepend (selector->priv->norm_tokens,
1041
                                                           token);
1042
    }
1043
1044
    g_strfreev (tokens);
1045
1046
    return FALSE;
1047
}
1048
1049
/**
1050
 * hildon_touch_selector_column_set_text_column:
1051
 * @column: A #HildonTouchSelectorColumn
1052
 * @text_column: the index of a model column in the model for @column.
1053
 *
1054
 * Sets the model column to be displayed in @column. @text_column must point to a
1055
 * column in the model used with type %G_TYPE_STRING. Initially, this property
1056
 * is unset. You should set it before using the #HildonTouchSelector that uses
1057
 * @column.
1058
 *
1059
 * Since: 2.2
1060
 **/
1061
void
1062
hildon_touch_selector_column_set_text_column (HildonTouchSelectorColumn *column,
1063
                                              gint text_column)
1064
{
1065
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column));
1066
  g_return_if_fail (text_column >= -1);
1067
1068
  column->priv->text_column = text_column;
1069
1070
  if (column->priv->livesearch) {
1071
    hildon_live_search_set_visible_func (HILDON_LIVE_SEARCH (column->priv->livesearch),
1072
                                         hildon_live_search_visible_func,
1073
                                         column,
1074
                                         NULL);
1075
  }
1076
1077
  g_object_notify (G_OBJECT (column), "text-column");
1078
}
1079
1080
/**
1081
 * hildon_touch_selector_column_get_text_column:
1082
 * @column: a #HildonTouchSelectorColumn
1083
 *
1084
 * Gets the model column set as the text source for @column.
1085
 *
1086
 * Returns: the index of the text column for @column, or -1 if unset.
1087
 *
1088
 * Since: 2.2
1089
 **/
1090
gint
1091
hildon_touch_selector_column_get_text_column (HildonTouchSelectorColumn *column)
1092
{
1093
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (column), -1);
1094
1095
  return column->priv->text_column;
1096
}
1097
1098
static void
1099
hildon_touch_selector_column_get_property (GObject *object, guint property_id,
1100
                                           GValue *value, GParamSpec *pspec)
1101
{
1102
  switch (property_id) {
1103
  case PROP_TEXT_COLUMN:
1104
    g_value_set_int (value,
1105
                     hildon_touch_selector_column_get_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object)));
1106
    break;
1107
  default:
1108
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1109
  }
1110
}
1111
1112
static void
1113
hildon_touch_selector_column_set_property (GObject *object, guint property_id,
1114
                                           const GValue *value, GParamSpec *pspec)
1115
{
1116
  switch (property_id) {
1117
  case PROP_TEXT_COLUMN:
1118
    hildon_touch_selector_column_set_text_column (HILDON_TOUCH_SELECTOR_COLUMN (object),
1119
                                                  g_value_get_int (value));
1120
    break;
1121
  default:
1122
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1123
  }
1124
}
1125
1126
static void
1127
hildon_touch_selector_column_dispose      (GObject *object)
1128
{
1129
  HildonTouchSelectorColumnPrivate *priv =
1130
      HILDON_TOUCH_SELECTOR_COLUMN (object)->priv;
1131
1132
  if (priv->model != NULL) {
1133
      g_object_unref (priv->model);
1134
      priv->model = NULL;
1135
  }
1136
1137
  if (priv->filter != NULL) {
1138
      g_object_unref (priv->filter);
1139
      priv->filter = NULL;
1140
  }
1141
1142
  G_OBJECT_CLASS (hildon_touch_selector_column_parent_class)->dispose (object);
1143
}
1144
1145
static void
1146
hildon_touch_selector_column_finalize     (GObject *object)
1147
{
1148
  HildonTouchSelectorColumnPrivate *priv = HILDON_TOUCH_SELECTOR_COLUMN (object)->priv;
1149
1150
  if (priv->initial_path) {
1151
    gtk_tree_path_free (priv->initial_path);
1152
  }
1153
1154
  G_OBJECT_CLASS (hildon_touch_selector_column_parent_class)->finalize (object);
1155
}
1156
1157
/* ------------------------ GtkCellLayout implementation -------------------- */
1158
static void
1159
hildon_touch_selector_column_cell_layout_init (GtkCellLayoutIface      *iface)
1160
{
1161
  iface->pack_start         = hildon_touch_selector_column_cell_layout_pack_start;
1162
  iface->pack_end           = hildon_touch_selector_column_cell_layout_pack_end;
1163
  iface->clear              = hildon_touch_selector_column_cell_layout_clear;
1164
  iface->add_attribute      = hildon_touch_selector_column_cell_layout_add_attribute;
1165
  iface->set_cell_data_func = hildon_touch_selector_column_cell_layout_set_cell_data_func;
1166
  iface->clear_attributes   = hildon_touch_selector_column_cell_layout_clear_attributes;
1167
  iface->reorder            = hildon_touch_selector_column_cell_layout_reorder;
1168
  iface->get_cells          = hildon_touch_selector_column_cell_layout_get_cells;
1169
}
1170
1171
static void
1172
hildon_touch_selector_column_cell_layout_pack_start (GtkCellLayout         *cell_layout,
1173
                                               GtkCellRenderer       *cell,
1174
                                               gboolean               expand)
1175
{
1176
  HildonTouchSelectorColumn *sel_column = NULL;
1177
  GtkTreeViewColumn *view_column = NULL;
1178
1179
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1180
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1181
1182
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1183
1184
  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT(view_column), cell, expand);
1185
1186
}
1187
1188
static void
1189
hildon_touch_selector_column_cell_layout_pack_end (GtkCellLayout         *cell_layout,
1190
                                             GtkCellRenderer       *cell,
1191
                                             gboolean               expand)
1192
{
1193
  HildonTouchSelectorColumn *sel_column = NULL;
1194
  GtkTreeViewColumn *view_column = NULL;
1195
1196
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1197
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1198
1199
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1200
1201
  gtk_cell_layout_pack_end (GTK_CELL_LAYOUT(view_column), cell, expand);
1202
}
1203
1204
static void
1205
hildon_touch_selector_column_cell_layout_clear (GtkCellLayout         *cell_layout)
1206
{
1207
  HildonTouchSelectorColumn *sel_column = NULL;
1208
  GtkTreeViewColumn *view_column = NULL;
1209
1210
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1211
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1212
1213
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1214
1215
  gtk_cell_layout_clear (GTK_CELL_LAYOUT(view_column));
1216
}
1217
1218
static void
1219
hildon_touch_selector_column_cell_layout_add_attribute (GtkCellLayout         *cell_layout,
1220
                                                  GtkCellRenderer       *cell,
1221
                                                  const gchar           *attribute,
1222
                                                  gint                   column)
1223
{
1224
  HildonTouchSelectorColumn *sel_column = NULL;
1225
  GtkTreeViewColumn *view_column = NULL;
1226
1227
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1228
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1229
1230
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1231
1232
  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT(view_column), cell, attribute, column);
1233
}
1234
1235
1236
static void
1237
hildon_touch_selector_column_cell_layout_set_cell_data_func (GtkCellLayout         *cell_layout,
1238
                                                       GtkCellRenderer       *cell,
1239
                                                       GtkCellLayoutDataFunc  func,
1240
                                                       gpointer               func_data,
1241
                                                       GDestroyNotify         destroy)
1242
{
1243
  HildonTouchSelectorColumn *sel_column = NULL;
1244
  GtkTreeViewColumn *view_column = NULL;
1245
1246
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1247
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1248
1249
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1250
1251
  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT(view_column), cell, func,
1252
                                      func_data, destroy);
1253
}
1254
1255
static void
1256
hildon_touch_selector_column_cell_layout_clear_attributes (GtkCellLayout         *cell_layout,
1257
                                                     GtkCellRenderer       *cell)
1258
{
1259
  HildonTouchSelectorColumn *sel_column = NULL;
1260
  GtkTreeViewColumn *view_column = NULL;
1261
1262
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1263
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1264
1265
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1266
1267
  gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (view_column), cell);
1268
}
1269
1270
static void
1271
hildon_touch_selector_column_cell_layout_reorder (GtkCellLayout         *cell_layout,
1272
                                            GtkCellRenderer       *cell,
1273
                                            gint                   position)
1274
{
1275
  HildonTouchSelectorColumn *sel_column = NULL;
1276
  GtkTreeViewColumn *view_column = NULL;
1277
1278
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout));
1279
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1280
1281
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1282
1283
  gtk_cell_layout_reorder (GTK_CELL_LAYOUT(view_column), cell, position);
1284
}
1285
1286
static GList*
1287
hildon_touch_selector_column_cell_layout_get_cells (GtkCellLayout         *cell_layout)
1288
{
1289
  HildonTouchSelectorColumn *sel_column = NULL;
1290
  GtkTreeViewColumn *view_column = NULL;
1291
1292
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_COLUMN (cell_layout), NULL);
1293
  sel_column = HILDON_TOUCH_SELECTOR_COLUMN (cell_layout);
1294
1295
  view_column = gtk_tree_view_get_column (sel_column->priv->tree_view, 0);
1296
1297
  return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT(view_column));
1298
}
1299
1300
/* ------------------------------ PUBLIC METHODS ---------------------------- */
1301
1302
/**
1303
 * hildon_touch_selector_new:
1304
 *
1305
 * Creates a new empty #HildonTouchSelector.
1306
 *
1307
 * Returns: a new #HildonTouchSelector.
1308
 *
1309
 * Since: 2.2
1310
 **/
1311
GtkWidget *
1312
hildon_touch_selector_new (void)
1313
{
1314
  return g_object_new (HILDON_TYPE_TOUCH_SELECTOR, NULL);
1315
}
1316
1317
/**
1318
 * hildon_touch_selector_new_text:
1319
 *
1320
 * Creates a #HildonTouchSelector with a single text column that
1321
 * can be populated conveniently through hildon_touch_selector_append_text(),
1322
 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
1323
 *
1324
 * Returns: A new #HildonTouchSelector
1325
 *
1326
 * Since: 2.2
1327
 **/
1328
GtkWidget *
1329
hildon_touch_selector_new_text (void)
1330
{
1331
  GtkWidget *selector;
1332
  GtkListStore *store;
1333
1334
  selector = hildon_touch_selector_new ();
1335
  store = gtk_list_store_new (1, G_TYPE_STRING);
1336
1337
  hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
1338
                                            GTK_TREE_MODEL (store), TRUE);
1339
1340
  g_object_unref (store);
1341
1342
  return selector;
1343
}
1344
1345
/**
1346
 * hildon_touch_selector_append_text:
1347
 * @selector: A #HildonTouchSelector.
1348
 * @text: a non %NULL text string.
1349
 *
1350
 * Appends a new entry in a #HildonTouchSelector created with
1351
 * hildon_touch_selector_new_text().
1352
 *
1353
 * Since: 2.2
1354
 **/
1355
void
1356
hildon_touch_selector_append_text (HildonTouchSelector * selector,
1357
                                   const gchar * text)
1358
{
1359
  GtkTreeModel *model;
1360
1361
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1362
  g_return_if_fail (text != NULL);
1363
1364
  model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1365
1366
  g_return_if_fail (GTK_IS_LIST_STORE (model));
1367
1368
  gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
1369
                                     NULL, G_MAXINT, 0, text, -1);
1370
}
1371
1372
/**
1373
 * hildon_touch_selector_prepend_text:
1374
 * @selector: A #HildonTouchSelector.
1375
 * @text: a non %NULL text string.
1376
 *
1377
 * Prepends a new entry in a #HildonTouchSelector created with
1378
 * hildon_touch_selector_new_text().
1379
 *
1380
 * Since: 2.2
1381
 **/
1382
void
1383
hildon_touch_selector_prepend_text (HildonTouchSelector * selector,
1384
                                    const gchar * text)
1385
{
1386
  GtkTreeModel *model;
1387
1388
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1389
  g_return_if_fail (text != NULL);
1390
1391
  model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1392
1393
  g_return_if_fail (GTK_IS_LIST_STORE (model));
1394
1395
  gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
1396
                                     NULL, 0, 0, text, -1);
1397
}
1398
1399
/**
1400
 * hildon_touch_selector_insert_text:
1401
 * @selector: a #HildonTouchSelector.
1402
 * @position: the position to insert @text.
1403
 * @text: A non %NULL text string.
1404
 *
1405
 * Inserts a new entry in a particular position of a
1406
 * #HildonTouchSelector created with hildon_touch_selector_new_text().
1407
 *
1408
 * Since: 2.2
1409
 **/
1410
void
1411
hildon_touch_selector_insert_text (HildonTouchSelector * selector,
1412
                                   gint position, const gchar * text)
1413
{
1414
  GtkTreeModel *model;
1415
1416
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1417
  g_return_if_fail (text != NULL);
1418
  g_return_if_fail (position >= 0);
1419
1420
  model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
1421
1422
  g_return_if_fail (GTK_IS_LIST_STORE (model));
1423
1424
  gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
1425
                                     NULL, position, 0, text, -1);
1426
}
1427
1428
static void
1429
hildon_touch_selector_add_live_search (HildonTouchSelector *selector,
1430
                                       HildonTouchSelectorColumn *column)
1431
{
1432
  if (column->priv->livesearch == NULL) {
1433
    gint text_column;
1434
1435
    column->priv->livesearch = hildon_live_search_new ();
1436
    hildon_live_search_set_filter (HILDON_LIVE_SEARCH (column->priv->livesearch),
1437
                                   GTK_TREE_MODEL_FILTER (column->priv->filter));
1438
    g_signal_connect (column->priv->livesearch, "refilter",
1439
                      G_CALLBACK (on_live_search_refilter), selector);
1440
    gtk_box_pack_start (GTK_BOX (column->priv->vbox),
1441
                        column->priv->livesearch,
1442
                        FALSE, FALSE, 0);
1443
    hildon_live_search_widget_hook (HILDON_LIVE_SEARCH (column->priv->livesearch),
1444
                                    GTK_WIDGET (column->priv->vbox),
1445
                                    GTK_WIDGET (column->priv->tree_view));
1446
    text_column = hildon_touch_selector_column_get_text_column (column);
1447
    if (text_column > -1) {
1448
      hildon_live_search_set_visible_func (HILDON_LIVE_SEARCH (column->priv->livesearch),
1449
                                           hildon_live_search_visible_func,
1450
                                           column,
1451
                                           NULL);
1452
    }
1453
  }
1454
}
1455
1456
static void
1457
hildon_touch_selector_remove_live_search (HildonTouchSelector *selector)
1458
{
1459
  HildonTouchSelectorColumn *col;
1460
1461
  if (selector->priv->has_live_search == FALSE ||
1462
      selector->priv->columns == NULL)
1463
    return;
1464
1465
  col = (HildonTouchSelectorColumn *) selector->priv->columns->data;
1466
1467
  if (col->priv->livesearch != NULL) {
1468
    hildon_live_search_widget_unhook (HILDON_LIVE_SEARCH (col->priv->livesearch));
1469
    gtk_widget_destroy (col->priv->livesearch);
1470
    col->priv->livesearch = NULL;
1471
  }
1472
1473
  selector->priv->has_live_search = FALSE;
1474
}
1475
1476
/**
1477
 * hildon_touch_selector_append_column
1478
 * @selector: a #HildonTouchSelector
1479
 * @model: the #GtkTreeModel with the data of the column
1480
 * @cell_renderer: The #GtkCellRenderer where to draw each row contents.
1481
 * @Varargs: a %NULL-terminated pair of attributes and column numbers.
1482
 *
1483
 * This functions adds a new column to the widget, whose data will
1484
 * be obtained from the model. Only widgets added this way should used on
1485
 * the selection logic, the print function, the #HildonTouchSelector::changed
1486
 * signal, etc. Internally, a #GtkTreeView will be added to the widget, using
1487
 * @model as the data source. This will add a reference to @model, so you
1488
 * must unref it after calling this function if you are not going to
1489
 * use it anymore.
1490
 *
1491
 * You can optionally pass a #GtkCellRenderer in @cell_renderer,
1492
 * together with a %NULL-terminated list of pairs property/value, in
1493
 * the same way you would use gtk_tree_view_column_set_attributes().
1494
 * This will pack @cell_renderer at the start of the column, expanded
1495
 * by default.  If you prefer not to add it this way, you can simply
1496
 * pass %NULL to @cell_renderer and use the #GtkCellLayout interface
1497
 * on the returned #HildonTouchSelectorColumn to set your
1498
 * renderers. Please note that the returned #HildonTouchSelectorColumn
1499
 * is owned by @selector, you shouldn't unref it after setting it
1500
 * up.
1501
 *
1502
 * Initially, the returned #HildonTouchSelectorColumn will have its
1503
 * #HildonTouchSelectorColumn:text-column property unset. You should set
1504
 * it to a column in @model with type %G_TYPE_STRING. See
1505
 * hildon_touch_selector_column_set_text_column().
1506
 *
1507
 * This method could change the current #HildonTouchSelector:hildon-ui-mode.
1508
 * %HILDON_UI_MODE_NORMAL is only allowed with one column, so if the selector
1509
 * is in this mode, and a additional column is added,
1510
 * #HildonTouchSelector:hildon-ui-mode will change to %HILDON_UI_MODE_EDIT.
1511
 *
1512
 * Returns: the new column added added, %NULL otherwise.
1513
 *
1514
 * Since: 2.2
1515
 **/
1516
1517
HildonTouchSelectorColumn*
1518
hildon_touch_selector_append_column (HildonTouchSelector * selector,
1519
                                     GtkTreeModel * model,
1520
                                     GtkCellRenderer * cell_renderer, ...)
1521
{
1522
  va_list args;
1523
  HildonTouchSelectorColumn *new_column = NULL;
1524
  gboolean emit_changed = FALSE;
1525
  gint colnum;
1526
1527
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1528
  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1529
1530
  if (model != NULL) {
1531
1532
    va_start (args, cell_renderer);
1533
    new_column = _create_new_column (selector, model, &emit_changed, cell_renderer, args);
1534
    va_end (args);
1535
1536
    /* If we already have one column, disable live search */
1537
    if (selector->priv->has_live_search &&
1538
        selector->priv->columns != NULL &&
1539
        selector->priv->columns->next == NULL) {
1540
	    hildon_touch_selector_remove_live_search (selector);
1541
    }
1542
1543
    selector->priv->columns = g_slist_append (selector->priv->columns,
1544
                                              new_column);
1545
1546
    new_column->priv->vbox = gtk_vbox_new (FALSE, 0);
1547
    gtk_box_pack_start (GTK_BOX (new_column->priv->vbox),
1548
                        new_column->priv->panarea,
1549
                        TRUE, TRUE, 0);
1550
    gtk_box_pack_start (GTK_BOX (selector->priv->hbox),
1551
                        new_column->priv->vbox,
1552
                        TRUE, TRUE, 6);
1553
1554
    if (selector->priv->has_live_search) {
1555
      hildon_touch_selector_add_live_search (selector, new_column);
1556
    }
1557
1558
    gtk_widget_show_all (new_column->priv->vbox);
1559
1560
    gtk_widget_child_focus (GTK_WIDGET (selector),
1561
                            GTK_DIR_TAB_FORWARD);
1562
1563
    if (selector->priv->initial_scroll) {
1564
      _hildon_touch_selector_center_on_selected_items (selector, new_column);
1565
    }
1566
1567
  } else {
1568
    return NULL;
1569
  }
1570
1571
  g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1572
  if (emit_changed) {
1573
    colnum = g_slist_length (selector->priv->columns);
1574
    hildon_touch_selector_emit_value_changed (selector, colnum);
1575
  }
1576
1577
  hildon_touch_selector_check_ui_mode_coherence (selector);
1578
1579
  return new_column;
1580
}
1581
1582
/**
1583
 * hildon_touch_selector_append_text_column
1584
 * @selector: a #HildonTouchSelector
1585
 * @model: a #GtkTreeModel with data for the column
1586
 * @center: whether to center the text on the column
1587
 *
1588
 * Equivalent to hildon_touch_selector_append_column(), but using a
1589
 * default text cell renderer. This is the most common use case of the
1590
 * widget.
1591
 *
1592
 * Note that this call adds a reference to @model, so you must unref
1593
 * it afterwards if you are not going to use it anymore.
1594
 *
1595
 * Returns: the new column added, NULL otherwise.
1596
 *
1597
 * Since: 2.2
1598
 **/
1599
HildonTouchSelectorColumn*
1600
hildon_touch_selector_append_text_column (HildonTouchSelector * selector,
1601
                                          GtkTreeModel * model, gboolean center)
1602
{
1603
  gfloat xalign = center ? 0.5 : 0.0;
1604
  GtkCellRenderer *renderer;
1605
  HildonTouchSelectorColumn *column = NULL;
1606
1607
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1608
  g_return_val_if_fail (GTK_IS_TREE_MODEL (model), NULL);
1609
1610
  renderer = gtk_cell_renderer_text_new ();
1611
1612
  g_object_set (renderer,
1613
                "width", 1,
1614
                "xalign", xalign,
1615
                NULL);
1616
1617
  column = hildon_touch_selector_append_column (selector, model, renderer,
1618
                                                "text", 0, NULL);
1619
  hildon_touch_selector_column_set_text_column (column, 0);
1620
1621
  g_object_set (column->priv->panarea, "sps", 28, NULL);
1622
1623
  return column;
1624
}
1625
1626
/**
1627
 * hildon_touch_selector_remove_column:
1628
 * @selector: a #HildonTouchSelector
1629
 * @column: the position of the column to be removed
1630
 *
1631
 * Removes a column from @selector.
1632
 *
1633
 * Returns: %TRUE if the column was removed, %FALSE otherwise
1634
 *
1635
 * Since: 2.2
1636
 **/
1637
gboolean
1638
hildon_touch_selector_remove_column (HildonTouchSelector * selector, gint column)
1639
{
1640
  HildonTouchSelectorColumn *current_column = NULL;
1641
  HildonTouchSelectorPrivate *priv;
1642
1643
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
1644
  g_return_val_if_fail (column <
1645
                        hildon_touch_selector_get_num_columns (selector), FALSE);
1646
1647
  priv = HILDON_TOUCH_SELECTOR_GET_PRIVATE (selector);
1648
  current_column = g_slist_nth_data (priv->columns, column);
1649
1650
  gtk_container_remove (GTK_CONTAINER (priv->hbox), current_column->priv->vbox);
1651
  priv->columns = g_slist_remove (priv->columns, current_column);
1652
  g_object_unref (current_column);
1653
1654
  g_signal_emit (selector, hildon_touch_selector_signals[COLUMNS_CHANGED], 0);
1655
1656
  return TRUE;
1657
}
1658
1659
/**
1660
 * hildon_touch_selector_set_column_attributes:
1661
 * @selector: a #HildonTouchSelector
1662
 * @num_column: the number of the column whose attributes we're setting
1663
 * @cell_renderer: the #GtkCellRendere we're setting the attributes of
1664
 * @Varargs: A %NULL-terminated list of attributes.
1665
 *
1666
 * Sets the attributes for the given column. The attributes must be given
1667
 * in attribute/column pairs, just like in gtk_tree_view_column_set_attributes().
1668
 * All existing attributes are removed and replaced with the new ones.
1669
 *
1670
 * Deprecated: #HildonTouchSelectorColumn implements #GtkCellLayout, use this
1671
 *             interface instead. See
1672
 *             hildon_touch_selector_get_column().
1673
 *
1674
 * Since: 2.2
1675
 **/
1676
void
1677
hildon_touch_selector_set_column_attributes (HildonTouchSelector * selector,
1678
                                             gint num_column,
1679
                                             GtkCellRenderer * cell_renderer,
1680
                                             ...)
1681
{
1682
  va_list args;
1683
  GtkTreeViewColumn *tree_column = NULL;
1684
  HildonTouchSelectorColumn *current_column = NULL;
1685
  gchar *attribute = NULL;
1686
  gint value = 0;
1687
1688
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1689
  g_return_if_fail (num_column <
1690
                    hildon_touch_selector_get_num_columns (selector));
1691
1692
  current_column = g_slist_nth_data (selector->priv->columns, num_column);
1693
1694
  tree_column = gtk_tree_view_get_column (current_column->priv->tree_view, 0);
1695
  gtk_tree_view_remove_column (current_column->priv->tree_view, tree_column);
1696
1697
  tree_column = gtk_tree_view_column_new ();
1698
  gtk_tree_view_column_pack_start (tree_column, cell_renderer, TRUE);
1699
1700
  va_start (args, cell_renderer);
1701
  attribute = va_arg (args, gchar *);
1702
1703
  gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1704
1705
  while (attribute != NULL) {
1706
    value = va_arg (args, gint);
1707
    gtk_tree_view_column_add_attribute (tree_column, cell_renderer,
1708
                                        attribute, value);
1709
    attribute = va_arg (args, gchar *);
1710
  }
1711
1712
  va_end (args);
1713
1714
  gtk_tree_view_append_column (current_column->priv->tree_view, tree_column);
1715
}
1716
1717
/**
1718
 * hildon_touch_selector_get_num_columns:
1719
 * @selector: a #HildonTouchSelector
1720
 *
1721
 * Gets the number of columns in the #HildonTouchSelector.
1722
 *
1723
 * Returns: the number of columns in @selector.
1724
 *
1725
 * Since: 2.2
1726
 **/
1727
gint
1728
hildon_touch_selector_get_num_columns (HildonTouchSelector * selector)
1729
{
1730
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1731
1732
  return g_slist_length (selector->priv->columns);
1733
}
1734
1735
/**
1736
 * hildon_touch_selector_get_column_selection_mode:
1737
 * @selector: a #HildonTouchSelector
1738
 *
1739
 * Gets the selection mode of @selector.
1740
 *
1741
 * Returns: one of #HildonTouchSelectorSelectionMode
1742
 *
1743
 * Since: 2.2
1744
 **/
1745
HildonTouchSelectorSelectionMode
1746
hildon_touch_selector_get_column_selection_mode (HildonTouchSelector * selector)
1747
{
1748
  HildonTouchSelectorSelectionMode result =
1749
    HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1750
  GtkSelectionMode treeview_mode = GTK_SELECTION_BROWSE;
1751
  HildonTouchSelectorColumn *column = NULL;
1752
  GtkTreeSelection *selection = NULL;
1753
1754
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), result);
1755
  g_return_val_if_fail (hildon_touch_selector_get_num_columns (selector) > 0,
1756
                        result);
1757
1758
  column = HILDON_TOUCH_SELECTOR_COLUMN (selector->priv->columns->data);
1759
1760
  selection = gtk_tree_view_get_selection (column->priv->tree_view);
1761
  treeview_mode = gtk_tree_selection_get_mode (selection);
1762
1763
1764
  if (treeview_mode == GTK_SELECTION_MULTIPLE) {
1765
    result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE;
1766
  } else {
1767
    result = HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE;
1768
  }
1769
1770
  return result;
1771
}
1772
1773
/**
1774
 * hildon_touch_selector_set_column_selection_mode:
1775
 * @selector: a #HildonTouchSelector
1776
 * @mode: the #HildonTouchSelectorMode for @selector
1777
 *
1778
 * Sets the selection mode for @selector. See #HildonTouchSelectorSelectionMode.
1779
 *
1780
 * The new @mode will be set, but take into into account that the
1781
 * #HildonTouchSelectorSelectionMode is ignored if the @selector
1782
 * #HildonTouchSelector:hildon-ui-mode property is set to %HILDON_UI_MODE_NORMAL
1783
 *
1784
 * Since: 2.2
1785
 **/
1786
void
1787
hildon_touch_selector_set_column_selection_mode (HildonTouchSelector * selector,
1788
                                                 HildonTouchSelectorSelectionMode mode)
1789
{
1790
  GtkTreeView *tv = NULL;
1791
  HildonTouchSelectorColumn *column = NULL;
1792
  GtkTreeSelection *selection = NULL;
1793
  GtkSelectionMode treeview_mode = GTK_SELECTION_MULTIPLE;
1794
  GtkTreeIter iter;
1795
  HildonTouchSelectorSelectionMode current_mode;
1796
1797
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1798
  g_return_if_fail (hildon_touch_selector_get_num_columns (selector) > 0);
1799
1800
  current_mode = hildon_touch_selector_get_column_selection_mode (selector);
1801
1802
  if (current_mode == mode) {
1803
    return;
1804
  }
1805
1806
  column = HILDON_TOUCH_SELECTOR_COLUMN ((g_slist_nth (selector->priv->columns, 0))->data);
1807
  tv = column->priv->tree_view;
1808
1809
  if (tv) {
1810
    switch (mode) {
1811
    case HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE:
1812
      treeview_mode = GTK_SELECTION_BROWSE;
1813
      break;
1814
    case HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE:
1815
      treeview_mode = GTK_SELECTION_MULTIPLE;
1816
      break;
1817
    }
1818
1819
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1820
    gtk_tree_selection_set_mode (selection, treeview_mode);
1821
1822
    selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tv));
1823
    gtk_tree_selection_unselect_all (selection);
1824
    if (gtk_tree_model_get_iter_first (column->priv->filter, &iter)) {
1825
        gtk_tree_selection_select_iter (selection, &iter);
1826
    }
1827
1828
    /* the column changed was the first one */
1829
    hildon_touch_selector_emit_value_changed (selector, 0);
1830
  }
1831
1832
}
1833
1834
/**
1835
 * hildon_touch_selector_set_print_func:
1836
 * @selector: a #HildonTouchSelector
1837
 * @func: a #HildonTouchSelectorPrintFunc function
1838
 *
1839
 * Sets the function to be used by hildon_touch_selector_get_current_text().
1840
 * See hildon_touch_selector_set_print_func_full().
1841
 *
1842
 * Since: 2.2
1843
 **/
1844
void
1845
hildon_touch_selector_set_print_func (HildonTouchSelector * selector,
1846
                                      HildonTouchSelectorPrintFunc func)
1847
{
1848
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1849
1850
  hildon_touch_selector_set_print_func_full (selector, func, NULL, NULL);
1851
}
1852
1853
/**
1854
 * hildon_touch_selector_set_print_func_full:
1855
 * @selector: a #HildonTouchSelector
1856
 * @func: a #HildonTouchSelectorPrintFunc function
1857
 * @user_data: a pointer to user data or %NULL
1858
 * @destroy_func: a callback for freeing the user data or %NULL
1859
 *
1860
 * Sets the function to be used by hildon_touch_selector_get_current_text()
1861
 * to produce a text representation of the currently selected items in @selector.
1862
 * The default function will return a concatenation of comma separated items
1863
 * selected in each column in @selector. Use this to override this method if you
1864
 * need a particular representation for your application.
1865
 *
1866
 * Since: 2.2
1867
 **/
1868
void
1869
hildon_touch_selector_set_print_func_full (HildonTouchSelector          *selector,
1870
                                           HildonTouchSelectorPrintFunc  func,
1871
                                           gpointer                      user_data,
1872
                                           GDestroyNotify                destroy_func)
1873
{
1874
  gpointer       old_user_data;
1875
  GDestroyNotify old_destroy_func;
1876
1877
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1878
1879
  old_user_data = selector->priv->print_user_data;
1880
  old_destroy_func = selector->priv->print_destroy_func;
1881
1882
  selector->priv->print_func = func;
1883
  selector->priv->print_user_data = user_data;
1884
  selector->priv->print_destroy_func = destroy_func;
1885
1886
  if (old_destroy_func && old_user_data != user_data)
1887
    (*old_destroy_func) (old_user_data);
1888
}
1889
1890
/**
1891
 * hildon_touch_selector_get_print_func:
1892
 * @selector: a #HildonTouchSelector
1893
 *
1894
 * Gets the #HildonTouchSelectorPrintFunc currently used. See
1895
 * hildon_touch_selector_set_print_func().
1896
 *
1897
 * Returns: a #HildonTouchSelectorPrintFunc or %NULL if the default
1898
 * one is currently used.
1899
 **/
1900
HildonTouchSelectorPrintFunc
1901
hildon_touch_selector_get_print_func (HildonTouchSelector * selector)
1902
{
1903
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
1904
1905
  return selector->priv->print_func;
1906
}
1907
1908
/**
1909
 * hildon_touch_selector_set_active:
1910
 * @selector: a #HildonTouchSelector
1911
 * @column: column number
1912
 * @index: the index of the item to select, or -1 to have no active item
1913
 *
1914
 * Sets the active item of the #HildonTouchSelector to @index. The
1915
 * column number is taken from @column.
1916
 *
1917
 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1918
 *
1919
 * Since: 2.2
1920
 **/
1921
void
1922
hildon_touch_selector_set_active                (HildonTouchSelector *selector,
1923
                                                 gint                 column,
1924
                                                 gint                 index)
1925
{
1926
  GtkTreeSelection *selection = NULL;
1927
  HildonTouchSelectorColumn *current_column = NULL;
1928
  HildonTouchSelectorSelectionMode mode;
1929
  GtkTreePath *path, *filter_path;
1930
1931
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
1932
  g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
1933
  mode = hildon_touch_selector_get_column_selection_mode (selector);
1934
  g_return_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
1935
1936
  current_column = g_slist_nth_data (selector->priv->columns, column);
1937
1938
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1939
1940
  if (index == -1) {
1941
      gtk_tree_selection_unselect_all (selection);
1942
      hildon_touch_selector_emit_value_changed (selector, column);
1943
      return;
1944
  }
1945
1946
  path = gtk_tree_path_new_from_indices (index, -1);
1947
  filter_path = gtk_tree_model_filter_convert_child_path_to_path (
1948
      GTK_TREE_MODEL_FILTER (current_column->priv->filter), path);
1949
1950
  if (filter_path != NULL) {
1951
      gtk_tree_selection_unselect_all (selection);
1952
      gtk_tree_selection_select_path (selection, filter_path);
1953
1954
      hildon_touch_selector_emit_value_changed (selector, column);
1955
      gtk_tree_path_free (filter_path);
1956
  }
1957
  gtk_tree_path_free (path);
1958
}
1959
1960
/**
1961
 * hildon_touch_selector_get_active:
1962
 * @selector: a #HildonTouchSelector
1963
 * @column: column number
1964
 *
1965
 * Returns the index of the currently active item in column number
1966
 * @column, or -1 if there's no active item.
1967
 *
1968
 * @selector must be in %HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE
1969
 *
1970
 * Returns: an integer which is the index of the currently active
1971
 * item, or -1 if there's no active item.
1972
 *
1973
 * Since: 2.2
1974
 **/
1975
gint
1976
hildon_touch_selector_get_active                (HildonTouchSelector *selector,
1977
                                                 gint                 column)
1978
{
1979
  GtkTreeSelection *selection = NULL;
1980
  HildonTouchSelectorColumn *current_column = NULL;
1981
  HildonTouchSelectorSelectionMode mode;
1982
  GtkTreeIter filter_iter;
1983
  gint index = -1;
1984
1985
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), -1);
1986
  g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector), -1);
1987
1988
  mode = hildon_touch_selector_get_column_selection_mode (selector);
1989
  g_return_val_if_fail (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE, -1);
1990
1991
  current_column = g_slist_nth_data (selector->priv->columns, column);
1992
1993
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
1994
1995
  if (gtk_tree_selection_get_selected (selection, NULL, &filter_iter)) {
1996
    GtkTreePath *path;
1997
    GtkTreeIter iter;
1998
    gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
1999
                                                      &iter, &filter_iter);
2000
    path = gtk_tree_model_get_path (current_column->priv->model, &iter);
2001
    index = (gtk_tree_path_get_indices (path))[0];
2002
    gtk_tree_path_free (path);
2003
  }
2004
2005
  return index;
2006
}
2007
2008
/**
2009
 * hildon_touch_selector_get_selected:
2010
 * @selector: a #HildonTouchSelector
2011
 * @column: the column to get the item from
2012
 * @iter: #GtkTreeIter currently selected
2013
 *
2014
 * Sets @iter to the currently selected node on the nth-column, if selection is
2015
 * set to %HILDON_TOUCH_SELECTOR_SINGLE or %HILDON_TOUCH_SELECTOR_MULTIPLE with
2016
 * a column different that the first one. @iter may be %NULL if you just want to
2017
 * test if selection has any selected items.
2018
 *
2019
 * This function will not work if selection is in
2020
 * %HILDON_TOUCH_SELECTOR_MULTIPLE mode and the column is the first one.
2021
 *
2022
 * To change the currently selected iter, see
2023
 * hildon_touch_selector_select_iter()
2024
 *
2025
 * See also gtk_tree_selection_get_selected() for more information.
2026
 *
2027
 * Returns: %TRUE if @iter was correctly set, %FALSE otherwise
2028
 *
2029
 * Since: 2.2
2030
 **/
2031
gboolean
2032
hildon_touch_selector_get_selected (HildonTouchSelector * selector,
2033
                                    gint column, GtkTreeIter * iter)
2034
{
2035
  GtkTreeSelection *selection = NULL;
2036
  HildonTouchSelectorColumn *current_column = NULL;
2037
  HildonTouchSelectorSelectionMode mode;
2038
  GtkTreeIter filter_iter;
2039
  gboolean result;
2040
2041
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
2042
  g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
2043
                        FALSE);
2044
  mode = hildon_touch_selector_get_column_selection_mode (selector);
2045
  g_return_val_if_fail
2046
    ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE) ||
2047
     ((mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)&&(column>0)),
2048
     FALSE);
2049
2050
  current_column = g_slist_nth_data (selector->priv->columns, column);
2051
2052
  selection =
2053
    gtk_tree_view_get_selection (GTK_TREE_VIEW (current_column->priv->tree_view));
2054
2055
  result = gtk_tree_selection_get_selected (selection, NULL, &filter_iter);
2056
2057
  if (iter) {
2058
    if (result == TRUE) {
2059
      gtk_tree_model_filter_convert_iter_to_child_iter
2060
        (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
2061
         iter, &filter_iter);
2062
    } else {
2063
      memset (iter, 0, sizeof (GtkTreeIter));
2064
    }
2065
  }
2066
2067
  return result;
2068
}
2069
2070
/**
2071
 * hildon_touch_selector_select_iter:
2072
 * @selector: a #HildonTouchSelector
2073
 * @column:   the column to select an item from
2074
 * @iter:     the #GtkTreeIter to be selected
2075
 * @scroll_to: whether to smoothly scroll to the item
2076
 *
2077
 * Sets the currently selected item in the column @column to the one pointed by @iter,
2078
 * optionally smoothly scrolling to it.
2079
 *
2080
 * To obtain the currently selected iter, see hildon_touch_selector_get_selected()
2081
 *
2082
 * Since: 2.2
2083
 **/
2084
void
2085
hildon_touch_selector_select_iter (HildonTouchSelector * selector,
2086
                                   gint column, GtkTreeIter * iter,
2087
                                   gboolean scroll_to)
2088
{
2089
  GtkTreePath *filter_path;
2090
  GtkTreeIter filter_iter;
2091
  HildonTouchSelectorColumn *current_column = NULL;
2092
  GtkTreeView *tv = NULL;
2093
  GtkTreeSelection *selection = NULL;
2094
2095
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2096
  g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
2097
2098
  current_column = g_slist_nth_data (selector->priv->columns, column);
2099
2100
  tv = current_column->priv->tree_view;
2101
  selection = gtk_tree_view_get_selection (tv);
2102
2103
  /* The given iter might be not visible, due to the
2104
     GtkTreeModelFilter we use. If so, don't change the selection. */
2105
  if (gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
2106
                                                        &filter_iter, iter) == FALSE)
2107
          return;
2108
2109
  filter_path = gtk_tree_model_get_path (current_column->priv->filter, &filter_iter);
2110
2111
  gtk_tree_selection_select_iter (selection, &filter_iter);
2112
2113
  if (scroll_to) {
2114
    hildon_touch_selector_scroll_to (current_column, tv, filter_path);
2115
  }
2116
2117
  hildon_touch_selector_emit_value_changed (selector, column);
2118
2119
  gtk_tree_path_free (filter_path);
2120
}
2121
2122
/**
2123
 * hildon_touch_selector_unselect_iter
2124
 * @selector: a #HildonTouchSelector
2125
 * @column:   the column to unselects from
2126
 * @iter:     the #GtkTreeIter to be unselected
2127
 *
2128
 * Unselect the item pointed by @iter in the column @column
2129
 *
2130
 * Since: 2.2
2131
 **/
2132
2133
void hildon_touch_selector_unselect_iter (HildonTouchSelector * selector,
2134
                                          gint column,
2135
                                          GtkTreeIter * iter)
2136
{
2137
  HildonTouchSelectorColumn *current_column = NULL;
2138
  GtkTreeSelection *selection = NULL;
2139
  GtkTreeIter filter_iter;
2140
2141
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2142
  g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
2143
2144
  current_column = g_slist_nth_data (selector->priv->columns, column);
2145
  selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
2146
  if (gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
2147
                                                        &filter_iter, iter) == FALSE)
2148
    return;
2149
2150
  gtk_tree_selection_unselect_iter (selection, &filter_iter);
2151
  hildon_touch_selector_emit_value_changed (selector, column);
2152
}
2153
2154
/**
2155
 * hildon_touch_selector_unselect_all:
2156
 * @selector: a #HildonTouchSelector
2157
 * @column: the position of the column to get the selected rows from
2158
 *
2159
 * Unselects all the selected items in the column @column.
2160
 *
2161
 * Since: 2.2
2162
 **/
2163
void
2164
hildon_touch_selector_unselect_all (HildonTouchSelector * selector,
2165
                                    gint column)
2166
{
2167
  HildonTouchSelectorColumn *current_column = NULL;
2168
  GtkTreeSelection *selection = NULL;
2169
2170
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2171
  g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
2172
2173
  current_column = g_slist_nth_data (selector->priv->columns, column);
2174
  selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
2175
  gtk_tree_selection_unselect_all (selection);
2176
2177
  hildon_touch_selector_emit_value_changed (selector, column);
2178
}
2179
2180
/**
2181
 * hildon_touch_selector_filter_selected_to_child_selected:
2182
 * @filter: 
2183
 * @filter_selected: 
2184
 *
2185
 * Converts a list of #GtkTreePath<!-- -->s from the internal
2186
 * #GtkTreeModelFilter to the child #GtkTreeModel.
2187
 *
2188
 * Returns: a newly created list of #GtkTreePath<!-- -->s. The list
2189
 * and paths should be freed when not needed anymore.
2190
 **/
2191
static GList *
2192
hildon_touch_selector_filter_selected_to_child_selected (GtkTreeModelFilter *filter,
2193
                                                         GList *filter_selected)
2194
{
2195
    GList *iter;
2196
    GList *child_selected = NULL;
2197
2198
    for (iter = filter_selected; iter; iter = iter->next)
2199
        child_selected = g_list_append (child_selected,
2200
                                        gtk_tree_model_filter_convert_path_to_child_path (
2201
                                            filter, (GtkTreePath *)iter->data));
2202
2203
    return child_selected;
2204
}
2205
2206
/**
2207
 * hildon_touch_selector_get_selected_rows:
2208
 * @selector: a #HildonTouchSelector
2209
 * @column: the position of the column to get the selected rows from
2210
 *
2211
 * Creates a list of #GtkTreePath<!-- -->s of all selected rows in a column. Additionally,
2212
 * if you to plan to modify the model after calling this function, you may
2213
 * want to convert the returned list into a list of GtkTreeRowReferences. To do this,
2214
 * you can use gtk_tree_row_reference_new().
2215
 *
2216
 * See gtk_tree_selection_get_selected_rows() for more information.
2217
 *
2218
 * Returns: A new #GList containing a #GtkTreePath for each selected row in the column @column.
2219
 *
2220
 * Since: 2.2
2221
 **/
2222
GList *
2223
hildon_touch_selector_get_selected_rows (HildonTouchSelector * selector,
2224
                                         gint column)
2225
{
2226
  GList *result;
2227
  GList *filter_selected;
2228
  HildonTouchSelectorColumn *current_column = NULL;
2229
  GtkTreeSelection *selection = NULL;
2230
2231
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
2232
  g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
2233
                        NULL);
2234
2235
  current_column = g_slist_nth_data (selector->priv->columns, column);
2236
  selection = gtk_tree_view_get_selection (current_column->priv->tree_view);
2237
2238
  filter_selected = gtk_tree_selection_get_selected_rows (selection, NULL);
2239
  result = hildon_touch_selector_filter_selected_to_child_selected
2240
      (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
2241
       filter_selected);
2242
  g_list_foreach (filter_selected, (GFunc) gtk_tree_path_free, NULL);
2243
  g_list_free (filter_selected);
2244
2245
  return result;
2246
}
2247
2248
/**
2249
 * hildon_touch_selector_get_model:
2250
 * @selector: a #HildonTouchSelector
2251
 * @column: the position of the column in @selector
2252
 *
2253
 * Gets the model of a column of @selector.
2254
 *
2255
 * Returns: the #GtkTreeModel for the column @column of @selector.
2256
 *
2257
 * Since: 2.2
2258
 **/
2259
GtkTreeModel *
2260
hildon_touch_selector_get_model (HildonTouchSelector * selector, gint column)
2261
{
2262
  HildonTouchSelectorColumn *current_column = NULL;
2263
2264
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
2265
  g_return_val_if_fail (column < hildon_touch_selector_get_num_columns (selector),
2266
                        NULL);
2267
2268
  current_column = g_slist_nth_data (selector->priv->columns, column);
2269
2270
  return current_column->priv->model;
2271
}
2272
2273
static void
2274
on_row_changed (GtkTreeModel *model,
2275
                GtkTreePath *path,
2276
                GtkTreeIter *iter,
2277
                gpointer userdata)
2278
{
2279
  HildonTouchSelector *selector;
2280
  HildonTouchSelectorColumn *current_column;
2281
  GtkTreePath *filter_path;
2282
2283
  gint column = 0;
2284
  GSList *col;
2285
2286
  selector = HILDON_TOUCH_SELECTOR (userdata);
2287
2288
  for (col = selector->priv->columns; col != NULL; col = col->next) {
2289
    current_column = HILDON_TOUCH_SELECTOR_COLUMN (col->data);
2290
    if (current_column->priv->model == model) {
2291
        filter_path =
2292
            gtk_tree_model_filter_convert_child_path_to_path (GTK_TREE_MODEL_FILTER (current_column->priv->filter),
2293
                                                              path);
2294
        if (filter_path &&
2295
            gtk_tree_selection_path_is_selected (gtk_tree_view_get_selection (current_column->priv->tree_view),
2296
                                                 filter_path)) {
2297
            hildon_touch_selector_emit_value_changed (selector, column);
2298
        }
2299
        gtk_tree_path_free (filter_path);
2300
    }
2301
    column ++;
2302
  }
2303
}
2304
2305
static void
2306
on_row_deleted (GtkTreeModel *model,
2307
                GtkTreePath *path,
2308
                gpointer userdata)
2309
{
2310
  HildonTouchSelector *selector = HILDON_TOUCH_SELECTOR (userdata);
2311
  gint column = 0;
2312
  GSList *col = selector->priv->columns;
2313
2314
  while (col != NULL) {
2315
    HildonTouchSelectorColumn *current_column;
2316
    current_column = HILDON_TOUCH_SELECTOR_COLUMN (col->data);
2317
    if (current_column->priv->model == model) {
2318
      GtkTreeSelection *sel = gtk_tree_view_get_selection (current_column->priv->tree_view);
2319
      if (gtk_tree_selection_get_mode (sel) == GTK_SELECTION_BROWSE &&
2320
          gtk_tree_model_iter_n_children (model, NULL) > 0 &&
2321
          gtk_tree_selection_count_selected_rows (sel) == 0) {
2322
        GtkTreeIter iter;
2323
        GtkTreePath *first;
2324
2325
        gtk_tree_model_get_iter_first (current_column->priv->filter, &iter);
2326
        first = gtk_tree_model_get_path (current_column->priv->filter, &iter);
2327
        gtk_tree_selection_select_path (sel, first);
2328
        gtk_tree_path_free (first);
2329
      }
2330
      hildon_touch_selector_emit_value_changed (selector, column);
2331
    }
2332
    col = col->next;
2333
    column ++;
2334
  }
2335
}
2336
2337
static void
2338
_hildon_touch_selector_set_model (HildonTouchSelector * selector,
2339
                                  gint column, GtkTreeModel * model)
2340
{
2341
  HildonTouchSelectorColumn *current_column = NULL;
2342
2343
  current_column =
2344
    HILDON_TOUCH_SELECTOR_COLUMN (g_slist_nth_data (selector->priv->columns, column));
2345
2346
  if (current_column->priv->model) {
2347
    g_signal_handlers_disconnect_by_func (current_column->priv->model,
2348
                                          on_row_changed, selector);
2349
    g_signal_handlers_disconnect_by_func (current_column->priv->model,
2350
                                          on_row_deleted, selector);
2351
    g_object_unref (current_column->priv->model);
2352
  }
2353
2354
  current_column->priv->model = g_object_ref (model);
2355
2356
  if (current_column->priv->filter) {
2357
    g_object_unref (current_column->priv->filter);
2358
  }
2359
2360
  current_column->priv->filter = gtk_tree_model_filter_new (model, NULL);
2361
  gtk_tree_view_set_model (current_column->priv->tree_view,
2362
                           current_column->priv->filter);
2363
2364
  g_signal_connect (model, "row-changed",
2365
                    G_CALLBACK (on_row_changed), selector);
2366
  g_signal_connect_after (model, "row-deleted",
2367
                          G_CALLBACK (on_row_deleted), selector);
2368
}
2369
2370
/**
2371
 * hildon_touch_selector_set_model:
2372
 * @selector: a #HildonTouchSelector
2373
 * @column: the position of the column to set the model to
2374
 * @model: a #GtkTreeModel. It increases a reference so you are not
2375
 * going to use the model anymore, unref it.
2376
 *
2377
 * Sets the #GtkTreeModel for a particular column in @model.
2378
 *
2379
 * Note that this call adds a reference to @model, so you must unref
2380
 * it afterwards if you are not going to use it anymore.
2381
 *
2382
 * Since: 2.2
2383
 **/
2384
void
2385
hildon_touch_selector_set_model (HildonTouchSelector * selector,
2386
                                 gint column, GtkTreeModel * model)
2387
{
2388
  g_return_if_fail (HILDON_TOUCH_SELECTOR (selector));
2389
  g_return_if_fail (column < hildon_touch_selector_get_num_columns (selector));
2390
2391
  HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->set_model (selector, column, model);
2392
}
2393
2394
/**
2395
 * hildon_touch_selector_get_current_text:
2396
 * @selector: a #HildonTouchSelector
2397
 *
2398
 * Returns a string representing the currently selected items for
2399
 * each column of @selector. See hildon_touch_selector_set_print_func().
2400
 *
2401
 * Returns: a newly allocated string.
2402
 *
2403
 * Since: 2.2
2404
 **/
2405
gchar *
2406
hildon_touch_selector_get_current_text (HildonTouchSelector * selector)
2407
{
2408
  gchar *result = NULL;
2409
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
2410
2411
  if (selector->priv->print_func) {
2412
    result = (*selector->priv->print_func) (selector, selector->priv->print_user_data);
2413
  } else {
2414
    result = _default_print_func (selector, NULL);
2415
  }
2416
2417
  return result;
2418
}
2419
2420
static void
2421
search_nearest_element (HildonPannableArea *panarea,
2422
                        GtkTreeView *tv,
2423
                        GList *selected_rows,
2424
                        GtkTreePath **nearest_path)
2425
{
2426
  GtkAdjustment *adj = NULL;
2427
  gdouble target_value = 0;
2428
  GdkRectangle rect;
2429
  GList *iter = NULL;
2430
  GtkTreePath *path = NULL;
2431
  gint y = -1;
2432
  gdouble nearest_distance = -1;
2433
  gdouble current_distance = -1;
2434
  GtkTreePath *result_path = NULL;
2435
2436
  g_assert (nearest_path != NULL);
2437
2438
  if (selected_rows == NULL) {
2439
    *nearest_path = NULL;
2440
    return;
2441
  }
2442
2443
  adj = hildon_pannable_area_get_vadjustment (panarea);
2444
  g_return_if_fail (adj != NULL);
2445
2446
  /* we add this in order to check the nearest to the center of
2447
     the visible area */
2448
  target_value = gtk_adjustment_get_value (adj) + adj->page_size/2;
2449
2450
  path = result_path = selected_rows->data;
2451
  gtk_tree_view_get_background_area (tv, path, NULL, &rect);
2452
  gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
2453
  nearest_distance = abs (target_value - y);
2454
2455
  for (iter = selected_rows->next; iter; iter = g_list_next (iter)) {
2456
    gtk_tree_view_get_background_area (tv, path, NULL, &rect);
2457
    gtk_tree_view_convert_bin_window_to_tree_coords (tv, 0, rect.y, NULL, &y);
2458
    current_distance = abs (target_value - y);
2459
    if (current_distance < nearest_distance) {
2460
      nearest_distance = current_distance;
2461
      result_path = path;
2462
    }
2463
  }
2464
2465
  *nearest_path = result_path;
2466
}
2467
2468
static gboolean
2469
on_realize_cb                                  (GtkWidget *widget,
2470
                                                gpointer data)
2471
{
2472
  HildonTouchSelectorColumn *column = NULL;
2473
  GdkRectangle rect;
2474
  gint y;
2475
2476
  column = HILDON_TOUCH_SELECTOR_COLUMN (data);
2477
2478
  if (column->priv->initial_path) {
2479
    gtk_tree_view_get_background_area (GTK_TREE_VIEW (column->priv->tree_view),
2480
                                       column->priv->initial_path, NULL, &rect);
2481
    gtk_tree_view_convert_bin_window_to_tree_coords
2482
      (GTK_TREE_VIEW (column->priv->tree_view),
2483
       0, rect.y, NULL, &y);
2484
2485
    hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA (column->priv->panarea),
2486
                                    -1, y);
2487
2488
    gtk_tree_path_free (column->priv->initial_path);
2489
2490
    column->priv->initial_path = NULL;
2491
2492
  }
2493
2494
  g_signal_handler_disconnect (column->priv->panarea,
2495
                               column->priv->realize_handler);
2496
2497
  return FALSE;
2498
}
2499
2500
static void
2501
hildon_touch_selector_scroll_to (HildonTouchSelectorColumn *column,
2502
                                 GtkTreeView *tv,
2503
                                 GtkTreePath *path)
2504
{
2505
  if (GTK_WIDGET_REALIZED (column->priv->panarea)) {
2506
    GdkRectangle rect;
2507
    gint y;
2508
2509
    gtk_tree_view_get_background_area (tv,
2510
                                       path, NULL, &rect);
2511
    gtk_tree_view_convert_bin_window_to_tree_coords (tv,
2512
                                                     0, rect.y, NULL, &y);
2513
2514
    hildon_pannable_area_scroll_to (HILDON_PANNABLE_AREA
2515
                                    (column->priv->panarea), -1, y);
2516
  } else {
2517
    if (column->priv->realize_handler != 0) {
2518
2519
      if (column->priv->initial_path) {
2520
        gtk_tree_path_free (column->priv->initial_path);
2521
        column->priv->initial_path = NULL;
2522
      }
2523
2524
      g_signal_handler_disconnect (column->priv->panarea,
2525
                                   column->priv->realize_handler);
2526
      column->priv->realize_handler = 0;
2527
    }
2528
2529
    column->priv->initial_path = gtk_tree_path_copy (path);
2530
    column->priv->realize_handler =
2531
      g_signal_connect_after (G_OBJECT (column->priv->panarea), "realize",
2532
                              G_CALLBACK (on_realize_cb),
2533
                              column);
2534
  }
2535
}
2536
2537
/**
2538
 *
2539
 * Center on the selected item of a concrete column
2540
 *
2541
 * Returns: TRUE if was able to do that
2542
 *          FALSE otherwise
2543
 */
2544
static gboolean
2545
_hildon_touch_selector_center_on_selected_items (HildonTouchSelector *selector,
2546
                                                 HildonTouchSelectorColumn *column)
2547
{
2548
  GtkTreePath *path = NULL;
2549
  GList *selected_rows = NULL;
2550
  gint num_column = -1;
2551
2552
  num_column = g_slist_index (selector->priv->columns, column);
2553
2554
  selected_rows = hildon_touch_selector_get_selected_rows (selector, num_column);
2555
  if (selected_rows) {
2556
    search_nearest_element (HILDON_PANNABLE_AREA (column->priv->panarea),
2557
                             GTK_TREE_VIEW (column->priv->tree_view),
2558
                             selected_rows,
2559
                             &path);
2560
2561
    if (path != NULL) {
2562
      hildon_touch_selector_scroll_to (column,
2563
                                       GTK_TREE_VIEW (column->priv->tree_view),
2564
                                       path);
2565
    } else {
2566
      return FALSE;
2567
    }
2568
2569
    g_list_foreach (selected_rows, (GFunc) (gtk_tree_path_free), NULL);
2570
    g_list_free (selected_rows);
2571
  }
2572
2573
  return TRUE;
2574
}
2575
2576
static gboolean
2577
_hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
2578
{
2579
  HildonTouchSelectorSelectionMode mode;
2580
  gint n_columns;
2581
2582
  n_columns = hildon_touch_selector_get_num_columns (selector);
2583
  mode = hildon_touch_selector_get_column_selection_mode (selector);
2584
2585
  return ((n_columns > 1) || (mode == HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE));
2586
}
2587
2588
/**
2589
 * hildon_touch_selector_has_multiple_selection:
2590
 * @selector: A #HildonTouchSelector
2591
 *
2592
 * Determines whether @selector is complex enough to actually require an
2593
 * extra selection step than only picking an item. This is normally %TRUE
2594
 * if @selector has multiple columns, multiple selection, or when it is a
2595
 * more complex widget, like #HildonTouchSelectorEntry.
2596
 *
2597
 * This information is useful for widgets containing a #HildonTouchSelector,
2598
 * like #HildonPickerDialog, that could need a "Done" button, in case that
2599
 * its internal #HildonTouchSelector has multiple columns, for instance.
2600
 *
2601
 * Returns: %TRUE if @selector requires multiple selection steps.
2602
 *
2603
 * Since: 2.2
2604
 **/
2605
gboolean
2606
hildon_touch_selector_has_multiple_selection (HildonTouchSelector * selector)
2607
{
2608
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
2609
2610
  return HILDON_TOUCH_SELECTOR_GET_CLASS (selector)->has_multiple_selection (selector);
2611
}
2612
2613
2614
/**
2615
 * hildon_touch_selector_get_column:
2616
 * @selector: A #HildonTouchSelector
2617
 * @column: a column number
2618
 *
2619
 * Use this method to retrieve a #HildonTouchSelectorColumn. Then, you can use
2620
 * the #GtkCellLayout interface to set up the layout of the column.
2621
 *
2622
 * Returns: the @column<!-- -->-th #HildonTouchSelectorColumn in @selector
2623
 *
2624
 * Since: 2.2
2625
 **/
2626
HildonTouchSelectorColumn *
2627
hildon_touch_selector_get_column (HildonTouchSelector * selector,
2628
                                  gint column)
2629
{
2630
  gint num_columns = -1;
2631
2632
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), NULL);
2633
  num_columns = hildon_touch_selector_get_num_columns (selector);
2634
  g_return_val_if_fail (column < num_columns && column >= 0, NULL);
2635
2636
  return g_slist_nth_data (selector->priv->columns, column);
2637
}
2638
2639
2640
/**
2641
 * hildon_touch_selector_center_on_selected:
2642
 * @selector: a #HildonTouchSelector
2643
 *
2644
 * Ensures all the columns in a #HildonTouchSelector show a selected
2645
 * item. If one of the columns is in
2646
 * %HILDON_TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE mode, that column
2647
 * will be scrolled to ensure the selected item that is closest to the
2648
 * currently visible area is shown.
2649
 *
2650
 * The #HildonTouchSelector:initial-scroll property configure the widget
2651
 * in order to use this function at the first show.
2652
 *
2653
 * Take into account that the element is not centered until the widget is
2654
 * realized. If the widget is not realized when the function is called, it
2655
 * will be postponed. If you call this functions several times before the
2656
 * widgets is realized, only the last one will be used.
2657
 *
2658
 * This behaviour includes any call to hildon_touch_selector_center_on_index(),
2659
 * so take care calling this functions, or with the
2660
 * #HildonTouchSelector:initial-scroll property in order to get centered on the
2661
 * proper element.
2662
 *
2663
 * Since: 2.2
2664
 **/
2665
void
2666
hildon_touch_selector_center_on_selected         (HildonTouchSelector *selector)
2667
{
2668
  GSList *iter = NULL;
2669
2670
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2671
2672
  for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) {
2673
    _hildon_touch_selector_center_on_selected_items (selector,
2674
                                                    HILDON_TOUCH_SELECTOR_COLUMN (iter->data));
2675
  }
2676
}
2677
2678
/**
2679
 * hildon_touch_selector_optimal_size_request
2680
 * @selector: a #HildonTouchSelector
2681
 * @requisition: a #GtkRequisition
2682
 *
2683
 * Gets the optimal size request of the touch selector. This function is mostly
2684
 * intended for dialog implementations that include a #HildonTouchSelector and
2685
 * want to optimize the screen real state, for example, when you want a dialog
2686
 * to show as much of the selector, avoiding any extra empty space below the
2687
 * selector.
2688
 *
2689
 * See #HildonPickerDialog implementation for an example.
2690
 *
2691
 * This function is oriented to be used in the size_request of a dialog or window,
2692
 * if you are not sure do not use it.
2693
 *
2694
 * There is a precondition to this function: Since this function does not
2695
 * call the "size_request" method, it can only be used when you know that
2696
 * gtk_widget_size_request() has been called since the last time a resize was
2697
 * queued.
2698
 *
2699
 * Since: 2.2
2700
 **/
2701
void
2702
hildon_touch_selector_optimal_size_request      (HildonTouchSelector *selector,
2703
                                                 GtkRequisition *requisition)
2704
{
2705
  GSList *iter = NULL;
2706
  gint height = 0;
2707
  gint base_height = 0;
2708
2709
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2710
2711
  iter = selector->priv->columns;
2712
2713
  /* Default optimal values are the current ones */
2714
  gtk_widget_get_child_requisition (GTK_WIDGET (selector),
2715
                                    requisition);
2716
2717
  if (iter == NULL) {
2718
    height = requisition->height;
2719
  } else {
2720
    /* we use the normal requisition as base, as the touch selector can has
2721
       extra widgets, not only the columns (ie: HildonTouchSelectorEntry) */
2722
    base_height = requisition->height;
2723
  }
2724
2725
  /* Compute optimal height for the columns */
2726
  while (iter) {
2727
    HildonTouchSelectorColumn *column;
2728
    GtkWidget *child;
2729
    GtkRequisition child_requisition = {0};
2730
2731
    column = HILDON_TOUCH_SELECTOR_COLUMN (iter->data);
2732
    child = GTK_WIDGET (column->priv->tree_view);
2733
2734
    gtk_widget_get_child_requisition (child, &child_requisition);
2735
2736
    height = MAX (height, child_requisition.height);
2737
2738
    iter = g_slist_next (iter);
2739
  }
2740
2741
  requisition->height = base_height + height;
2742
}
2743
2744
2745
2746
/**
2747
 * hildon_touch_selector_get_hildon_ui_mode
2748
 * @selector: a #HildonTouchSelector
2749
 *
2750
 * Gets the current hildon-ui-mode, see #HildonUIMode for more information
2751
 *
2752
 * Returns: the current hildon-ui-mode
2753
 *
2754
 * Since: 2.2
2755
 **/
2756
HildonUIMode
2757
hildon_touch_selector_get_hildon_ui_mode        (HildonTouchSelector *selector)
2758
{
2759
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), HILDON_UI_MODE_EDIT);
2760
2761
  return selector->priv->hildon_ui_mode;
2762
}
2763
2764
/**
2765
 * hildon_touch_selector_set_hildon_ui_mode
2766
 * @selector: a #HildonTouchSelector
2767
 * @mode: a #HildonUIMode
2768
 *
2769
 * Sets the value of the property #HildonTouchSelector:hildon-ui-mode to be @mode,
2770
 * see #HildonUIMode for more information
2771
 *
2772
 * Note that the %HILDON_UI_MODE_NORMAL can be only used when the selector has
2773
 * one column, use the return value to check if the change was effective.
2774
 *
2775
 * Returns: %TRUE if #HildonTouchSelector:hildon-ui-mode was changed
2776
 *          %FALSE otherwise
2777
 *
2778
 * Since: 2.2
2779
 **/
2780
gboolean
2781
hildon_touch_selector_set_hildon_ui_mode        (HildonTouchSelector *selector,
2782
                                                 HildonUIMode         mode)
2783
{
2784
  gint num = 0;
2785
  GSList *iter = NULL;
2786
  HildonTouchSelectorColumn *column = NULL;
2787
  GtkTreeView *tree_view = NULL;
2788
2789
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
2790
  num = hildon_touch_selector_get_num_columns (selector);
2791
  g_return_val_if_fail ((mode == HILDON_UI_MODE_EDIT) || (num == 1), FALSE);
2792
2793
  if (mode == selector->priv->hildon_ui_mode) {
2794
    return FALSE;
2795
  }
2796
2797
  for (iter = selector->priv->columns; iter; iter = g_slist_next (iter)) {
2798
    column = HILDON_TOUCH_SELECTOR_COLUMN (iter->data);
2799
    tree_view = column->priv->tree_view;
2800
2801
    hildon_tree_view_set_hildon_ui_mode (tree_view, mode);
2802
2803
    /* looking at the code of hildon_tree_view_set_hildon_ui_mode, it seems
2804
       that it call the unselect_all, but it is required anyway */
2805
    if (mode == HILDON_UI_MODE_NORMAL) {
2806
      GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
2807
2808
      gtk_tree_selection_unselect_all (selection);
2809
    }
2810
  }
2811
2812
  selector->priv->hildon_ui_mode = mode;
2813
2814
  return TRUE;
2815
}
2816
2817
/**
2818
 * hildon_touch_selector_get_last_activated_row
2819
 * @selector: a #HildonTouchSelector
2820
 * @column: column number
2821
 *
2822
 * Gets a #GtkTreePath of the last row activated in a column (the last row that
2823
 * emitted a #GtkTreeView::row-activated signal). This is mainly useful if the
2824
 * @selector #HildonTouchSelector:hildon-ui-mode in set to %HILDON_UI_MODE_NORMAL,
2825
 * as using this state there is no real selection, so a method like
2826
 * hildon_touch_selector_get_selected_rows() will return always a empty
2827
 * selection.
2828
 *
2829
 * Anyway, this method works as well on %HILDON_UI_MODE_EDIT, but in this case
2830
 * is better, and more useful, to get the current selection.
2831
 *
2832
 * Returns: a newly allocated #GtkTreePath pointing to the last activated row
2833
 *          NULL if no row were activated.
2834
 *
2835
 * Since: 2.2
2836
 **/
2837
GtkTreePath*
2838
hildon_touch_selector_get_last_activated_row    (HildonTouchSelector *selector,
2839
                                                 gint                 column)
2840
{
2841
  HildonTouchSelectorColumn *selector_column = NULL;
2842
2843
  /* this method with check selector and that the column number is correct*/
2844
  selector_column = hildon_touch_selector_get_column (selector, column);
2845
2846
  if (selector_column == NULL) {
2847
    return NULL;
2848
  }
2849
2850
  if (selector_column->priv->last_activated != NULL) {
2851
    return gtk_tree_row_reference_get_path (selector_column->priv->last_activated);
2852
  } else {
2853
    return NULL;
2854
  }
2855
}
2856
2857
2858
/**
2859
 * hildon_touch_selector_center_on_index:
2860
 * @selector: a #HildonTouchSelector
2861
 * @column: column number
2862
 * @index: the index of the item to center on
2863
 *
2864
 * Ensures that the column number @column shows the element @index
2865
 *
2866
 * This is similar to hildon_touch_selector_center_on_selected() but with the
2867
 * difference that allows to center on a column item not selected.
2868
 *
2869
 * Take into account that the element is not centered until the widget is
2870
 * realized. If the widget is not realized when the function is called, it will
2871
 * be postponed. If you call this function several times before the widget is
2872
 * realized, only the last one will be used.
2873
 *
2874
 * This behaviour includes any call to hildon_touch_selector_center_on_selected().
2875
 * Check this function for more tips.
2876
 *
2877
 * Since: 2.2
2878
 **/
2879
void
2880
hildon_touch_selector_center_on_index (HildonTouchSelector *selector,
2881
                                       gint column,
2882
                                       gint index)
2883
{
2884
  HildonTouchSelectorColumn *current_column = NULL;
2885
  GtkTreePath *path = NULL;
2886
2887
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2888
  g_return_if_fail ((column >= 0) && (column < hildon_touch_selector_get_num_columns (selector)));
2889
  g_return_if_fail (index >= 0);
2890
2891
  current_column = g_slist_nth_data (selector->priv->columns, column);
2892
2893
  path = gtk_tree_path_new_from_indices (index, -1);
2894
2895
  hildon_touch_selector_scroll_to (current_column,
2896
                                   current_column->priv->tree_view,
2897
                                   path);
2898
  gtk_tree_path_free (path);
2899
}
2900
2901
/**
2902
 * hildon_touch_selector_set_live_search:
2903
 * @selector: a #HildonTouchSelector
2904
 * @live_search: whether @selector should have live search capabilities
2905
 *
2906
 * Toggles a #HildonLiveSearch widget in @selector. This is enabled by
2907
 * default in #HildonTouchSelector but disabled for some of its
2908
 * subclasses like #HildonTouchSelectorEntry, #HildonDateSelector, and
2909
 * #HildonTimeSelector.  For the former, #HildonLiveSearch makes no
2910
 * sense. In a multi-column #HildonTouchSelector, #HildonLiveSearch
2911
 * is not supported, so don't try to enable it in one.
2912
 *
2913
 * If more columns are added to @selector, the #HildonLiveSearch
2914
 * will be removed and the property set to %FALSE.
2915
 *
2916
 * Since: 2.2.10
2917
 **/
2918
void
2919
hildon_touch_selector_set_live_search (HildonTouchSelector *selector,
2920
                                       gboolean live_search)
2921
{
2922
  HildonTouchSelectorColumn *col;
2923
2924
  g_return_if_fail (HILDON_IS_TOUCH_SELECTOR (selector));
2925
2926
  if (selector->priv->has_live_search == live_search)
2927
    return;
2928
2929
  if (live_search) {
2930
    if (selector->priv->columns &&
2931
        selector->priv->columns->next == NULL) {
2932
      /* There is one and only one column already.  */
2933
      col = (HildonTouchSelectorColumn *) selector->priv->columns->data;
2934
      /* There is already a livesearch widget. Let's hook it up.  */
2935
      if (col->priv->livesearch) {
2936
        hildon_live_search_widget_hook (HILDON_LIVE_SEARCH (col->priv->livesearch),
2937
                                        GTK_WIDGET (col->priv->vbox),
2938
                                        GTK_WIDGET (col->priv->tree_view));
2939
      } else {
2940
        /* There is no livesearch widget yet. Create one.  */
2941
        hildon_touch_selector_add_live_search (selector, col);
2942
      }
2943
    } else if (selector->priv->columns &&
2944
               selector->priv->columns->next != NULL) {
2945
      g_critical ("Trying to set HildonTouchSelector::live-search to TRUE "
2946
                  "in a HildonTouchSelector instance with more than one column.");
2947
      return;
2948
    }
2949
  } else {
2950
    if (selector->priv->columns &&
2951
        selector->priv->columns->next == NULL) {
2952
        col = (HildonTouchSelectorColumn *) selector->priv->columns->data;
2953
        gtk_widget_hide (col->priv->livesearch);
2954
        hildon_live_search_widget_unhook (HILDON_LIVE_SEARCH (col->priv->livesearch));
2955
    }
2956
  }
2957
2958
  selector->priv->has_live_search = live_search;
2959
}
2960
2961
/**
2962
 * hildon_touch_selector_get_live_search:
2963
 * @selector: a #HildonTouchSelector
2964
 *
2965
 * Whether @selector has an embedded #HildonLiveSearch widget
2966
 *
2967
 * Returns: %TRUE if there is a #HildonLiveSearch in @selector, %FALSE
2968
 * otherwise
2969
 *
2970
 * Since: 2.2.10
2971
 **/
2972
gboolean
2973
hildon_touch_selector_get_live_search (HildonTouchSelector *selector)
2974
{
2975
  g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR (selector), FALSE);
2976
2977
  return selector->priv->has_live_search;
2978
}