]> Pileus Git - ~andy/gtk/blob - tests/testentrycompletion.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / tests / testentrycompletion.c
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 #include "prop-editor.h"
25
26 /* Don't copy this bad example; inline RGB data is always a better
27  * idea than inline XPMs.
28  */
29 static char  *book_closed_xpm[] = {
30 "16 16 6 1",
31 "       c None s None",
32 ".      c black",
33 "X      c red",
34 "o      c yellow",
35 "O      c #808080",
36 "#      c white",
37 "                ",
38 "       ..       ",
39 "     ..XX.      ",
40 "   ..XXXXX.     ",
41 " ..XXXXXXXX.    ",
42 ".ooXXXXXXXXX.   ",
43 "..ooXXXXXXXXX.  ",
44 ".X.ooXXXXXXXXX. ",
45 ".XX.ooXXXXXX..  ",
46 " .XX.ooXXX..#O  ",
47 "  .XX.oo..##OO. ",
48 "   .XX..##OO..  ",
49 "    .X.#OO..    ",
50 "     ..O..      ",
51 "      ..        ",
52 "                "
53 };
54
55 static GtkWidget *window = NULL;
56
57
58 /* Creates a tree model containing the completions */
59 GtkTreeModel *
60 create_simple_completion_model (void)
61 {
62   GtkListStore *store;
63   GtkTreeIter iter;
64   
65   store = gtk_list_store_new (1, G_TYPE_STRING);
66
67   gtk_list_store_append (store, &iter);
68   gtk_list_store_set (store, &iter, 0, "GNOME", -1);
69   gtk_list_store_append (store, &iter);
70   gtk_list_store_set (store, &iter, 0, "gnominious", -1);
71   gtk_list_store_append (store, &iter);
72   gtk_list_store_set (store, &iter, 0, "Gnomonic projection", -1);
73
74   gtk_list_store_append (store, &iter);
75   gtk_list_store_set (store, &iter, 0, "total", -1);
76   gtk_list_store_append (store, &iter);
77   gtk_list_store_set (store, &iter, 0, "totally", -1);
78   gtk_list_store_append (store, &iter);
79   gtk_list_store_set (store, &iter, 0, "toto", -1);
80   gtk_list_store_append (store, &iter);
81   gtk_list_store_set (store, &iter, 0, "tottery", -1);
82   gtk_list_store_append (store, &iter);
83   gtk_list_store_set (store, &iter, 0, "totterer", -1);
84   gtk_list_store_append (store, &iter);
85   gtk_list_store_set (store, &iter, 0, "Totten trust", -1);
86   gtk_list_store_append (store, &iter);
87   gtk_list_store_set (store, &iter, 0, "totipotent", -1);
88   gtk_list_store_append (store, &iter);
89   gtk_list_store_set (store, &iter, 0, "totipotency", -1);
90   gtk_list_store_append (store, &iter);
91   gtk_list_store_set (store, &iter, 0, "totemism", -1);
92   gtk_list_store_append (store, &iter);
93   gtk_list_store_set (store, &iter, 0, "totem pole", -1);
94   gtk_list_store_append (store, &iter);
95   gtk_list_store_set (store, &iter, 0, "Totara", -1);
96   gtk_list_store_append (store, &iter);
97   gtk_list_store_set (store, &iter, 0, "totalizer", -1);
98   gtk_list_store_append (store, &iter);
99   gtk_list_store_set (store, &iter, 0, "totalizator", -1);
100   gtk_list_store_append (store, &iter);
101   gtk_list_store_set (store, &iter, 0, "totalitarianism", -1);
102   gtk_list_store_append (store, &iter);
103   gtk_list_store_set (store, &iter, 0, "total parenteral nutrition", -1);
104   gtk_list_store_append (store, &iter);
105   gtk_list_store_set (store, &iter, 0, "total hysterectomy", -1);
106   gtk_list_store_append (store, &iter);
107   gtk_list_store_set (store, &iter, 0, "total eclipse", -1);
108   gtk_list_store_append (store, &iter);
109   gtk_list_store_set (store, &iter, 0, "Totipresence", -1);
110   gtk_list_store_append (store, &iter);
111   gtk_list_store_set (store, &iter, 0, "Totipalmi", -1);
112   gtk_list_store_append (store, &iter);
113   gtk_list_store_set (store, &iter, 0, "zombie", -1);
114   gtk_list_store_append (store, &iter);
115   gtk_list_store_set (store, &iter, 0, "a\303\246x", -1);
116   gtk_list_store_append (store, &iter);
117   gtk_list_store_set (store, &iter, 0, "a\303\246y", -1);
118   gtk_list_store_append (store, &iter);
119   gtk_list_store_set (store, &iter, 0, "a\303\246z", -1);
120  
121   return GTK_TREE_MODEL (store);
122 }
123
124 /* Creates a tree model containing the completions */
125 GtkTreeModel *
126 create_completion_model (void)
127 {
128   GtkListStore *store;
129   GtkTreeIter iter;
130   GdkPixbuf *pixbuf;
131
132   pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
133
134   store = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
135
136   gtk_list_store_append (store, &iter);
137   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambient", -1);
138   gtk_list_store_append (store, &iter);
139   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidextrously", -1);
140   gtk_list_store_append (store, &iter);
141   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambidexter", -1);
142   gtk_list_store_append (store, &iter);
143   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "ambiguity", -1);
144   gtk_list_store_append (store, &iter);
145   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American Party", -1);
146   gtk_list_store_append (store, &iter);
147   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "American mountain ash", -1);
148   gtk_list_store_append (store, &iter);
149   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "amelioration", -1);
150   gtk_list_store_append (store, &iter);
151   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Amelia Earhart", -1);
152   gtk_list_store_append (store, &iter);
153   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Totten trust", -1);
154   gtk_list_store_append (store, &iter);
155   gtk_list_store_set (store, &iter, 0, pixbuf, 1, "Laminated arch", -1);
156  
157   return GTK_TREE_MODEL (store);
158 }
159
160 static gboolean
161 match_func (GtkEntryCompletion *completion,
162             const gchar        *key,
163             GtkTreeIter        *iter,
164             gpointer            user_data)
165 {
166   gchar *item = NULL;
167   GtkTreeModel *model;
168
169   gboolean ret = FALSE;
170
171   model = gtk_entry_completion_get_model (completion);
172
173   gtk_tree_model_get (model, iter, 1, &item, -1);
174
175   if (item != NULL)
176     {
177       g_print ("compare %s %s\n", key, item);
178       if (strncmp (key, item, strlen (key)) == 0)
179         ret = TRUE;
180
181       g_free (item);
182     }
183
184   return ret;
185 }
186
187 static void
188 activated_cb (GtkEntryCompletion *completion, 
189               gint                index,
190               gpointer            user_data)
191 {
192   g_print ("action activated: %d\n", index);
193 }
194
195 static gint timer_count = 0;
196
197 static gchar *dynamic_completions[] = {
198   "GNOME",
199   "gnominious",
200   "Gnomonic projection",
201   "total",
202   "totally",
203   "toto",
204   "tottery",
205   "totterer",
206   "Totten trust",
207   "totipotent",
208   "totipotency",
209   "totemism",
210   "totem pole",
211   "Totara",
212   "totalizer",
213   "totalizator",
214   "totalitarianism",
215   "total parenteral nutrition",
216   "total hysterectomy",
217   "total eclipse",
218   "Totipresence",
219   "Totipalmi",
220   "zombie"
221 };
222
223 static gint
224 animation_timer (GtkEntryCompletion *completion)
225 {
226   GtkTreeIter iter;
227   gint n_completions = G_N_ELEMENTS (dynamic_completions);
228   gint n;
229   static GtkListStore *old_store = NULL;
230   GtkListStore *store = GTK_LIST_STORE (gtk_entry_completion_get_model (completion));
231
232   if (timer_count % 10 == 0)
233     {
234       if (!old_store)
235         {
236           g_print ("removing model!\n");
237
238           old_store = g_object_ref (gtk_entry_completion_get_model (completion));
239           gtk_entry_completion_set_model (completion, NULL);
240         }
241       else
242         {
243           g_print ("readding model!\n");
244           
245           gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (old_store));
246           g_object_unref (old_store);
247           old_store = NULL;
248         }
249
250       timer_count ++;
251       return TRUE;
252     }
253
254   if (!old_store)
255     {
256       if ((timer_count / n_completions) % 2 == 0)
257         {
258           n = timer_count % n_completions;
259           gtk_list_store_append (store, &iter);
260           gtk_list_store_set (store, &iter, 0, dynamic_completions[n], -1);
261           
262         }
263       else
264         {
265           if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
266             gtk_list_store_remove (store, &iter);
267         }
268     }
269   
270   timer_count++;
271   return TRUE;
272 }
273
274 gboolean 
275 match_selected_cb (GtkEntryCompletion *completion,
276                    GtkTreeModel       *model,
277                    GtkTreeIter        *iter)
278 {
279   gchar *str;
280   GtkWidget *entry;
281
282   entry = gtk_entry_completion_get_entry (completion);
283   gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 1, &str, -1);
284   gtk_entry_set_text (GTK_ENTRY (entry), str);
285   gtk_editable_set_position (GTK_EDITABLE (entry), -1);
286   g_free (str);
287
288   return TRUE;
289 }
290
291 static void
292 new_prop_editor (GObject *object)
293 {
294         gtk_widget_show (create_prop_editor (object, G_OBJECT_TYPE (object)));
295 }
296
297 static void
298 add_with_prop_edit_button (GtkWidget *vbox, GtkWidget *entry, GtkEntryCompletion *completion)
299 {
300         GtkWidget *hbox, *button;
301
302         hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
303         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
304
305         gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
306
307         button = gtk_button_new_with_label ("Properties");
308         g_signal_connect_swapped (button, "clicked", G_CALLBACK (new_prop_editor), completion);
309         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
310 }
311
312 int 
313 main (int argc, char *argv[])
314 {
315   GtkWidget *vbox;
316   GtkWidget *label;
317   GtkWidget *entry;
318   GtkEntryCompletion *completion;
319   GtkTreeModel *completion_model;
320   GtkCellRenderer *cell;
321
322   gtk_init (&argc, &argv);
323
324   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
325   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
326   g_signal_connect (window, "delete_event", gtk_main_quit, NULL);
327   
328   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
329   gtk_container_add (GTK_CONTAINER (window), vbox);
330     
331   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
332   
333   label = gtk_label_new (NULL);
334
335   gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
336   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
337
338   /* Create our first entry */
339   entry = gtk_entry_new ();
340   
341   /* Create the completion object */
342   completion = gtk_entry_completion_new ();
343   gtk_entry_completion_set_inline_completion (completion, TRUE);
344   
345   /* Assign the completion to the entry */
346   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
347   g_object_unref (completion);
348   
349   add_with_prop_edit_button (vbox, entry, completion);
350
351   /* Create a tree model and use it as the completion model */
352   completion_model = create_simple_completion_model ();
353   gtk_entry_completion_set_model (completion, completion_model);
354   g_object_unref (completion_model);
355   
356   /* Use model column 0 as the text column */
357   gtk_entry_completion_set_text_column (completion, 0);
358
359   /* Create our second entry */
360   entry = gtk_entry_new ();
361
362   /* Create the completion object */
363   completion = gtk_entry_completion_new ();
364   
365   /* Assign the completion to the entry */
366   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
367   g_object_unref (completion);
368   
369   add_with_prop_edit_button (vbox, entry, completion);
370
371   /* Create a tree model and use it as the completion model */
372   completion_model = create_completion_model ();
373   gtk_entry_completion_set_model (completion, completion_model);
374   gtk_entry_completion_set_minimum_key_length (completion, 2);
375   g_object_unref (completion_model);
376   
377   /* Use model column 1 as the text column */
378   cell = gtk_cell_renderer_pixbuf_new ();
379   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
380   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, 
381                                   "pixbuf", 0, NULL); 
382
383   cell = gtk_cell_renderer_text_new ();
384   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion), cell, FALSE);
385   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell, 
386                                   "text", 1, NULL); 
387   
388   gtk_entry_completion_set_match_func (completion, match_func, NULL, NULL);
389   g_signal_connect (completion, "match-selected", 
390                     G_CALLBACK (match_selected_cb), NULL);
391
392   gtk_entry_completion_insert_action_text (completion, 100, "action!");
393   gtk_entry_completion_insert_action_text (completion, 101, "'nother action!");
394   g_signal_connect (completion, "action_activated", G_CALLBACK (activated_cb), NULL);
395
396   /* Create our third entry */
397   entry = gtk_entry_new ();
398
399   /* Create the completion object */
400   completion = gtk_entry_completion_new ();
401   
402   /* Assign the completion to the entry */
403   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
404   g_object_unref (completion);
405   
406   add_with_prop_edit_button (vbox, entry, completion);
407
408   /* Create a tree model and use it as the completion model */
409   completion_model = GTK_TREE_MODEL (gtk_list_store_new (1, G_TYPE_STRING));
410
411   gtk_entry_completion_set_model (completion, completion_model);
412   g_object_unref (completion_model);
413
414   /* Use model column 0 as the text column */
415   gtk_entry_completion_set_text_column (completion, 0);
416
417   /* Fill the completion dynamically */
418   gdk_threads_add_timeout (1000, (GSourceFunc) animation_timer, completion);
419
420   /* Fourth entry */
421   gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Model-less entry completion"), FALSE, FALSE, 0);
422
423   entry = gtk_entry_new ();
424
425   /* Create the completion object */
426   completion = gtk_entry_completion_new ();
427   
428   /* Assign the completion to the entry */
429   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
430   g_object_unref (completion);
431   
432   add_with_prop_edit_button (vbox, entry, completion);
433
434   gtk_widget_show_all (window);
435
436   gtk_main ();
437   
438   return 0;
439 }
440
441