]> Pileus Git - ~andy/gtk/blob - demos/gtk-demo/search_entry.c
Silence compiler warnings
[~andy/gtk] / demos / gtk-demo / search_entry.c
1 /* Entry/Search Entry
2  *
3  * GtkEntry allows to display icons and progress information.
4  * This demo shows how to use these features in a search entry.
5  */
6
7 #include <gtk/gtk.h>
8
9 static GtkWidget *window = NULL;
10 static GtkWidget *menu = NULL;
11 static GtkWidget *notebook = NULL;
12
13 static guint search_progress_id = 0;
14 static guint finish_search_id = 0;
15
16 static void
17 show_find_button (void)
18 {
19   gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
20 }
21
22 static void
23 show_cancel_button (void)
24 {
25   gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 1);
26 }
27
28 static gboolean
29 search_progress (gpointer data)
30 {
31   gtk_entry_progress_pulse (GTK_ENTRY (data));
32   return G_SOURCE_CONTINUE;
33 }
34
35 static void
36 search_progress_done (GtkEntry *entry)
37 {
38   gtk_entry_set_progress_fraction (entry, 0.0);
39 }
40
41 static gboolean
42 finish_search (GtkButton *button)
43 {
44   show_find_button ();
45   g_source_remove (search_progress_id);
46   search_progress_id = 0;
47
48   return FALSE;
49 }
50
51 static gboolean
52 start_search_feedback (gpointer data)
53 {
54   search_progress_id = g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
55                                            (GSourceFunc)search_progress, data,
56                                            (GDestroyNotify)search_progress_done);
57   return FALSE;
58 }
59
60 static void
61 start_search (GtkButton *button,
62               GtkEntry  *entry)
63 {
64   show_cancel_button ();
65   search_progress_id = g_timeout_add_seconds (1, (GSourceFunc)start_search_feedback, entry);
66   finish_search_id = g_timeout_add_seconds (15, (GSourceFunc)finish_search, button);
67 }
68
69
70 static void
71 stop_search (GtkButton *button,
72              gpointer   data)
73 {
74   g_source_remove (finish_search_id);
75   finish_search (button);
76 }
77
78 static void
79 clear_entry (GtkEntry *entry)
80 {
81   gtk_entry_set_text (entry, "");
82 }
83
84 static void
85 search_by_name (GtkWidget *item,
86                 GtkEntry  *entry)
87 {
88   gtk_entry_set_icon_from_stock (entry,
89                                  GTK_ENTRY_ICON_PRIMARY,
90                                  GTK_STOCK_FIND);
91   gtk_entry_set_icon_tooltip_text (entry,
92                                    GTK_ENTRY_ICON_PRIMARY,
93                                    "Search by name\n"
94                                    "Click here to change the search type");
95   gtk_entry_set_placeholder_text (entry, "name");
96 }
97
98 static void
99 search_by_description (GtkWidget *item,
100                        GtkEntry  *entry)
101 {
102   gtk_entry_set_icon_from_stock (entry,
103                                  GTK_ENTRY_ICON_PRIMARY,
104                                  GTK_STOCK_EDIT);
105   gtk_entry_set_icon_tooltip_text (entry,
106                                    GTK_ENTRY_ICON_PRIMARY,
107                                    "Search by description\n"
108                                    "Click here to change the search type");
109   gtk_entry_set_placeholder_text (entry, "description");
110 }
111
112 static void
113 search_by_file (GtkWidget *item,
114                 GtkEntry  *entry)
115 {
116   gtk_entry_set_icon_from_stock (entry,
117                                  GTK_ENTRY_ICON_PRIMARY,
118                                  GTK_STOCK_OPEN);
119   gtk_entry_set_icon_tooltip_text (entry,
120                                    GTK_ENTRY_ICON_PRIMARY,
121                                    "Search by file name\n"
122                                    "Click here to change the search type");
123   gtk_entry_set_placeholder_text (entry, "file name");
124 }
125
126 GtkWidget *
127 create_search_menu (GtkWidget *entry)
128 {
129   GtkWidget *menu;
130   GtkWidget *item;
131   GtkWidget *image;
132
133   menu = gtk_menu_new ();
134
135   item = gtk_image_menu_item_new_with_mnemonic ("Search by _name");
136   image = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
137   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
138   gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
139   g_signal_connect (item, "activate",
140                     G_CALLBACK (search_by_name), entry);
141   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
142
143   item = gtk_image_menu_item_new_with_mnemonic ("Search by _description");
144   image = gtk_image_new_from_stock (GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU);
145   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
146   gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
147   g_signal_connect (item, "activate",
148                     G_CALLBACK (search_by_description), entry);
149   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
150
151   item = gtk_image_menu_item_new_with_mnemonic ("Search by _file name");
152   image = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
153   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
154   gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
155   g_signal_connect (item, "activate",
156                     G_CALLBACK (search_by_file), entry);
157   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
158
159   gtk_widget_show_all (menu);
160
161   return menu;
162 }
163
164 static void
165 icon_press_cb (GtkEntry       *entry,
166                gint            position,
167                GdkEventButton *event,
168                gpointer        data)
169 {
170   if (position == GTK_ENTRY_ICON_PRIMARY)
171     gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
172                     event->button, event->time);
173   else
174     clear_entry (entry);
175 }
176
177 static void
178 text_changed_cb (GtkEntry   *entry,
179                  GParamSpec *pspec,
180                  GtkWidget  *button)
181 {
182   gboolean has_text;
183
184   has_text = gtk_entry_get_text_length (entry) > 0;
185   gtk_entry_set_icon_sensitive (entry,
186                                 GTK_ENTRY_ICON_SECONDARY,
187                                 has_text);
188   gtk_widget_set_sensitive (button, has_text);
189 }
190
191 static void
192 activate_cb (GtkEntry  *entry,
193              GtkButton *button)
194 {
195   if (search_progress_id != 0)
196     return;
197
198   start_search (button, entry);
199
200 }
201
202 static void
203 search_entry_destroyed (GtkWidget  *widget)
204 {
205   if (finish_search_id != 0)
206     g_source_remove (finish_search_id);
207
208   if (search_progress_id != 0)
209     g_source_remove (search_progress_id);
210
211   window = NULL;
212 }
213
214 static void
215 entry_populate_popup (GtkEntry *entry,
216                       GtkMenu  *menu,
217                       gpointer user_data)
218 {
219   GtkWidget *item;
220   GtkWidget *search_menu;
221   gboolean has_text;
222
223   has_text = gtk_entry_get_text_length (entry) > 0;
224
225   item = gtk_separator_menu_item_new ();
226   gtk_widget_show (item);
227   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
228
229   item = gtk_menu_item_new_with_mnemonic ("C_lear");
230   gtk_widget_show (item);
231   g_signal_connect_swapped (item, "activate",
232                             G_CALLBACK (clear_entry), entry);
233   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
234   gtk_widget_set_sensitive (item, has_text);
235
236   search_menu = create_search_menu (GTK_WIDGET (entry));
237   item = gtk_menu_item_new_with_label ("Search by");
238   gtk_widget_show (item);
239   gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), search_menu);
240   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
241 }
242
243 GtkWidget *
244 do_search_entry (GtkWidget *do_widget)
245 {
246   GtkWidget *content_area;
247   GtkWidget *vbox;
248   GtkWidget *hbox;
249   GtkWidget *label;
250   GtkWidget *entry;
251   GtkWidget *button;
252   GtkWidget *find_button;
253   GtkWidget *cancel_button;
254
255   if (!window)
256     {
257       window = gtk_dialog_new_with_buttons ("Search Entry",
258                                             GTK_WINDOW (do_widget),
259                                             0,
260                                             GTK_STOCK_CLOSE,
261                                             GTK_RESPONSE_NONE,
262                                             NULL);
263       gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
264
265       g_signal_connect (window, "response",
266                         G_CALLBACK (gtk_widget_destroy), NULL);
267       g_signal_connect (window, "destroy",
268                         G_CALLBACK (search_entry_destroyed), &window);
269
270       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
271
272       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
273       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
274       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
275
276       label = gtk_label_new (NULL);
277       gtk_label_set_markup (GTK_LABEL (label), "Search entry demo");
278       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
279
280       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
281       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
282       gtk_container_set_border_width (GTK_CONTAINER (hbox), 0);
283
284       /* Create our entry */
285       entry = gtk_entry_new ();
286       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
287
288       /* Create the find and cancel buttons */
289       notebook = gtk_notebook_new ();
290       gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
291       gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
292       gtk_box_pack_start (GTK_BOX (hbox), notebook, FALSE, FALSE, 0);
293
294       find_button = gtk_button_new_with_label ("Find");
295       g_signal_connect (find_button, "clicked",
296                         G_CALLBACK (start_search), entry);
297       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), find_button, NULL);
298       gtk_widget_show (find_button);
299
300       cancel_button = gtk_button_new_with_label ("Cancel");
301       g_signal_connect (cancel_button, "clicked",
302                         G_CALLBACK (stop_search), NULL);
303       gtk_notebook_append_page (GTK_NOTEBOOK (notebook), cancel_button, NULL);
304       gtk_widget_show (cancel_button);
305
306       /* Set up the search icon */
307       search_by_name (NULL, GTK_ENTRY (entry));
308
309       /* Set up the clear icon */
310       gtk_entry_set_icon_from_stock (GTK_ENTRY (entry),
311                                      GTK_ENTRY_ICON_SECONDARY,
312                                      GTK_STOCK_CLEAR);
313       text_changed_cb (GTK_ENTRY (entry), NULL, find_button);
314
315       g_signal_connect (entry, "icon-press",
316                         G_CALLBACK (icon_press_cb), NULL);
317       g_signal_connect (entry, "notify::text",
318                         G_CALLBACK (text_changed_cb), find_button);
319       g_signal_connect (entry, "activate",
320                         G_CALLBACK (activate_cb), NULL);
321
322       /* Create the menu */
323       menu = create_search_menu (entry);
324       gtk_menu_attach_to_widget (GTK_MENU (menu), entry, NULL);
325
326       /* add accessible alternatives for icon functionality */
327       g_signal_connect (entry, "populate-popup",
328                         G_CALLBACK (entry_populate_popup), NULL);
329
330       /* Give the focus to the close button */
331       button = gtk_dialog_get_widget_for_response (GTK_DIALOG (window), GTK_RESPONSE_NONE);
332       gtk_widget_grab_focus (button);
333     }
334
335   if (!gtk_widget_get_visible (window))
336     gtk_widget_show_all (window);
337   else
338     {
339       gtk_widget_destroy (menu);
340       gtk_widget_destroy (window);
341       window = NULL;
342     }
343
344   return window;
345 }