2 * This file is a part of hildon
4 * Copyright (C) 2008 Nokia Corporation.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version. or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * SECTION:hildon-touch-selector-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 #GtkEntry. Items can also
29 * be searched and selected by typing in the entry.
31 * The main difference between the #GtkTreeModel used by #HildonTouchSelector
32 * and #HildonTouchSelectorEntry, is that the latter must always include a text
33 * column. You should set it with hildon_touch_selector_entry_set_text_column().
35 * Normally, you would use #HildonTouchSelectorEntry together with a
36 * #HildonPickerDialog activated from a button. For the most common
37 * cases, you should use #HildonPickerButton.
39 * If you only need a text only, one column selector, you can create it with
40 * hildon_touch_selector_entry_new_text() and populate it with
41 * hildon_touch_selector_append_text(), hildon_touch_selector_prepend_text(),
42 * and hildon_touch_selector_insert_text().
46 #include "hildon-touch-selector.h"
47 #include "hildon-touch-selector-entry.h"
49 G_DEFINE_TYPE (HildonTouchSelectorEntry, hildon_touch_selector_entry, HILDON_TYPE_TOUCH_SELECTOR)
51 #define HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE(o) \
52 (G_TYPE_INSTANCE_GET_PRIVATE ((o), HILDON_TYPE_TOUCH_SELECTOR_ENTRY, HildonTouchSelectorEntryPrivate))
54 typedef struct _HildonTouchSelectorEntryPrivate HildonTouchSelectorEntryPrivate;
56 static void entry_on_text_changed (GtkEditable * editable, gpointer userdata);
57 static void hildon_touch_selector_entry_changed (HildonTouchSelector * selector,
60 static void hildon_touch_selector_entry_set_model (HildonTouchSelector * selector,
61 gint column, GtkTreeModel *model);
62 static gboolean hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector);
65 _text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data);
68 struct _HildonTouchSelectorEntryPrivate {
78 hildon_touch_selector_entry_get_property (GObject *object, guint property_id,
79 GValue *value, GParamSpec *pspec)
81 switch (property_id) {
82 case PROP_TEXT_COLUMN:
83 g_value_set_int (value,
84 hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object)));
86 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
91 hildon_touch_selector_entry_set_property (GObject *object, guint property_id,
92 const GValue *value, GParamSpec *pspec)
94 switch (property_id) {
95 case PROP_TEXT_COLUMN:
96 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object),
97 g_value_get_int (value));
99 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
104 hildon_touch_selector_entry_class_init (HildonTouchSelectorEntryClass *klass)
106 GObjectClass *object_class = G_OBJECT_CLASS (klass);
107 HildonTouchSelectorClass *selector_class = HILDON_TOUCH_SELECTOR_CLASS (klass);
109 g_type_class_add_private (klass, sizeof (HildonTouchSelectorEntryPrivate));
111 selector_class->set_model = hildon_touch_selector_entry_set_model;
112 selector_class->has_multiple_selection = hildon_touch_selector_entry_has_multiple_selection;
114 object_class->get_property = hildon_touch_selector_entry_get_property;
115 object_class->set_property = hildon_touch_selector_entry_set_property;
118 * HildonTouchSelectorEntry:text-column:
120 * Deprecated: now this property is in HildonTouchSelectorColumn use
121 * hildon_touch_selector_entry_set_text_column() and
122 * hildon_touch_selector_entry_get_text_column() to manage this.
125 g_object_class_install_property (G_OBJECT_CLASS (klass),
127 g_param_spec_int ("text-column",
129 "A column in the data source model to get the strings from.",
137 hildon_touch_selector_entry_print_func (HildonTouchSelector * selector)
139 HildonTouchSelectorEntryPrivate *priv;
145 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
147 if (*(gtk_entry_get_text (GTK_ENTRY (priv->entry))) != '\0') {
148 text = g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
150 model = hildon_touch_selector_get_model (selector, 0);
151 if (hildon_touch_selector_get_selected (selector, 0, &iter)) {
152 column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
153 gtk_tree_model_get (model, &iter, column, &text, -1);
161 hildon_touch_selector_entry_init (HildonTouchSelectorEntry *self)
163 HildonTouchSelectorEntryPrivate *priv;
164 GtkEntryCompletion *completion;
166 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (self);
168 priv->entry = gtk_entry_new ();
169 gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE);
171 completion = gtk_entry_completion_new ();
172 gtk_entry_completion_set_inline_completion (completion, TRUE);
173 gtk_entry_completion_set_popup_completion (completion, FALSE);
174 gtk_entry_set_completion (GTK_ENTRY (priv->entry), completion);
176 gtk_widget_show (priv->entry);
177 g_signal_connect (G_OBJECT (priv->entry), "changed",
178 G_CALLBACK (entry_on_text_changed), self);
179 priv->signal_id = g_signal_connect (G_OBJECT (self), "changed",
180 G_CALLBACK (hildon_touch_selector_entry_changed), NULL);
182 hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (self), hildon_touch_selector_entry_print_func);
183 gtk_box_pack_start (GTK_BOX (self), priv->entry, FALSE, FALSE, 0);
187 hildon_touch_selector_entry_new (void)
189 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR_ENTRY, NULL);
193 * hildon_touch_selector_entry_new_text:
195 * Creates a #HildonTouchSelectorEntry with a single text column that
196 * can be populated conveniently through hildon_touch_selector_append_text(),
197 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
199 * Returns: A new #HildonTouchSelectorEntry
202 hildon_touch_selector_entry_new_text (void)
206 GtkEntryCompletion *completion;
207 HildonTouchSelectorEntryPrivate *priv;
208 HildonTouchSelectorColumn *column = NULL;
210 selector = hildon_touch_selector_entry_new ();
212 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
214 model = gtk_list_store_new (1, G_TYPE_STRING);
215 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
216 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model));
217 column = hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
218 GTK_TREE_MODEL (model), FALSE);
220 g_signal_connect (column, "notify::text-column", G_CALLBACK (_text_column_modified),
222 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector), 0);
228 _text_column_modified (GObject *pspec, GParamSpec *gobject, gpointer data)
230 HildonTouchSelectorEntry *selector;
231 HildonTouchSelectorEntryPrivate *priv;
232 GtkEntryCompletion *completion;
233 gint text_column = -1;
235 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (data));
236 selector = HILDON_TOUCH_SELECTOR_ENTRY (data);
238 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (HILDON_TOUCH_SELECTOR_ENTRY(selector));
239 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
241 text_column = hildon_touch_selector_entry_get_text_column (selector);
243 gtk_entry_completion_set_text_column (completion, text_column);
247 * hildon_touch_selector_entry_set_text_column:
248 * @selector: A #HildonTouchSelectorEntry
249 * @text_column: A column in model to get the strings from
251 * Sets the model column which touch selector box should use to get strings
252 * from to be @text_column.
256 hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector,
259 HildonTouchSelectorColumn *column = NULL;
261 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
262 g_return_if_fail (text_column >= -1);
264 column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector), 0);
266 g_object_set (G_OBJECT (column), "text-column", text_column, NULL);
270 * hildon_touch_selector_entry_get_text_column:
271 * @selector: A #HildonTouchSelectorEntry
273 * Returns the @column which the touch selector is using to get the strings from
277 hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector)
279 HildonTouchSelectorColumn *column = NULL;
280 gint text_column = -1;
282 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), -1);
284 column = hildon_touch_selector_get_column (HILDON_TOUCH_SELECTOR (selector),
287 g_object_get (G_OBJECT (column), "text-column", &text_column, NULL);
293 entry_on_text_changed (GtkEditable * editable,
296 HildonTouchSelector *selector;
297 HildonTouchSelectorEntryPrivate *priv;
303 gboolean found = FALSE;
304 gint text_column = -1;
306 entry = GTK_ENTRY (editable);
307 selector = HILDON_TOUCH_SELECTOR (userdata);
308 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
311 hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
313 prefix = gtk_entry_get_text (entry);
314 model = hildon_touch_selector_get_model (selector, 0);
316 if (!gtk_tree_model_get_iter_first (model, &iter)) {
321 gtk_tree_model_get (model, &iter, text_column, &text, -1);
322 found = g_str_has_prefix (text, prefix);
324 } while (found != TRUE && gtk_tree_model_iter_next (model, &iter));
326 g_signal_handler_block (selector, priv->signal_id);
328 /* We emit the HildonTouchSelector::changed signal because a change in the
329 GtkEntry represents a change in current selection, and therefore, users
330 should be notified. */
332 hildon_touch_selector_select_iter (selector, 0, &iter, TRUE);
334 g_signal_emit_by_name (selector, "changed", 0);
336 g_signal_handler_unblock (selector, priv->signal_id);
340 /* FIXME: This is actually a very ugly way to retrieve the text. Ideally,
341 we would have API to retrieve it from the base clase (HildonTouchSelector).
342 In the meantime, leaving it here.
345 hildon_touch_selector_get_text_from_model (HildonTouchSelectorEntry * selector)
347 HildonTouchSelectorEntryPrivate *priv;
351 GList *selected_rows;
353 gint text_column = -1;
355 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
357 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
358 text_column = hildon_touch_selector_entry_get_text_column (selector);
359 selected_rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0);
361 if (selected_rows == NULL) {
365 /* We are in single selection mode */
366 g_assert (selected_rows->next == NULL);
368 path = (GtkTreePath *)selected_rows->data;
369 gtk_tree_model_get_iter (model, &iter, path);
370 gtk_tree_model_get (model, &iter, text_column, &text, -1);
372 gtk_tree_path_free (path);
373 g_list_free (selected_rows);
379 hildon_touch_selector_entry_changed (HildonTouchSelector * selector,
380 gint column, gpointer user_data)
382 HildonTouchSelectorEntryPrivate *priv;
385 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
387 text = hildon_touch_selector_get_text_from_model (HILDON_TOUCH_SELECTOR_ENTRY (selector));
389 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
390 gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
396 hildon_touch_selector_entry_set_model (HildonTouchSelector * selector,
397 gint column, GtkTreeModel *model)
399 GtkEntryCompletion *completion;
400 HildonTouchSelectorEntryPrivate *priv;
401 gint text_column = -1;
403 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
404 g_return_if_fail (column == 0);
405 g_return_if_fail (GTK_IS_TREE_MODEL (model));
407 HILDON_TOUCH_SELECTOR_CLASS (hildon_touch_selector_entry_parent_class)->set_model (selector, column, model);
409 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
411 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
412 gtk_entry_completion_set_model (completion, model);
414 text_column = hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector));
416 gtk_entry_completion_set_text_column (completion, text_column);
420 hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector)
422 /* Always TRUE, given the GtkEntry. */