]> Pileus Git - ~andy/gtk/blob - tests/testtreeedit.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / tests / testtreeedit.c
1 /* testtreeedit.c
2  * Copyright (C) 2001 Red Hat, Inc
3  * Author: Jonathan Blandford
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 <gtk/gtk.h>
21
22 typedef struct {
23   const gchar *string;
24   gboolean is_editable;
25   gboolean is_sensitive;
26   gint progress;
27 } ListEntry;
28
29 enum {
30   STRING_COLUMN,
31   IS_EDITABLE_COLUMN,
32   IS_SENSITIVE_COLUMN,
33   PIXBUF_COLUMN,
34   LAST_PIXBUF_COLUMN,
35   PROGRESS_COLUMN,
36   NUM_COLUMNS
37 };
38
39 static ListEntry model_strings[] =
40 {
41   {"A simple string", TRUE, TRUE, 0 },
42   {"Another string!", TRUE, TRUE, 10 },
43   {"", TRUE, TRUE, 0 },
44   {"Guess what, a third string. This one can't be edited", FALSE, TRUE, 47 },
45   {"And then a fourth string. Neither can this", FALSE, TRUE, 48 },
46   {"Multiline\nFun!", TRUE, FALSE, 75 },
47   { NULL }
48 };
49
50 static GtkTreeModel *
51 create_model (void)
52 {
53   GtkTreeStore *model;
54   GtkTreeIter iter;
55   gint i;
56   GdkPixbuf *foo, *bar;
57   GtkWidget *blah;
58
59   blah = gtk_window_new (GTK_WINDOW_TOPLEVEL);
60   foo = gtk_widget_render_icon_pixbuf (blah, GTK_STOCK_NEW, GTK_ICON_SIZE_MENU);
61   bar = gtk_widget_render_icon_pixbuf (blah, GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU);
62   gtk_widget_destroy (blah);
63   
64   model = gtk_tree_store_new (NUM_COLUMNS,
65                               G_TYPE_STRING,
66                               G_TYPE_BOOLEAN,
67                               G_TYPE_BOOLEAN,
68                               GDK_TYPE_PIXBUF,
69                               GDK_TYPE_PIXBUF,
70                               G_TYPE_INT);
71
72   for (i = 0; model_strings[i].string != NULL; i++)
73     {
74       gtk_tree_store_append (model, &iter, NULL);
75
76       gtk_tree_store_set (model, &iter,
77                           STRING_COLUMN, model_strings[i].string,
78                           IS_EDITABLE_COLUMN, model_strings[i].is_editable,
79                           IS_SENSITIVE_COLUMN, model_strings[i].is_sensitive,
80                           PIXBUF_COLUMN, foo,
81                           LAST_PIXBUF_COLUMN, bar,
82                           PROGRESS_COLUMN, model_strings[i].progress,
83                           -1);
84     }
85   
86   return GTK_TREE_MODEL (model);
87 }
88
89 static void
90 editable_toggled (GtkCellRendererToggle *cell,
91                   gchar                 *path_string,
92                   gpointer               data)
93 {
94   GtkTreeModel *model = GTK_TREE_MODEL (data);
95   GtkTreeIter iter;
96   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
97   gboolean value;
98
99   gtk_tree_model_get_iter (model, &iter, path);
100   gtk_tree_model_get (model, &iter, IS_EDITABLE_COLUMN, &value, -1);
101
102   value = !value;
103   gtk_tree_store_set (GTK_TREE_STORE (model), &iter, IS_EDITABLE_COLUMN, value, -1);
104
105   gtk_tree_path_free (path);
106 }
107
108 static void
109 sensitive_toggled (GtkCellRendererToggle *cell,
110                    gchar                 *path_string,
111                    gpointer               data)
112 {
113   GtkTreeModel *model = GTK_TREE_MODEL (data);
114   GtkTreeIter iter;
115   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
116   gboolean value;
117
118   gtk_tree_model_get_iter (model, &iter, path);
119   gtk_tree_model_get (model, &iter, IS_SENSITIVE_COLUMN, &value, -1);
120
121   value = !value;
122   gtk_tree_store_set (GTK_TREE_STORE (model), &iter, IS_SENSITIVE_COLUMN, value, -1);
123
124   gtk_tree_path_free (path);
125 }
126
127 static void
128 edited (GtkCellRendererText *cell,
129         gchar               *path_string,
130         gchar               *new_text,
131         gpointer             data)
132 {
133   GtkTreeModel *model = GTK_TREE_MODEL (data);
134   GtkTreeIter iter;
135   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
136
137   gtk_tree_model_get_iter (model, &iter, path);
138   gtk_tree_store_set (GTK_TREE_STORE (model), &iter, STRING_COLUMN, new_text, -1);
139
140   gtk_tree_path_free (path);
141 }
142
143 static gboolean
144 button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer callback_data)
145 {
146         /* Deselect if people click outside any row. */
147         if (event->window == gtk_tree_view_get_bin_window (GTK_TREE_VIEW (widget))
148             && !gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
149                                                event->x, event->y, NULL, NULL, NULL, NULL)) {
150                 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget)));
151         }
152
153         /* Let the default code run in any case; it won't reselect anything. */
154         return FALSE;
155 }
156
157 typedef struct {
158   GtkCellArea     *area;
159   GtkCellRenderer *renderer;
160 } CallbackData;
161
162 static void
163 align_cell_toggled (GtkToggleButton  *toggle,
164                     CallbackData     *data)
165 {
166   gboolean active = gtk_toggle_button_get_active (toggle);
167
168   gtk_cell_area_cell_set (data->area, data->renderer, "align", active, NULL);
169 }
170
171 static void
172 expand_cell_toggled (GtkToggleButton  *toggle,
173                      CallbackData     *data)
174 {
175   gboolean active = gtk_toggle_button_get_active (toggle);
176
177   gtk_cell_area_cell_set (data->area, data->renderer, "expand", active, NULL);
178 }
179
180 static void
181 fixed_cell_toggled (GtkToggleButton  *toggle,
182                     CallbackData     *data)
183 {
184   gboolean active = gtk_toggle_button_get_active (toggle);
185
186   gtk_cell_area_cell_set (data->area, data->renderer, "fixed-size", active, NULL);
187 }
188
189 enum {
190   CNTL_EXPAND,
191   CNTL_ALIGN,
192   CNTL_FIXED
193 };
194
195 static void
196 create_control (GtkWidget *box, gint number, gint cntl, CallbackData *data)
197 {
198   GtkWidget *checkbutton;
199   GCallback  callback = NULL;
200   gchar *name = NULL;
201
202   switch (cntl)
203     {
204     case CNTL_EXPAND: 
205       name = g_strdup_printf ("Expand Cell #%d", number); 
206       callback = G_CALLBACK (expand_cell_toggled);
207       break;
208     case CNTL_ALIGN: 
209       name = g_strdup_printf ("Align Cell #%d", number); 
210       callback = G_CALLBACK (align_cell_toggled);
211       break;
212     case CNTL_FIXED: 
213       name = g_strdup_printf ("Fix size Cell #%d", number); 
214       callback = G_CALLBACK (fixed_cell_toggled);
215       break;
216     }
217
218   checkbutton = gtk_check_button_new_with_label (name);
219   gtk_widget_show (checkbutton);
220   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), cntl == CNTL_FIXED);
221   gtk_box_pack_start (GTK_BOX (box), checkbutton, FALSE, FALSE, 0);
222
223   g_signal_connect (G_OBJECT (checkbutton), "toggled", callback, data);
224   g_free (name);
225 }
226
227 gint
228 main (gint argc, gchar **argv)
229 {
230   GtkWidget *window;
231   GtkWidget *scrolled_window;
232   GtkWidget *tree_view;
233   GtkWidget *vbox, *hbox, *cntl_vbox;
234   GtkTreeModel *tree_model;
235   GtkCellRenderer *renderer;
236   GtkTreeViewColumn *column;
237   GtkCellArea *area;
238   CallbackData callback[4];
239   
240   gtk_init (&argc, &argv);
241
242   if (g_getenv ("RTL"))
243     gtk_widget_set_default_direction (GTK_TEXT_DIR_RTL);
244
245   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
246   gtk_window_set_title (GTK_WINDOW (window), "GtkTreeView editing sample");
247   g_signal_connect (window, "destroy", gtk_main_quit, NULL);
248
249   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
250   gtk_widget_show (vbox);
251   gtk_container_add (GTK_CONTAINER (window), vbox);
252
253   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
254   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
255   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), 
256                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
257   gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
258
259   tree_model = create_model ();
260   tree_view = gtk_tree_view_new_with_model (tree_model);
261   g_signal_connect (tree_view, "button_press_event", G_CALLBACK (button_press_event), NULL);
262   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
263   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree_view), TRUE);
264
265   column = gtk_tree_view_column_new ();
266   gtk_tree_view_column_set_title (column, "String");
267   area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
268
269   renderer = gtk_cell_renderer_pixbuf_new ();
270   gtk_tree_view_column_pack_start (column, renderer, FALSE);
271   gtk_tree_view_column_set_attributes (column, renderer,
272                                        "pixbuf", PIXBUF_COLUMN, 
273                                        "sensitive", IS_SENSITIVE_COLUMN,
274                                        NULL);
275   callback[0].area = area;
276   callback[0].renderer = renderer;
277
278   renderer = gtk_cell_renderer_text_new ();
279   gtk_tree_view_column_pack_start (column, renderer, FALSE);
280   gtk_tree_view_column_set_attributes (column, renderer,
281                                        "text", STRING_COLUMN,
282                                        "editable", IS_EDITABLE_COLUMN,
283                                        "sensitive", IS_SENSITIVE_COLUMN,
284                                        NULL);
285   callback[1].area = area;
286   callback[1].renderer = renderer;
287   g_signal_connect (renderer, "edited",
288                     G_CALLBACK (edited), tree_model);
289   g_object_set (renderer,
290                 "placeholder-text", "Type here",
291                 NULL);
292
293   renderer = gtk_cell_renderer_text_new ();
294   gtk_tree_view_column_pack_start (column, renderer, FALSE);
295   gtk_tree_view_column_set_attributes (column, renderer,
296                                        "text", STRING_COLUMN,
297                                        "editable", IS_EDITABLE_COLUMN,
298                                        "sensitive", IS_SENSITIVE_COLUMN,
299                                        NULL);
300   callback[2].area = area;
301   callback[2].renderer = renderer;
302   g_signal_connect (renderer, "edited",
303                     G_CALLBACK (edited), tree_model);
304   g_object_set (renderer,
305                 "placeholder-text", "Type here too",
306                 NULL);
307
308   renderer = gtk_cell_renderer_pixbuf_new ();
309   g_object_set (renderer,
310                 "xalign", 0.0,
311                 NULL);
312   gtk_tree_view_column_pack_start (column, renderer, FALSE);
313   gtk_tree_view_column_set_attributes (column, renderer,
314                                        "pixbuf", LAST_PIXBUF_COLUMN, 
315                                        "sensitive", IS_SENSITIVE_COLUMN,
316                                        NULL);
317   callback[3].area = area;
318   callback[3].renderer = renderer;
319
320   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
321
322   renderer = gtk_cell_renderer_toggle_new ();
323   g_signal_connect (renderer, "toggled",
324                     G_CALLBACK (editable_toggled), tree_model);
325   
326   g_object_set (renderer,
327                 "xalign", 0.0,
328                 NULL);
329   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
330                                                -1, "Editable",
331                                                renderer,
332                                                "active", IS_EDITABLE_COLUMN,
333                                                NULL);
334
335   renderer = gtk_cell_renderer_toggle_new ();
336   g_signal_connect (renderer, "toggled",
337                     G_CALLBACK (sensitive_toggled), tree_model);
338   
339   g_object_set (renderer,
340                 "xalign", 0.0,
341                 NULL);
342   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
343                                                -1, "Sensitive",
344                                                renderer,
345                                                "active", IS_SENSITIVE_COLUMN,
346                                                NULL);
347
348   renderer = gtk_cell_renderer_progress_new ();
349   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view),
350                                                -1, "Progress",
351                                                renderer,
352                                                "value", PROGRESS_COLUMN,
353                                                NULL);
354
355   gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
356   
357   gtk_window_set_default_size (GTK_WINDOW (window),
358                                800, 250);
359
360   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
361   gtk_widget_show (hbox);
362   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
363
364   /* Alignment controls */
365   cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
366   gtk_widget_show (cntl_vbox);
367   gtk_box_pack_start (GTK_BOX (hbox), cntl_vbox, FALSE, FALSE, 0);
368
369   create_control (cntl_vbox, 1, CNTL_ALIGN, &callback[0]);
370   create_control (cntl_vbox, 2, CNTL_ALIGN, &callback[1]);
371   create_control (cntl_vbox, 3, CNTL_ALIGN, &callback[2]);
372   create_control (cntl_vbox, 4, CNTL_ALIGN, &callback[3]);
373
374   /* Expand controls */
375   cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
376   gtk_widget_show (cntl_vbox);
377   gtk_box_pack_start (GTK_BOX (hbox), cntl_vbox, FALSE, FALSE, 0);
378
379   create_control (cntl_vbox, 1, CNTL_EXPAND, &callback[0]);
380   create_control (cntl_vbox, 2, CNTL_EXPAND, &callback[1]);
381   create_control (cntl_vbox, 3, CNTL_EXPAND, &callback[2]);
382   create_control (cntl_vbox, 4, CNTL_EXPAND, &callback[3]);
383
384   /* Fixed controls */
385   cntl_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
386   gtk_widget_show (cntl_vbox);
387   gtk_box_pack_start (GTK_BOX (hbox), cntl_vbox, FALSE, FALSE, 0);
388
389   create_control (cntl_vbox, 1, CNTL_FIXED, &callback[0]);
390   create_control (cntl_vbox, 2, CNTL_FIXED, &callback[1]);
391   create_control (cntl_vbox, 3, CNTL_FIXED, &callback[2]);
392   create_control (cntl_vbox, 4, CNTL_FIXED, &callback[3]);
393
394   gtk_widget_show_all (window);
395   gtk_main ();
396
397   return 0;
398 }