1 | /* testentrycompletion.c |
2 | * Copyright (C) 2004 Red Hat, Inc. |
3 | * Author: Matthias Clasen |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Library General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public |
16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
17 | */ |
18 | |
19 | #include "config.h" |
20 | #include <stdlib.h> |
21 | #include <string.h> |
22 | #include <gtk/gtk.h> |
23 | |
24 | /* Don't copy this bad example; inline RGB data is always a better |
25 | * idea than inline XPMs. |
26 | */ |
27 | static const char *book_closed_xpm[] = { |
28 | "16 16 6 1" , |
29 | " c None s None" , |
30 | ". c black" , |
31 | "X c red" , |
32 | "o c yellow" , |
33 | "O c #808080" , |
34 | "# c white" , |
35 | " " , |
36 | " .. " , |
37 | " ..XX. " , |
38 | " ..XXXXX. " , |
39 | " ..XXXXXXXX. " , |
40 | ".ooXXXXXXXXX. " , |
41 | "..ooXXXXXXXXX. " , |
42 | ".X.ooXXXXXXXXX. " , |
43 | ".XX.ooXXXXXX.. " , |
44 | " .XX.ooXXX..#O " , |
45 | " .XX.oo..##OO. " , |
46 | " .XX..##OO.. " , |
47 | " .X.#OO.. " , |
48 | " ..O.. " , |
49 | " .. " , |
50 | " " |
51 | }; |
52 | |
53 | static GtkWidget *window = NULL; |
54 | |
55 | |
56 | /* Creates a tree model containing the completions */ |
57 | static GtkTreeModel * |
58 | create_simple_completion_model (void) |
59 | { |
60 | GtkListStore *store; |
61 | GtkTreeIter iter; |
62 | |
63 | store = gtk_list_store_new (n_columns: 1, G_TYPE_STRING); |
64 | |
65 | gtk_list_store_append (list_store: store, iter: &iter); |
66 | gtk_list_store_set (list_store: store, iter: &iter, 0, "GNOME" , -1); |
67 | gtk_list_store_append (list_store: store, iter: &iter); |
68 | gtk_list_store_set (list_store: store, iter: &iter, 0, "gnominious" , -1); |
69 | gtk_list_store_append (list_store: store, iter: &iter); |
70 | gtk_list_store_set (list_store: store, iter: &iter, 0, "Gnomonic projection" , -1); |
71 | |
72 | gtk_list_store_append (list_store: store, iter: &iter); |
73 | gtk_list_store_set (list_store: store, iter: &iter, 0, "total" , -1); |
74 | gtk_list_store_append (list_store: store, iter: &iter); |
75 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totally" , -1); |
76 | gtk_list_store_append (list_store: store, iter: &iter); |
77 | gtk_list_store_set (list_store: store, iter: &iter, 0, "toto" , -1); |
78 | gtk_list_store_append (list_store: store, iter: &iter); |
79 | gtk_list_store_set (list_store: store, iter: &iter, 0, "tottery" , -1); |
80 | gtk_list_store_append (list_store: store, iter: &iter); |
81 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totterer" , -1); |
82 | gtk_list_store_append (list_store: store, iter: &iter); |
83 | gtk_list_store_set (list_store: store, iter: &iter, 0, "Totten trust" , -1); |
84 | gtk_list_store_append (list_store: store, iter: &iter); |
85 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totipotent" , -1); |
86 | gtk_list_store_append (list_store: store, iter: &iter); |
87 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totipotency" , -1); |
88 | gtk_list_store_append (list_store: store, iter: &iter); |
89 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totemism" , -1); |
90 | gtk_list_store_append (list_store: store, iter: &iter); |
91 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totem pole" , -1); |
92 | gtk_list_store_append (list_store: store, iter: &iter); |
93 | gtk_list_store_set (list_store: store, iter: &iter, 0, "Totara" , -1); |
94 | gtk_list_store_append (list_store: store, iter: &iter); |
95 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totalizer" , -1); |
96 | gtk_list_store_append (list_store: store, iter: &iter); |
97 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totalizator" , -1); |
98 | gtk_list_store_append (list_store: store, iter: &iter); |
99 | gtk_list_store_set (list_store: store, iter: &iter, 0, "totalitarianism" , -1); |
100 | gtk_list_store_append (list_store: store, iter: &iter); |
101 | gtk_list_store_set (list_store: store, iter: &iter, 0, "total parenteral nutrition" , -1); |
102 | gtk_list_store_append (list_store: store, iter: &iter); |
103 | gtk_list_store_set (list_store: store, iter: &iter, 0, "total hysterectomy" , -1); |
104 | gtk_list_store_append (list_store: store, iter: &iter); |
105 | gtk_list_store_set (list_store: store, iter: &iter, 0, "total eclipse" , -1); |
106 | gtk_list_store_append (list_store: store, iter: &iter); |
107 | gtk_list_store_set (list_store: store, iter: &iter, 0, "Totipresence" , -1); |
108 | gtk_list_store_append (list_store: store, iter: &iter); |
109 | gtk_list_store_set (list_store: store, iter: &iter, 0, "Totipalmi" , -1); |
110 | gtk_list_store_append (list_store: store, iter: &iter); |
111 | gtk_list_store_set (list_store: store, iter: &iter, 0, "zombie" , -1); |
112 | gtk_list_store_append (list_store: store, iter: &iter); |
113 | gtk_list_store_set (list_store: store, iter: &iter, 0, "a\303\246x" , -1); |
114 | gtk_list_store_append (list_store: store, iter: &iter); |
115 | gtk_list_store_set (list_store: store, iter: &iter, 0, "a\303\246y" , -1); |
116 | gtk_list_store_append (list_store: store, iter: &iter); |
117 | gtk_list_store_set (list_store: store, iter: &iter, 0, "a\303\246z" , -1); |
118 | |
119 | return GTK_TREE_MODEL (store); |
120 | } |
121 | |
122 | /* Creates a tree model containing the completions */ |
123 | static GtkTreeModel * |
124 | create_completion_model (void) |
125 | { |
126 | GtkListStore *store; |
127 | GtkTreeIter iter; |
128 | GdkPixbuf *pixbuf; |
129 | |
130 | pixbuf = gdk_pixbuf_new_from_xpm_data (data: (const char **)book_closed_xpm); |
131 | |
132 | store = gtk_list_store_new (n_columns: 2, GDK_TYPE_PIXBUF, G_TYPE_STRING); |
133 | |
134 | gtk_list_store_append (list_store: store, iter: &iter); |
135 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "ambient" , -1); |
136 | gtk_list_store_append (list_store: store, iter: &iter); |
137 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "ambidextrously" , -1); |
138 | gtk_list_store_append (list_store: store, iter: &iter); |
139 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "ambidexter" , -1); |
140 | gtk_list_store_append (list_store: store, iter: &iter); |
141 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "ambiguity" , -1); |
142 | gtk_list_store_append (list_store: store, iter: &iter); |
143 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "American Party" , -1); |
144 | gtk_list_store_append (list_store: store, iter: &iter); |
145 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "American mountain ash" , -1); |
146 | gtk_list_store_append (list_store: store, iter: &iter); |
147 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "amelioration" , -1); |
148 | gtk_list_store_append (list_store: store, iter: &iter); |
149 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "Amelia Earhart" , -1); |
150 | gtk_list_store_append (list_store: store, iter: &iter); |
151 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "Totten trust" , -1); |
152 | gtk_list_store_append (list_store: store, iter: &iter); |
153 | gtk_list_store_set (list_store: store, iter: &iter, 0, pixbuf, 1, "Laminated arch" , -1); |
154 | |
155 | return GTK_TREE_MODEL (store); |
156 | } |
157 | |
158 | static gboolean |
159 | match_func (GtkEntryCompletion *completion, |
160 | const char *key, |
161 | GtkTreeIter *iter, |
162 | gpointer user_data) |
163 | { |
164 | char *item = NULL; |
165 | GtkTreeModel *model; |
166 | |
167 | gboolean ret = FALSE; |
168 | |
169 | model = gtk_entry_completion_get_model (completion); |
170 | |
171 | gtk_tree_model_get (tree_model: model, iter, 1, &item, -1); |
172 | |
173 | if (item != NULL) |
174 | { |
175 | g_print (format: "compare %s %s\n" , key, item); |
176 | if (strncmp (s1: key, s2: item, n: strlen (s: key)) == 0) |
177 | ret = TRUE; |
178 | |
179 | g_free (mem: item); |
180 | } |
181 | |
182 | return ret; |
183 | } |
184 | |
185 | static int timer_count = 0; |
186 | |
187 | static const char *dynamic_completions[] = { |
188 | "GNOME" , |
189 | "gnominious" , |
190 | "Gnomonic projection" , |
191 | "total" , |
192 | "totally" , |
193 | "toto" , |
194 | "tottery" , |
195 | "totterer" , |
196 | "Totten trust" , |
197 | "totipotent" , |
198 | "totipotency" , |
199 | "totemism" , |
200 | "totem pole" , |
201 | "Totara" , |
202 | "totalizer" , |
203 | "totalizator" , |
204 | "totalitarianism" , |
205 | "total parenteral nutrition" , |
206 | "total hysterectomy" , |
207 | "total eclipse" , |
208 | "Totipresence" , |
209 | "Totipalmi" , |
210 | "zombie" |
211 | }; |
212 | |
213 | static int |
214 | animation_timer (GtkEntryCompletion *completion) |
215 | { |
216 | GtkTreeIter iter; |
217 | int n_completions = G_N_ELEMENTS (dynamic_completions); |
218 | int n; |
219 | static GtkListStore *old_store = NULL; |
220 | GtkListStore *store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion)); |
221 | |
222 | if (timer_count % 10 == 0) |
223 | { |
224 | if (!old_store) |
225 | { |
226 | g_print (format: "removing model!\n" ); |
227 | |
228 | old_store = g_object_ref (store); |
229 | gtk_entry_completion_set_model (completion, NULL); |
230 | } |
231 | else |
232 | { |
233 | g_print (format: "readding model!\n" ); |
234 | |
235 | gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (old_store)); |
236 | g_object_unref (object: old_store); |
237 | old_store = NULL; |
238 | } |
239 | |
240 | timer_count ++; |
241 | return TRUE; |
242 | } |
243 | |
244 | if (!old_store) |
245 | { |
246 | if ((timer_count / n_completions) % 2 == 0) |
247 | { |
248 | n = timer_count % n_completions; |
249 | gtk_list_store_append (list_store: store, iter: &iter); |
250 | gtk_list_store_set (list_store: store, iter: &iter, 0, dynamic_completions[n], -1); |
251 | |
252 | } |
253 | else |
254 | { |
255 | if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), iter: &iter)) |
256 | gtk_list_store_remove (list_store: store, iter: &iter); |
257 | } |
258 | } |
259 | |
260 | timer_count++; |
261 | return TRUE; |
262 | } |
263 | |
264 | static gboolean |
265 | match_selected_cb (GtkEntryCompletion *completion, |
266 | GtkTreeModel *model, |
267 | GtkTreeIter *iter) |
268 | { |
269 | char *str; |
270 | GtkWidget *entry; |
271 | |
272 | entry = gtk_entry_completion_get_entry (completion); |
273 | gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 1, &str, -1); |
274 | gtk_editable_set_text (GTK_EDITABLE (entry), text: str); |
275 | gtk_editable_set_position (GTK_EDITABLE (entry), position: -1); |
276 | g_free (mem: str); |
277 | |
278 | return TRUE; |
279 | } |
280 | |
281 | static void |
282 | quit_cb (GtkWidget *widget, |
283 | gpointer data) |
284 | { |
285 | gboolean *done = data; |
286 | |
287 | *done = TRUE; |
288 | |
289 | g_main_context_wakeup (NULL); |
290 | } |
291 | |
292 | int |
293 | main (int argc, char *argv[]) |
294 | { |
295 | GtkWidget *vbox; |
296 | GtkWidget *label; |
297 | GtkWidget *entry; |
298 | GtkEntryCompletion *completion; |
299 | GtkTreeModel *completion_model; |
300 | GtkCellRenderer *cell; |
301 | gboolean done = FALSE; |
302 | |
303 | gtk_init (); |
304 | |
305 | window = gtk_window_new (); |
306 | g_signal_connect (window, "destroy" , G_CALLBACK (quit_cb), &done); |
307 | |
308 | vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 2); |
309 | gtk_widget_set_margin_start (widget: vbox, margin: 5); |
310 | gtk_widget_set_margin_end (widget: vbox, margin: 5); |
311 | gtk_widget_set_margin_top (widget: vbox, margin: 5); |
312 | gtk_widget_set_margin_bottom (widget: vbox, margin: 5); |
313 | gtk_window_set_child (GTK_WINDOW (window), child: vbox); |
314 | |
315 | label = gtk_label_new (NULL); |
316 | |
317 | gtk_label_set_markup (GTK_LABEL (label), str: "Completion demo, try writing <b>total</b> or <b>gnome</b> for example." ); |
318 | gtk_box_append (GTK_BOX (vbox), child: label); |
319 | |
320 | /* Create our first entry */ |
321 | entry = gtk_entry_new (); |
322 | |
323 | /* Create the completion object */ |
324 | completion = gtk_entry_completion_new (); |
325 | gtk_entry_completion_set_inline_completion (completion, TRUE); |
326 | |
327 | /* Assign the completion to the entry */ |
328 | gtk_entry_set_completion (GTK_ENTRY (entry), completion); |
329 | g_object_unref (object: completion); |
330 | |
331 | gtk_box_append (GTK_BOX (vbox), child: entry); |
332 | |
333 | /* Create a tree model and use it as the completion model */ |
334 | completion_model = create_simple_completion_model (); |
335 | gtk_entry_completion_set_model (completion, model: completion_model); |
336 | g_object_unref (object: completion_model); |
337 | |
338 | /* Use model column 0 as the text column */ |
339 | gtk_entry_completion_set_text_column (completion, column: 0); |
340 | |
341 | /* Create our second entry */ |
342 | entry = gtk_entry_new (); |
343 | |
344 | /* Create the completion object */ |
345 | completion = gtk_entry_completion_new (); |
346 | |
347 | /* Assign the completion to the entry */ |
348 | gtk_entry_set_completion (GTK_ENTRY (entry), completion); |
349 | g_object_unref (object: completion); |
350 | |
351 | gtk_box_append (GTK_BOX (vbox), child: entry); |
352 | |
353 | /* Create a tree model and use it as the completion model */ |
354 | completion_model = create_completion_model (); |
355 | gtk_entry_completion_set_model (completion, model: completion_model); |
356 | gtk_entry_completion_set_minimum_key_length (completion, length: 2); |
357 | g_object_unref (object: completion_model); |
358 | |
359 | /* Use model column 1 as the text column */ |
360 | cell = gtk_cell_renderer_pixbuf_new (); |
361 | gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE); |
362 | gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, |
363 | "pixbuf" , 0, NULL); |
364 | |
365 | cell = gtk_cell_renderer_text_new (); |
366 | gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE); |
367 | gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, |
368 | "text" , 1, NULL); |
369 | |
370 | gtk_entry_completion_set_match_func (completion, func: match_func, NULL, NULL); |
371 | g_signal_connect (completion, "match-selected" , |
372 | G_CALLBACK (match_selected_cb), NULL); |
373 | |
374 | /* Create our third entry */ |
375 | entry = gtk_entry_new (); |
376 | |
377 | /* Create the completion object */ |
378 | completion = gtk_entry_completion_new (); |
379 | |
380 | /* Assign the completion to the entry */ |
381 | gtk_entry_set_completion (GTK_ENTRY (entry), completion); |
382 | g_object_unref (object: completion); |
383 | |
384 | gtk_box_append (GTK_BOX (vbox), child: entry); |
385 | |
386 | /* Create a tree model and use it as the completion model */ |
387 | completion_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING)); |
388 | |
389 | gtk_entry_completion_set_model (completion, model: completion_model); |
390 | g_object_unref (object: completion_model); |
391 | |
392 | /* Use model column 0 as the text column */ |
393 | gtk_entry_completion_set_text_column (completion, column: 0); |
394 | |
395 | /* Fill the completion dynamically */ |
396 | g_timeout_add (interval: 1000, function: (GSourceFunc) animation_timer, data: completion); |
397 | |
398 | /* Fourth entry */ |
399 | gtk_box_append (GTK_BOX (vbox), child: gtk_label_new (str: "Model-less entry completion" )); |
400 | |
401 | entry = gtk_entry_new (); |
402 | |
403 | /* Create the completion object */ |
404 | completion = gtk_entry_completion_new (); |
405 | |
406 | /* Assign the completion to the entry */ |
407 | gtk_entry_set_completion (GTK_ENTRY (entry), completion); |
408 | g_object_unref (object: completion); |
409 | |
410 | gtk_box_append (GTK_BOX (vbox), child: entry); |
411 | |
412 | gtk_widget_show (widget: window); |
413 | |
414 | while (!done) |
415 | g_main_context_iteration (NULL, TRUE); |
416 | |
417 | return 0; |
418 | } |
419 | |
420 | |
421 | |