]> Pileus Git - ~andy/gtk/blob - tests/testtreecolumns.c
af95e5e39b5ef282966f547ae915035b7c9100ba
[~andy/gtk] / tests / testtreecolumns.c
1 #include <gtk/gtk.h>
2
3
4 GtkWidget *left_tree_view;
5 GtkWidget *top_right_tree_view;
6 GtkWidget *bottom_right_tree_view;
7 GtkTreeModel *left_tree_model;
8 GtkTreeModel *top_right_tree_model;
9 GtkTreeModel *bottom_right_tree_model;
10 GtkWidget *sample_tree_view_top;
11 GtkWidget *sample_tree_view_bottom;
12
13 #define column_data "my_column_data"
14
15
16
17 /* Kids, don't try this at home.
18  */
19
20 /* Small GtkTreeModel to model columns */
21 typedef struct _ViewColumnModel ViewColumnModel;
22 typedef struct _ViewColumnModelClass ViewColumnModelClass;
23
24 struct _ViewColumnModel
25 {
26   GObject parent;
27   GtkTreeView *view;
28   GList *columns;
29   gint stamp;
30 };
31
32 struct _ViewColumnModelClass
33 {
34   GObjectClass parent_class;
35 };
36
37 static void view_column_model_class_init (ViewColumnModelClass *model)
38 {
39 }
40
41 static void view_column_model_init (ViewColumnModel *model)
42 {
43   model->stamp = g_random_int ();
44 }
45
46 static gint
47 view_column_model_get_n_columns (GtkTreeModel *tree_model)
48 {
49   return 2;
50 }
51
52 static GType
53 view_column_model_get_column_type (GtkTreeModel *tree_model,
54                                    gint          index)
55 {
56   switch (index)
57     {
58     case 0:
59       return G_TYPE_STRING;
60     case 1:
61       return GTK_TYPE_TREE_VIEW_COLUMN;
62     default:
63       return G_TYPE_INVALID;
64     }
65 }
66
67 static gboolean
68 view_column_model_get_iter (GtkTreeModel *tree_model,
69                             GtkTreeIter  *iter,
70                             GtkTreePath  *path)
71
72 {
73   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
74   GList *list;
75   gint i;
76
77   g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
78
79   i = gtk_tree_path_get_indices (path)[0];
80   list = g_list_nth (view_model->columns, i);
81
82   if (list == NULL)
83     return FALSE;
84
85   iter->stamp = view_model->stamp;
86   iter->user_data = list;
87
88   return TRUE;
89 }
90
91 static GtkTreePath *
92 view_column_model_get_path (GtkTreeModel *tree_model,
93                             GtkTreeIter  *iter)
94 {
95   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
96   GtkTreePath *retval;
97   GList *list;
98   gint i = 0;
99
100   g_return_val_if_fail (iter->stamp == view_model->stamp, NULL);
101
102   for (list = view_model->columns; list; list = list->next)
103     {
104       if (list == (GList *)iter->user_data)
105         break;
106       i++;
107     }
108   if (list == NULL)
109     return NULL;
110
111   retval = gtk_tree_path_new ();
112   gtk_tree_path_append_index (retval, i);
113   return retval;
114 }
115
116 static void
117 view_column_model_get_value (GtkTreeModel *tree_model,
118                              GtkTreeIter  *iter,
119                              gint          column,
120                              GValue       *value)
121 {
122   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
123
124   g_return_if_fail (column < 2);
125   g_return_if_fail (view_model->stamp == iter->stamp);
126   g_return_if_fail (iter->user_data != NULL);
127
128   if (column == 0)
129     {
130       g_value_init (value, G_TYPE_STRING);
131       g_value_set_string (value, gtk_tree_view_column_get_title (GTK_TREE_VIEW_COLUMN (((GList *)iter->user_data)->data)));
132     }
133   else
134     {
135       g_value_init (value, GTK_TYPE_TREE_VIEW_COLUMN);
136       g_value_set_object (value, ((GList *)iter->user_data)->data);
137     }
138 }
139
140 static gboolean
141 view_column_model_iter_next (GtkTreeModel  *tree_model,
142                              GtkTreeIter   *iter)
143 {
144   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
145
146   g_return_val_if_fail (view_model->stamp == iter->stamp, FALSE);
147   g_return_val_if_fail (iter->user_data != NULL, FALSE);
148
149   iter->user_data = ((GList *)iter->user_data)->next;
150   return iter->user_data != NULL;
151 }
152
153 static gboolean
154 view_column_model_iter_children (GtkTreeModel *tree_model,
155                                  GtkTreeIter  *iter,
156                                  GtkTreeIter  *parent)
157 {
158   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
159
160   /* this is a list, nodes have no children */
161   if (parent)
162     return FALSE;
163
164   /* but if parent == NULL we return the list itself as children of the
165    * "root"
166    */
167
168   if (view_model->columns)
169     {
170       iter->stamp = view_model->stamp;
171       iter->user_data = view_model->columns;
172       return TRUE;
173     }
174   else
175     return FALSE;
176 }
177
178 static gboolean
179 view_column_model_iter_has_child (GtkTreeModel *tree_model,
180                                   GtkTreeIter  *iter)
181 {
182   return FALSE;
183 }
184
185 static gint
186 view_column_model_iter_n_children (GtkTreeModel *tree_model,
187                                    GtkTreeIter  *iter)
188 {
189   return g_list_length (((ViewColumnModel *)tree_model)->columns);
190 }
191
192 static gint
193 view_column_model_iter_nth_child (GtkTreeModel *tree_model,
194                                   GtkTreeIter  *iter,
195                                   GtkTreeIter  *parent,
196                                   gint          n)
197 {
198   ViewColumnModel *view_model = (ViewColumnModel *)tree_model;
199
200   if (parent)
201     return FALSE;
202
203   iter->stamp = view_model->stamp;
204   iter->user_data = g_list_nth ((GList *)view_model->columns, n);
205
206   return (iter->user_data != NULL);
207 }
208
209 static gboolean
210 view_column_model_iter_parent (GtkTreeModel *tree_model,
211                                GtkTreeIter  *iter,
212                                GtkTreeIter  *child)
213 {
214   return FALSE;
215 }
216
217 static void
218 view_column_model_tree_model_init (GtkTreeModelIface *iface)
219 {
220   iface->get_n_columns = view_column_model_get_n_columns;
221   iface->get_column_type = view_column_model_get_column_type;
222   iface->get_iter = view_column_model_get_iter;
223   iface->get_path = view_column_model_get_path;
224   iface->get_value = view_column_model_get_value;
225   iface->iter_next = view_column_model_iter_next;
226   iface->iter_children = view_column_model_iter_children;
227   iface->iter_has_child = view_column_model_iter_has_child;
228   iface->iter_n_children = view_column_model_iter_n_children;
229   iface->iter_nth_child = view_column_model_iter_nth_child;
230   iface->iter_parent = view_column_model_iter_parent;
231 }
232
233
234 GType
235 view_column_model_get_type (void)
236 {
237   static GType view_column_model_type = 0;
238
239   if (!view_column_model_type)
240     {
241       static const GTypeInfo view_column_model_info =
242       {
243         sizeof (GtkListStoreClass),
244         NULL,           /* base_init */
245         NULL,           /* base_finalize */
246         (GClassInitFunc) view_column_model_class_init,
247         NULL,           /* class_finalize */
248         NULL,           /* class_data */
249         sizeof (GtkListStore),
250         0,
251         (GInstanceInitFunc) view_column_model_init,
252       };
253
254       static const GInterfaceInfo tree_model_info =
255       {
256         (GInterfaceInitFunc) view_column_model_tree_model_init,
257         NULL,
258         NULL
259       };
260
261       view_column_model_type = g_type_register_static (G_TYPE_OBJECT, "ViewModelColumn", &view_column_model_info, 0);
262       g_type_add_interface_static (view_column_model_type,
263                                    GTK_TYPE_TREE_MODEL,
264                                    &tree_model_info);
265     }
266
267   return view_column_model_type;
268 }
269
270 static void
271 update_columns (GtkTreeView *view, ViewColumnModel *view_model)
272 {
273   GList *old_columns = view_model->columns;
274   gint old_length, length;
275   GList *a, *b;
276
277   view_model->columns = gtk_tree_view_get_columns (view_model->view);
278
279   /* As the view tells us one change at a time, we can do this hack. */
280   length = g_list_length (view_model->columns);
281   old_length = g_list_length (old_columns);
282   if (length != old_length)
283     {
284       GtkTreePath *path;
285       gint i = 0;
286
287       /* where are they different */
288       for (a = old_columns, b = view_model->columns; a && b; a = a->next, b = b->next)
289         {
290           if (a->data != b->data)
291             break;
292           i++;
293         }
294       path = gtk_tree_path_new ();
295       gtk_tree_path_append_index (path, i);
296       if (length < old_length)
297         {
298           view_model->stamp++;
299           gtk_tree_model_deleted (GTK_TREE_MODEL (view_model), path);
300         }
301       else
302         {
303           GtkTreeIter iter;
304           iter.stamp = view_model->stamp;
305           iter.user_data = b;
306           gtk_tree_model_inserted (GTK_TREE_MODEL (view_model), path, &iter);
307         }
308       gtk_tree_path_free (path);
309     }
310   else
311     {
312       gint i;
313       gint m = 0, n = 1;
314       gint *new_order;
315       GtkTreePath *path;
316
317       new_order = g_new (int, length);
318       a = old_columns; b = view_model->columns;
319
320       while (a->data == b->data)
321         {
322           a = a->next;
323           b = b->next;
324           if (a == NULL)
325             return;
326           m++;
327         }
328
329       if (a->next->data == b->data)
330         {
331           b = b->next;
332           while (b->data != a->data)
333             {
334               b = b->next;
335               n++;
336             }
337           for (i = 0; i < m; i++)
338             new_order[i] = i;
339           for (i = m; i < m+n; i++)
340             new_order[i] = i+1;
341           new_order[i] = m;
342           for (i = m + n +1; i < length; i++)
343             new_order[i] = i;
344         }
345       else
346         {
347           a = a->next;
348           while (a->data != b->data)
349             {
350               a = a->next;
351               n++;
352             }
353           for (i = 0; i < m; i++)
354             new_order[i] = i;
355           new_order[m] = m+n;
356           for (i = m+1; i < m + n+ 1; i++)
357             new_order[i] = i - 1;
358           for (i = m + n + 1; i < length; i++)
359             new_order[i] = i;
360         }
361
362       path = gtk_tree_path_new ();
363       gtk_tree_model_reordered (GTK_TREE_MODEL (view_model),
364                                 path,
365                                 NULL,
366                                 new_order);
367       gtk_tree_path_free (path);
368       g_free (new_order);
369     }
370   if (old_columns)
371     g_list_free (old_columns);
372 }
373
374 static GtkTreeModel *
375 view_column_model_new (GtkTreeView *view)
376 {
377   GtkTreeModel *retval;
378
379   retval = GTK_TREE_MODEL (g_object_new (view_column_model_get_type (), NULL));
380   ((ViewColumnModel *)retval)->view = view;
381   ((ViewColumnModel *)retval)->columns = gtk_tree_view_get_columns (view);
382
383   gtk_signal_connect (GTK_OBJECT (view), "columns_changed", GTK_SIGNAL_FUNC (update_columns), retval);
384
385   return retval;
386 }
387
388 /* Back to sanity.
389  */
390
391 static void
392 add_clicked (GtkWidget *button, gpointer data)
393 {
394   static gint i = 0;
395
396   GtkTreeIter iter;
397   GtkTreeViewColumn *column;
398   GtkTreeSelection *selection;
399   GtkCellRenderer *cell;
400   gchar *label = g_strdup_printf ("Column %d", i);
401
402   cell = gtk_cell_renderer_text_new ();
403   column = gtk_tree_view_column_new_with_attributes (label, cell, "text", 0, NULL);
404   g_object_set_data_full (G_OBJECT (column), column_data, label, g_free);
405   gtk_tree_view_column_set_reorderable (column, TRUE);
406   gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_RESIZEABLE);
407   gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter);
408   gtk_list_store_set (GTK_LIST_STORE (left_tree_model), &iter, 0, label, 1, column, -1);
409   i++;
410
411   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
412   gtk_tree_selection_select_iter (selection, &iter);
413 }
414
415 static void
416 get_visible (GtkTreeViewColumn *tree_column,
417              GtkCellRenderer   *cell,
418              GtkTreeModel      *tree_model,
419              GtkTreeIter       *iter,
420              gpointer           data)
421 {
422   GtkTreeViewColumn *column;
423
424   gtk_tree_model_get (tree_model, iter, 1, &column, -1);
425   if (column)
426     {
427       gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell),
428                                            column->visible);
429     }
430 }
431
432 static void
433 set_visible (GtkCellRendererToggle *cell,
434              gchar                 *path_str,
435              gpointer               data)
436 {
437   GtkTreeView *tree_view = (GtkTreeView *) data;
438   GtkTreeViewColumn *column;
439   GtkTreeModel *model;
440   GtkTreeIter iter;
441   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
442
443   model = gtk_tree_view_get_model (tree_view);
444
445   gtk_tree_model_get_iter (model, &iter, path);
446   gtk_tree_model_get (model, &iter, 1, &column, -1);
447
448   if (column)
449     {
450       gtk_tree_view_column_set_visible (column, ! gtk_tree_view_column_get_visible (column));
451       gtk_tree_model_range_changed (model, path, &iter, path, &iter);
452     }
453   gtk_tree_path_free (path);
454 }
455
456 static void
457 add_left_clicked (GtkWidget *button,
458                   gpointer data)
459 {
460   GtkTreeIter iter;
461   gchar *label;
462   GtkTreeViewColumn *column;
463
464   GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (data));
465
466   gtk_tree_selection_get_selected (selection, NULL, &iter);
467   gtk_tree_model_get (gtk_tree_view_get_model (GTK_TREE_VIEW (data)),
468                       &iter, 0, &label, 1, &column, -1);
469
470   if (GTK_WIDGET (data) == top_right_tree_view)
471     gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_top), column);
472   else
473     gtk_tree_view_remove_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
474
475   /*  gtk_list_store_remove (GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (data))), &iter);*/
476
477   /* Put it back on the left */
478   gtk_list_store_append (GTK_LIST_STORE (left_tree_model), &iter);
479   gtk_list_store_set (GTK_LIST_STORE (left_tree_model), &iter, 0, label, 1, column, -1);
480   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
481   gtk_tree_selection_select_iter (selection, &iter);
482   g_free (label);
483 }
484
485
486 static void
487 add_right_clicked (GtkWidget *button, gpointer data)
488 {
489   GtkTreeIter iter;
490   gchar *label;
491   GtkTreeViewColumn *column;
492
493   GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view));
494
495   gtk_tree_selection_get_selected (selection, NULL, &iter);
496   gtk_tree_model_get (GTK_TREE_MODEL (left_tree_model),
497                       &iter, 0, &label, 1, &column, -1);
498   gtk_list_store_remove (GTK_LIST_STORE (left_tree_model), &iter);
499
500   if (GTK_WIDGET (data) == top_right_tree_view)
501     gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_top), column);
502   else
503     gtk_tree_view_append_column (GTK_TREE_VIEW (sample_tree_view_bottom), column);
504   g_free (label);
505 }
506
507 static void
508 selection_changed (GtkTreeSelection *selection, GtkWidget *button)
509 {
510   if (gtk_tree_selection_get_selected (selection, NULL, NULL))
511     gtk_widget_set_sensitive (button, TRUE);
512   else
513     gtk_widget_set_sensitive (button, FALSE);
514 }
515
516 static GtkTargetEntry row_targets[] = {
517   { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP, 0}
518 };
519
520 int
521 main (int argc, char *argv[])
522 {
523   GtkWidget *window;
524   GtkWidget *hbox, *vbox;
525   GtkWidget *vbox2, *bbox;
526   GtkWidget *button;
527   GtkTreeViewColumn *column;
528   GtkCellRenderer *cell;
529   GtkWidget *swindow;
530   GtkTreeModel *sample_model;
531   gint i;
532
533   gtk_init (&argc, &argv);
534
535   /* First initialize all the models for signal purposes */
536   left_tree_model = (GtkTreeModel *) gtk_list_store_new_with_types (2, G_TYPE_STRING, GTK_TYPE_POINTER);
537   sample_model = (GtkTreeModel *) gtk_list_store_new_with_types (1, G_TYPE_STRING);
538   sample_tree_view_top = gtk_tree_view_new_with_model (sample_model);
539   sample_tree_view_bottom = gtk_tree_view_new_with_model (sample_model);
540   top_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_top));
541   bottom_right_tree_model = (GtkTreeModel *) view_column_model_new (GTK_TREE_VIEW (sample_tree_view_bottom));
542   top_right_tree_view = gtk_tree_view_new_with_model (top_right_tree_model);
543   bottom_right_tree_view = gtk_tree_view_new_with_model (bottom_right_tree_model);
544
545   for (i = 0; i < 10; i++)
546     {
547       GtkTreeIter iter;
548       gchar *string = g_strdup_printf ("%d", i);
549       gtk_list_store_append (GTK_LIST_STORE (sample_model), &iter);
550       gtk_list_store_set (GTK_LIST_STORE (sample_model), &iter, 0, string, -1);
551       g_free (string);
552     }
553
554   /* Set up the test windows. */
555   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
556   gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
557   gtk_window_set_title (GTK_WINDOW (window), "Top Window");
558   swindow = gtk_scrolled_window_new (NULL, NULL);
559   gtk_container_add (GTK_CONTAINER (window), swindow);
560   gtk_container_add (GTK_CONTAINER (swindow), sample_tree_view_top);
561   gtk_widget_show_all (window);
562
563   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
564   gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
565   gtk_window_set_title (GTK_WINDOW (window), "Bottom Window");
566   swindow = gtk_scrolled_window_new (NULL, NULL);
567   gtk_container_add (GTK_CONTAINER (window), swindow);
568   gtk_container_add (GTK_CONTAINER (swindow), sample_tree_view_bottom);
569   gtk_widget_show_all (window);
570
571   /* Set up the main window */
572   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
573   gtk_window_set_default_size (GTK_WINDOW (window), 500, 300);
574   vbox = gtk_vbox_new (FALSE, 8);
575   gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
576   gtk_container_add (GTK_CONTAINER (window), vbox);
577
578   hbox = gtk_hbox_new (FALSE, 8);
579   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
580
581   /* Left Pane */
582   cell = gtk_cell_renderer_text_new ();
583
584   swindow = gtk_scrolled_window_new (NULL, NULL);
585   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
586   left_tree_view = gtk_tree_view_new_with_model (left_tree_model);
587   gtk_container_add (GTK_CONTAINER (swindow), left_tree_view);
588   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (left_tree_view), -1,
589                                                "Unattached Columns", cell, "text", 0, NULL);
590   cell = gtk_cell_renderer_toggle_new ();
591   g_signal_connect_data (G_OBJECT (cell), "toggled", (GCallback) set_visible, left_tree_view, NULL, FALSE, FALSE);
592   column = gtk_tree_view_column_new_with_attributes ("Visible", cell, NULL);
593   gtk_tree_view_append_column (GTK_TREE_VIEW (left_tree_view), column);
594   g_object_unref (G_OBJECT (column));
595   gtk_tree_view_column_set_cell_data_func (column, get_visible, NULL, NULL);
596   gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
597
598   /* Middle Pane */
599   vbox2 = gtk_vbox_new (FALSE, 8);
600   gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 0);
601   
602   bbox = gtk_vbutton_box_new ();
603   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
604   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0);
605   gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0);
606
607   button = gtk_button_new_with_label ("<<");
608   gtk_widget_set_sensitive (button, FALSE);
609   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), top_right_tree_view);
610   gtk_signal_connect (GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (top_right_tree_view))),
611                       "selection-changed", GTK_SIGNAL_FUNC (selection_changed), button);
612   gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
613
614   button = gtk_button_new_with_label (">>");
615   gtk_widget_set_sensitive (button, FALSE);
616   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), top_right_tree_view);
617   gtk_signal_connect (GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))),
618                       "selection-changed", GTK_SIGNAL_FUNC (selection_changed), button);
619   gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
620
621   bbox = gtk_vbutton_box_new ();
622   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_SPREAD);
623   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), 0, 0);
624   gtk_box_pack_start (GTK_BOX (vbox2), bbox, TRUE, TRUE, 0);
625
626   button = gtk_button_new_with_label ("<<");
627   gtk_widget_set_sensitive (button, FALSE);
628   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_left_clicked), bottom_right_tree_view);
629   gtk_signal_connect (GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (bottom_right_tree_view))),
630                       "selection-changed", GTK_SIGNAL_FUNC (selection_changed), button);
631   gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
632
633   button = gtk_button_new_with_label (">>");
634   gtk_widget_set_sensitive (button, FALSE);
635   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_right_clicked), bottom_right_tree_view);
636   gtk_signal_connect (GTK_OBJECT (gtk_tree_view_get_selection (GTK_TREE_VIEW (left_tree_view))),
637                       "selection-changed", GTK_SIGNAL_FUNC (selection_changed), button);
638   gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
639
640   
641   /* Right Pane */
642   vbox2 = gtk_vbox_new (FALSE, 8);
643   gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
644
645   swindow = gtk_scrolled_window_new (NULL, NULL);
646   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
647   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (top_right_tree_view), FALSE);
648   cell = gtk_cell_renderer_text_new ();
649   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (top_right_tree_view), -1,
650                                                NULL, cell, "text", 0, NULL);
651   cell = gtk_cell_renderer_toggle_new ();
652   g_signal_connect_data (G_OBJECT (cell), "toggled", (GCallback) set_visible, top_right_tree_view, NULL, FALSE, FALSE);
653   column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
654   gtk_tree_view_column_set_cell_data_func (column, get_visible, NULL, NULL);
655   gtk_tree_view_append_column (GTK_TREE_VIEW (top_right_tree_view), column);
656
657   gtk_container_add (GTK_CONTAINER (swindow), top_right_tree_view);
658   gtk_box_pack_start (GTK_BOX (vbox2), swindow, TRUE, TRUE, 0);
659
660   swindow = gtk_scrolled_window_new (NULL, NULL);
661   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
662   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (bottom_right_tree_view), FALSE);
663   cell = gtk_cell_renderer_text_new ();
664   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (bottom_right_tree_view), -1,
665                                                NULL, cell, "text", 0, NULL);
666   cell = gtk_cell_renderer_toggle_new ();
667   g_signal_connect_data (G_OBJECT (cell), "toggled", (GCallback) set_visible, bottom_right_tree_view, NULL, FALSE, FALSE);
668   column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
669   gtk_tree_view_column_set_cell_data_func (column, get_visible, NULL, NULL);
670   gtk_tree_view_append_column (GTK_TREE_VIEW (bottom_right_tree_view), column);
671   gtk_container_add (GTK_CONTAINER (swindow), bottom_right_tree_view);
672   gtk_box_pack_start (GTK_BOX (vbox2), swindow, TRUE, TRUE, 0);
673
674   
675   /* Drag and Drop */
676   gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (left_tree_view),
677                                       GDK_BUTTON1_MASK,
678                                       row_targets,
679                                       G_N_ELEMENTS (row_targets),
680                                       GDK_ACTION_MOVE,
681                                       NULL, NULL);
682   gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (left_tree_view),
683                                     row_targets,
684                                     G_N_ELEMENTS (row_targets),
685                                     GDK_ACTION_MOVE,
686                                     NULL, NULL);
687
688   gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (top_right_tree_view),
689                                       GDK_BUTTON1_MASK,
690                                       row_targets,
691                                       G_N_ELEMENTS (row_targets),
692                                       GDK_ACTION_MOVE,
693                                       NULL, NULL);
694   gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (top_right_tree_view),
695                                     row_targets,
696                                     G_N_ELEMENTS (row_targets),
697                                     GDK_ACTION_MOVE,
698                                       NULL, NULL);
699
700   gtk_tree_view_set_rows_drag_source (GTK_TREE_VIEW (bottom_right_tree_view),
701                                       GDK_BUTTON1_MASK,
702                                       row_targets,
703                                       G_N_ELEMENTS (row_targets),
704                                       GDK_ACTION_MOVE,
705                                       NULL, NULL);
706   gtk_tree_view_set_rows_drag_dest (GTK_TREE_VIEW (bottom_right_tree_view),
707                                     row_targets,
708                                     G_N_ELEMENTS (row_targets),
709                                     GDK_ACTION_MOVE,
710                                     NULL, NULL);
711
712
713   gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
714
715   hbox = gtk_hbox_new (FALSE, 8);
716   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
717   button = gtk_button_new_with_mnemonic ("_Add new Column");
718   gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (add_clicked), left_tree_model);
719   gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
720
721   gtk_widget_show_all (window);
722   gtk_main ();
723
724   return 0;
725 }