2 * This file is a part of hildon
4 * Copyright (C) 2008, 2009 Nokia Corporation.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * SECTION:hildon-touch-selector-entry
23 * @short_description: A selector widget with one column and a text entry
24 * @see_also: #HildonTouchSelector, #HildonPickerButton
26 * #HildonTouchSelectorEntry is a selector widget with a text entry, similar in
27 * behaviour to #GtkComboBoxEntry, that allows user to select an item from a
28 * predefined list or to enter a different one in a #HildonEntry. Items can also
29 * be searched and selected by typing in the entry. For more specific use cases,
30 * the #HildonEntry can be accessed directly with hildon_touch_selector_get_entry().
32 * The main difference between the #GtkTreeModel used by #HildonTouchSelector
33 * and #HildonTouchSelectorEntry, is that the latter must always include a text
34 * column. You should set it with hildon_touch_selector_entry_set_text_column().
36 * Normally, you would use #HildonTouchSelectorEntry together with a
37 * #HildonPickerDialog activated from a button. For the most common
38 * cases, you should use #HildonPickerButton.
40 * If you only need a text only, one column selector, you can create it with
41 * hildon_touch_selector_entry_new_text() and populate it with
42 * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(),
43 * and hildon_touch_selector_insert_text().
47 #include "hildon-touch-selector.h"
48 #include "hildon-touch-selector-entry.h"
49 #include "hildon-entry.h"
51 G_DEFINE_TYPE (HildonTouchSelectorEntry, hildon_touch_selector_entry, HILDON_TYPE_TOUCH_SELECTOR)
53 #define HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE(o) \
54 (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryPrivate))
56 typedef struct _HildonTouchSelectorEntryPrivate HildonTouchSelectorEntryPrivate;
58 static void entry_on_text_changed (GtkEditable * editable, gpointer userdata);
59 static void hildon_touch_selector_entry_changed (HildonTouchSelector * selector,
62 static void hildon_touch_selector_entry_set_model (HildonTouchSelector * selector,
63 gint column, GtkTreeModel *model);
64 static gboolean hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector);
67 _text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data);
70 struct _HildonTouchSelectorEntryPrivate {
80 hildon_touch_selector_entry_get_property (GObject *object, guint property_id,
81 GValue *value, GParamSpec *pspec)
83 switch (property_id) {
84 case PROP_TEXT_COLUMN:
85 g_value_set_int (value,
86 hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object)));
89 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
94 hildon_touch_selector_entry_set_property (GObject *object, guint property_id,
95 const GValue *value, GParamSpec *pspec)
97 switch (property_id) {
98 case PROP_TEXT_COLUMN:
99 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object),
100 g_value_get_int (value));
103 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
108 hildon_touch_selector_entry_class_init (HildonTouchSelectorEntryClass *klass)
110 GObjectClass *object_class = G_OBJECT_CLASS (klass);
111 HildonTouchSelectorClass *selector_class = HILDON_TOUCH_SELECTOR_CLASS (klass);
113 g_type_class_add_private (klass, sizeof (HildonTouchSelectorEntryPrivate));
115 selector_class->set_model = hildon_touch_selector_entry_set_model;
116 selector_class->has_multiple_selection = hildon_touch_selector_entry_has_multiple_selection;
118 object_class->get_property = hildon_touch_selector_entry_get_property;
119 object_class->set_property = hildon_touch_selector_entry_set_property;
122 * HildonTouchSelectorEntry:text-column:
124 * A column in the data source model to get the strings from.
126 * This property is deprecated. Use HildonTouchSelectorColumn:text-column
127 * instead. Use hildon_touch_selector_entry_set_text_column() and
128 * hildon_touch_selector_entry_get_text_column() to manage it.
130 * Deprecated: use HildonTouchSelectorColumn:text-column instead
134 g_object_class_install_property (G_OBJECT_CLASS (klass),
136 g_param_spec_int ("text-column",
138 "A column in the data source model to get the strings from.",
146 hildon_touch_selector_entry_print_func (HildonTouchSelector * selector, gpointer user_data)
148 HildonTouchSelectorEntryPrivate *priv;
154 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
156 if (*(gtk_entry_get_text (GTK_ENTRY (priv->entry))) != '\0') {
157 text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
159 model = hildon_touch_selector_get_model (selector, 0);
160 if (hildon_touch_selector_get_selected (selector, 0, &iter)) {
161 column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
162 gtk_tree_model_get (model, &iter, column, &text, -1);
170 hildon_touch_selector_entry_init (HildonTouchSelectorEntry *self)
172 HildonTouchSelectorEntryPrivate *priv;
173 GtkEntryCompletion *completion;
174 HildonGtkInputMode input_mode;
176 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (self);
178 priv->entry = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
179 gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE);
180 input_mode = hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry));
182 /* Disable unsupported input modes. */
183 input_mode &= ~HILDON_GTK_INPUT_MODE_MULTILINE;
184 input_mode &= ~HILDON_GTK_INPUT_MODE_INVISIBLE;
185 input_mode &= ~HILDON_GTK_INPUT_MODE_DICTIONARY;
187 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode);
189 completion = gtk_entry_completion_new ();
190 gtk_entry_completion_set_inline_completion (completion, TRUE);
191 gtk_entry_completion_set_popup_completion (completion, FALSE);
192 gtk_entry_set_completion (GTK_ENTRY (priv->entry), completion);
194 gtk_widget_show (priv->entry);
195 g_signal_connect (G_OBJECT (priv->entry), "changed",
196 G_CALLBACK (entry_on_text_changed), self);
197 priv->signal_id = g_signal_connect (G_OBJECT (self), "changed",
198 G_CALLBACK (hildon_touch_selector_entry_changed), NULL);
200 hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (self), hildon_touch_selector_entry_print_func);
201 gtk_box_pack_start (GTK_BOX (self), priv->entry, FALSE, FALSE, 0);
205 * hildon_touch_selector_entry_new:
207 * Creates a #HildonTouchSelectorEntry
209 * Returns: A new #HildonTouchSelectorEntry
214 hildon_touch_selector_entry_new (void)
216 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR_ENTRY, NULL);
220 * hildon_touch_selector_entry_new_text:
222 * Creates a #HildonTouchSelectorEntry with a single text column that
223 * can be populated conveniently through hildon_touch_selector_append_text(),
224 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
226 * Returns: A new #HildonTouchSelectorEntry
231 hildon_touch_selector_entry_new_text (void)
235 GtkEntryCompletion *completion;
236 HildonTouchSelectorEntryPrivate *priv;
237 HildonTouchSelectorColumn *column = NULL;
239 selector = hildon_touch_selector_entry_new ();
241 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
243 model = gtk_list_store_new (1, G_TYPE_STRING);
244 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
245 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model));
246 column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
247 GTK_TREE_MODEL (model), FALSE);
249 g_signal_connect (column, "notify::text-column", G_CALLBACK (_text_column_modified),
251 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector), 0);
257 _text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data)
259 HildonTouchSelectorEntry *selector;
260 HildonTouchSelectorEntryPrivate *priv;
261 GtkEntryCompletion *completion;
262 gint text_column = -1;
264 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (data));
265 selector = HILDON_TOUCH_SELECTOR_ENTRY (data);
267 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (HILDON_TOUCH_SELECTOR_ENTRY(selector));
268 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
270 text_column = hildon_touch_selector_entry_get_text_column (selector);
272 gtk_entry_completion_set_text_column (completion, text_column);
276 * hildon_touch_selector_entry_set_text_column:
277 * @selector: A #HildonTouchSelectorEntry
278 * @text_column: A column in model to get the strings from
280 * Sets the model column which touch selector box should use to get strings
281 * from to be @text_column.
286 hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector,
289 HildonTouchSelectorColumn *column = NULL;
291 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
292 g_return_if_fail (text_column >= -1);
294 column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), 0);
296 hildon_touch_selector_column_set_text_column (column, text_column);
300 * hildon_touch_selector_entry_get_text_column:
301 * @selector: A #HildonTouchSelectorEntry
303 * Gets the text column that @selector is using as a text column.
305 * Returns: the number of the column used as a text column.
310 hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector)
312 HildonTouchSelectorColumn *column = NULL;
313 gint text_column = -1;
315 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), -1);
317 column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector),
320 text_column = hildon_touch_selector_column_get_text_column (column);
326 * hildon_touch_selector_entry_set_input_mode:
327 * @selector: a #HildonTouchSelectorEntry
328 * @input_mode: #HildonGtkInputMode mask
330 * Sets the input mode to be used in the #GtkEntry in @selector. See hildon_gtk_entry_set_input_mode()
333 * It must be noted that not all input modes are available for the
334 * entry in @selector. In particular,
335 * %HILDON_GTK_INPUT_MODE_MULTILINE, %HILDON_GTK_INPUT_MODE_INVISIBLE,
336 * %HILDON_GTK_INPUT_MODE_DICTIONARY are disabled, since these are irrelevant
337 * for #HildonTouchSelectorEntry.
342 hildon_touch_selector_entry_set_input_mode (HildonTouchSelectorEntry * selector,
343 HildonGtkInputMode input_mode)
345 HildonTouchSelectorEntryPrivate *priv;
347 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
348 g_return_if_fail (!(input_mode & (HILDON_GTK_INPUT_MODE_MULTILINE |
349 HILDON_GTK_INPUT_MODE_INVISIBLE |
350 HILDON_GTK_INPUT_MODE_DICTIONARY)));
352 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
354 hildon_gtk_entry_set_input_mode (GTK_ENTRY (priv->entry), input_mode);
358 * hildon_touch_selector_entry_get_input_mode:
359 * @selector: a #HildonTouchSelectorEntry
361 * Gets the input mode used in the #GtkEntry in @selector. See hildon_gtk_entry_get_input_mode()
364 * Returns: a mask of #HildonGtkInputMode
369 hildon_touch_selector_entry_get_input_mode (HildonTouchSelectorEntry * selector)
371 HildonTouchSelectorEntryPrivate *priv;
373 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), HILDON_GTK_INPUT_MODE_ALPHA);
375 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
377 return hildon_gtk_entry_get_input_mode (GTK_ENTRY (priv->entry));
381 entry_on_text_changed (GtkEditable * editable,
384 HildonTouchSelector *selector;
385 HildonTouchSelectorEntryPrivate *priv;
391 gboolean found = FALSE;
392 gint text_column = -1;
394 entry = GTK_ENTRY (editable);
395 selector = HILDON_TOUCH_SELECTOR (userdata);
396 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
399 hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
401 prefix = gtk_entry_get_text (entry);
403 if (prefix[0] == '\0') {
407 model = hildon_touch_selector_get_model (selector, 0);
409 if (!gtk_tree_model_get_iter_first (model, &iter)) {
414 gtk_tree_model_get (model, &iter, text_column, &text, -1);
415 found = g_str_has_prefix (text, prefix);
417 } while (found != TRUE && gtk_tree_model_iter_next (model, &iter));
419 g_signal_handler_block (selector, priv->signal_id);
421 /* We emit the HildonTouchSelector::changed signal because a change in the
422 GtkEntry represents a change in current selection, and therefore, users
423 should be notified. */
425 hildon_touch_selector_select_iter (selector, 0, &iter, TRUE);
427 g_signal_emit_by_name (selector, "changed", 0);
429 g_signal_handler_unblock (selector, priv->signal_id);
433 /* FIXME: This is actually a very ugly way to retrieve the text. Ideally,
434 we would have API to retrieve it from the base clase (HildonTouchSelector).
435 In the meantime, leaving it here.
438 hildon_touch_selector_get_text_from_model (HildonTouchSelectorEntry * selector)
443 GList *selected_rows;
445 gint text_column = -1;
447 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
448 text_column = hildon_touch_selector_entry_get_text_column (selector);
449 selected_rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0);
451 if (selected_rows == NULL) {
455 /* We are in single selection mode */
456 g_assert (selected_rows->next == NULL);
458 path = (GtkTreePath *)selected_rows->data;
459 gtk_tree_model_get_iter (model, &iter, path);
460 gtk_tree_model_get (model, &iter, text_column, &text, -1);
462 gtk_tree_path_free (path);
463 g_list_free (selected_rows);
469 hildon_touch_selector_entry_changed (HildonTouchSelector * selector,
470 gint column, gpointer user_data)
472 HildonTouchSelectorEntryPrivate *priv;
475 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
477 text = hildon_touch_selector_get_text_from_model (HILDON_TOUCH_SELECTOR_ENTRY (selector));
479 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
480 gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
486 hildon_touch_selector_entry_set_model (HildonTouchSelector * selector,
487 gint column, GtkTreeModel *model)
489 GtkEntryCompletion *completion;
490 HildonTouchSelectorEntryPrivate *priv;
491 gint text_column = -1;
493 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
494 g_return_if_fail (column == 0);
495 g_return_if_fail (GTK_IS_TREE_MODEL (model));
497 HILDON_TOUCH_SELECTOR_CLASS (hildon_touch_selector_entry_parent_class)->set_model (selector, column, model);
499 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
501 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
502 gtk_entry_completion_set_model (completion, model);
504 text_column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
506 gtk_entry_completion_set_text_column (completion, text_column);
510 hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector)
512 /* Always TRUE, given the GtkEntry. */
517 * hildon_touch_selector_entry_get_entry:
518 * @selector: a #HildonTouchSelectorEntry.
520 * Provides access to the #HildonEntry in @selector. Use to programmatically
521 * change the contents in entry or modify its behavior.
523 * Returns: a #HildonEntry.
528 hildon_touch_selector_entry_get_entry (HildonTouchSelectorEntry * selector)
530 HildonTouchSelectorEntryPrivate *priv;
532 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), NULL);
534 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
536 return HILDON_ENTRY (priv->entry);