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 behaviour
27 * to #GtkComboBoxEntry, that allows user to select an item from a predefined list
28 * or to enter a different one in a #GtkEntry. Items can also be searched and selected
29 * 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 column.
33 * 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);
64 struct _HildonTouchSelectorEntryPrivate {
75 hildon_touch_selector_entry_get_property (GObject *object, guint property_id,
76 GValue *value, GParamSpec *pspec)
78 switch (property_id) {
79 case PROP_TEXT_COLUMN:
80 g_value_set_int (value,
81 hildon_touch_selector_entry_get_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object)));
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
88 hildon_touch_selector_entry_set_property (GObject *object, guint property_id,
89 const GValue *value, GParamSpec *pspec)
91 switch (property_id) {
92 case PROP_TEXT_COLUMN:
93 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (object),
94 g_value_get_int (value));
96 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
101 hildon_touch_selector_entry_class_init (HildonTouchSelectorEntryClass *klass)
103 GObjectClass *object_class = G_OBJECT_CLASS (klass);
104 HildonTouchSelectorClass *selector_class = HILDON_TOUCH_SELECTOR_CLASS (klass);
106 g_type_class_add_private (klass, sizeof (HildonTouchSelectorEntryPrivate));
108 selector_class->set_model = hildon_touch_selector_entry_set_model;
109 selector_class->has_multiple_selection = hildon_touch_selector_entry_has_multiple_selection;
111 object_class->get_property = hildon_touch_selector_entry_get_property;
112 object_class->set_property = hildon_touch_selector_entry_set_property;
114 g_object_class_install_property (G_OBJECT_CLASS (klass),
116 g_param_spec_int ("text-column",
118 "A column in the data source model to get the strings from.",
126 hildon_touch_selector_entry_print_func (HildonTouchSelector * selector)
128 HildonTouchSelectorEntryPrivate *priv;
130 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
132 return g_strdup (gtk_entry_get_text (GTK_ENTRY (priv->entry)));
136 hildon_touch_selector_entry_init (HildonTouchSelectorEntry *self)
138 HildonTouchSelectorEntryPrivate *priv;
139 GtkEntryCompletion *completion;
141 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (self);
143 priv->entry = gtk_entry_new ();
144 gtk_entry_set_activates_default (GTK_ENTRY (priv->entry), TRUE);
146 completion = gtk_entry_completion_new ();
147 gtk_entry_completion_set_inline_completion (completion, TRUE);
148 gtk_entry_completion_set_popup_completion (completion, FALSE);
149 gtk_entry_set_completion (GTK_ENTRY (priv->entry), completion);
151 gtk_widget_show (priv->entry);
152 g_signal_connect (G_OBJECT (priv->entry), "changed",
153 G_CALLBACK (entry_on_text_changed), self);
154 priv->signal_id = g_signal_connect (G_OBJECT (self), "changed",
155 G_CALLBACK (hildon_touch_selector_entry_changed), NULL);
157 hildon_touch_selector_set_print_func (HILDON_TOUCH_SELECTOR (self), hildon_touch_selector_entry_print_func);
158 gtk_box_pack_start (GTK_BOX (self), priv->entry, FALSE, FALSE, 0);
162 hildon_touch_selector_entry_new (void)
164 return g_object_new (HILDON_TYPE_TOUCH_SELECTOR_ENTRY, NULL);
168 * hildon_touch_selector_entry_new_text:
170 * Creates a #HildonTouchSelectorEntry with a single text column that
171 * can be populated conveniently through hildon_touch_selector_append_text(),
172 * hildon_touch_selector_prepend_text(), hildon_touch_selector_insert_text().
174 * Returns: A new #HildonTouchSelectorEntry
177 hildon_touch_selector_entry_new_text (void)
181 GtkEntryCompletion *completion;
182 HildonTouchSelectorEntryPrivate *priv;
184 selector = hildon_touch_selector_entry_new ();
186 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
188 model = gtk_list_store_new (1, G_TYPE_STRING);
189 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
190 gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (model));
192 hildon_touch_selector_append_text_column (HILDON_TOUCH_SELECTOR (selector),
193 GTK_TREE_MODEL (model), FALSE);
194 hildon_touch_selector_entry_set_text_column (HILDON_TOUCH_SELECTOR_ENTRY (selector), 0);
200 hildon_touch_selector_entry_set_text_column (HildonTouchSelectorEntry *selector,
203 HildonTouchSelectorEntryPrivate *priv;
204 GtkEntryCompletion *completion;
206 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
207 g_return_if_fail (text_column >= -1);
209 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
210 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
212 gtk_entry_completion_set_text_column (completion, text_column);
213 priv->text_column = text_column;
217 hildon_touch_selector_entry_get_text_column (HildonTouchSelectorEntry *selector)
219 HildonTouchSelectorEntryPrivate *priv;
221 g_return_val_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector), -1);
223 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
225 return priv->text_column;
229 entry_on_text_changed (GtkEditable * editable,
232 HildonTouchSelector *selector;
233 HildonTouchSelectorEntryPrivate *priv;
239 gboolean found = FALSE;
241 entry = GTK_ENTRY (editable);
242 selector = HILDON_TOUCH_SELECTOR (userdata);
243 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
245 prefix = gtk_entry_get_text (entry);
246 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
248 if (!gtk_tree_model_get_iter_first (model, &iter)) {
253 gtk_tree_model_get (model, &iter, priv->text_column, &text, -1);
254 found = g_str_has_prefix (text, prefix);
256 } while (found != TRUE && gtk_tree_model_iter_next (model, &iter));
258 g_signal_handler_block (selector, priv->signal_id);
260 /* We emit the HildonTouchSelector::changed signal because a change in the
261 GtkEntry represents a change in current selection, and therefore, users
262 should be notified. */
264 hildon_touch_selector_select_iter (selector, 0, &iter, TRUE);
266 g_signal_emit_by_name (selector, "changed", 0);
268 g_signal_handler_unblock (selector, priv->signal_id);
272 /* FIXME: This is actually a very ugly way to retrieve the text. Ideally,
273 we would have API to retrieve it from the base clase (HildonTouchSelector).
274 In the meantime, leaving it here.
277 hildon_touch_selector_get_text_from_model (HildonTouchSelectorEntry * selector)
279 HildonTouchSelectorEntryPrivate *priv;
283 GList *selected_rows;
286 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
288 model = hildon_touch_selector_get_model (HILDON_TOUCH_SELECTOR (selector), 0);
289 selected_rows = hildon_touch_selector_get_selected_rows (HILDON_TOUCH_SELECTOR (selector), 0);
291 if (selected_rows == NULL) {
295 /* We are in single selection mode */
296 g_assert (selected_rows->next == NULL);
298 path = (GtkTreePath *)selected_rows->data;
299 gtk_tree_model_get_iter (model, &iter, path);
300 gtk_tree_model_get (model, &iter, priv->text_column, &text, -1);
302 gtk_tree_path_free (path);
303 g_list_free (selected_rows);
309 hildon_touch_selector_entry_changed (HildonTouchSelector * selector,
310 gint column, gpointer user_data)
312 HildonTouchSelectorEntryPrivate *priv;
315 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
317 text = hildon_touch_selector_get_text_from_model (HILDON_TOUCH_SELECTOR_ENTRY (selector));
318 gtk_entry_set_text (GTK_ENTRY (priv->entry), text);
319 gtk_editable_select_region (GTK_EDITABLE (priv->entry), 0, -1);
324 hildon_touch_selector_entry_set_model (HildonTouchSelector * selector,
325 gint column, GtkTreeModel *model)
327 GtkEntryCompletion *completion;
328 HildonTouchSelectorEntryPrivate *priv;
330 g_return_if_fail (HILDON_IS_TOUCH_SELECTOR_ENTRY (selector));
331 g_return_if_fail (column == 0);
332 g_return_if_fail (GTK_IS_TREE_MODEL (model));
334 HILDON_TOUCH_SELECTOR_CLASS (hildon_touch_selector_entry_parent_class)->set_model (selector, column, model);
336 priv = HILDON_TOUCH_SELECTOR_ENTRY_GET_PRIVATE (selector);
338 completion = gtk_entry_get_completion (GTK_ENTRY (priv->entry));
339 gtk_entry_completion_set_model (completion, model);
340 gtk_entry_completion_set_text_column (completion, priv->text_column);
344 hildon_touch_selector_entry_has_multiple_selection (HildonTouchSelector * selector)
346 /* Always TRUE, given the GtkEntry. */