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