]> Pileus Git - ~andy/gtk/blob - examples/tree/tree.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / examples / tree / tree.c
1
2 #define GTK_ENABLE_BROKEN
3 #include <config.h>
4 #include <gtk/gtk.h>
5
6 /* for all the GtkItem:: and GtkTreeItem:: signals */
7 static void cb_itemsignal( GtkWidget *item,
8                            gchar     *signame )
9 {
10   gchar *name;
11   GtkLabel *label;
12
13   /* It's a Bin, so it has one child, which we know to be a
14      label, so get that */
15   label = GTK_LABEL (GTK_BIN (item)->child);
16   /* Get the text of the label */
17   gtk_label_get (label, &name);
18   /* Get the level of the tree which the item is in */
19   g_print ("%s called for item %s->%p, level %d\n", signame, name,
20            item, GTK_TREE (item->parent)->level);
21 }
22
23 /* Note that this is never called */
24 static void cb_unselect_child( GtkWidget *root_tree,
25                                GtkWidget *child,
26                                GtkWidget *subtree )
27 {
28   g_print ("unselect_child called for root tree %p, subtree %p, child %p\n",
29            root_tree, subtree, child);
30 }
31
32 /* Note that this is called every time the user clicks on an item,
33    whether it is already selected or not. */
34 static void cb_select_child (GtkWidget *root_tree, GtkWidget *child,
35                              GtkWidget *subtree)
36 {
37   g_print ("select_child called for root tree %p, subtree %p, child %p\n",
38            root_tree, subtree, child);
39 }
40
41 static void cb_selection_changed( GtkWidget *tree )
42 {
43   GList *i;
44   
45   g_print ("selection_change called for tree %p\n", tree);
46   g_print ("selected objects are:\n");
47
48   i = GTK_TREE_SELECTION_OLD (tree);
49   while (i) {
50     gchar *name;
51     GtkLabel *label;
52     GtkWidget *item;
53
54     /* Get a GtkWidget pointer from the list node */
55     item = GTK_WIDGET (i->data);
56     label = GTK_LABEL (GTK_BIN (item)->child);
57     gtk_label_get (label, &name);
58     g_print ("\t%s on level %d\n", name, GTK_TREE
59              (item->parent)->level);
60     i = i->next;
61   }
62 }
63
64 int main( int   argc,
65           char *argv[] )
66 {
67   GtkWidget *window, *scrolled_win, *tree;
68   static gchar *itemnames[] = {"Foo", "Bar", "Baz", "Quux",
69                                "Maurice"};
70   gint i;
71
72   gtk_init (&argc, &argv);
73
74   /* a generic toplevel window */
75   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
76   g_signal_connect (G_OBJECT (window), "delete_event",
77                     G_CALLBACK (gtk_main_quit), NULL);
78   gtk_container_set_border_width (GTK_CONTAINER (window), 5);
79
80   /* A generic scrolled window */
81   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
82   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
83                                   GTK_POLICY_AUTOMATIC,
84                                   GTK_POLICY_AUTOMATIC);
85   gtk_widget_set_size_request (scrolled_win, 150, 200);
86   gtk_container_add (GTK_CONTAINER (window), scrolled_win);
87   gtk_widget_show (scrolled_win);
88   
89   /* Create the root tree */
90   tree = gtk_tree_new ();
91   g_print ("root tree is %p\n", tree);
92   /* connect all GtkTree:: signals */
93   g_signal_connect (G_OBJECT (tree), "select_child",
94                     G_CALLBACK (cb_select_child), tree);
95   g_signal_connect (G_OBJECT (tree), "unselect_child",
96                     G_CALLBACK (cb_unselect_child), tree);
97   g_signal_connect (G_OBJECT(tree), "selection_changed",
98                     G_CALLBACK(cb_selection_changed), tree);
99   /* Add it to the scrolled window */
100   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win),
101                                          tree);
102   /* Set the selection mode */
103   gtk_tree_set_selection_mode (GTK_TREE (tree),
104                                GTK_SELECTION_MULTIPLE);
105   /* Show it */
106   gtk_widget_show (tree);
107
108   for (i = 0; i < 5; i++){
109     GtkWidget *subtree, *item;
110     gint j;
111
112     /* Create a tree item */
113     item = gtk_tree_item_new_with_label (itemnames[i]);
114     /* Connect all GtkItem:: and GtkTreeItem:: signals */
115     g_signal_connect (G_OBJECT (item), "select",
116                       G_CALLBACK (cb_itemsignal), "select");
117     g_signal_connect (G_OBJECT (item), "deselect",
118                       G_CALLBACK (cb_itemsignal), "deselect");
119     g_signal_connect (G_OBJECT (item), "toggle",
120                       G_CALLBACK (cb_itemsignal), "toggle");
121     g_signal_connect (G_OBJECT (item), "expand",
122                       G_CALLBACK (cb_itemsignal), "expand");
123     g_signal_connect (G_OBJECT (item), "collapse",
124                       G_CALLBACK (cb_itemsignal), "collapse");
125     /* Add it to the parent tree */
126     gtk_tree_append (GTK_TREE (tree), item);
127     /* Show it - this can be done at any time */
128     gtk_widget_show (item);
129     /* Create this item's subtree */
130     subtree = gtk_tree_new ();
131     g_print ("-> item %s->%p, subtree %p\n", itemnames[i], item,
132              subtree);
133
134     /* This is still necessary if you want these signals to be called
135        for the subtree's children.  Note that selection_change will be 
136        signalled for the root tree regardless. */
137     g_signal_connect (G_OBJECT (subtree), "select_child",
138                         G_CALLBACK (cb_select_child), subtree);
139     g_signal_connect (G_OBJECT (subtree), "unselect_child",
140                         G_CALLBACK (cb_unselect_child), subtree);
141     /* This has absolutely no effect, because it is completely ignored 
142        in subtrees */
143     gtk_tree_set_selection_mode (GTK_TREE (subtree),
144                                  GTK_SELECTION_SINGLE);
145     /* Neither does this, but for a rather different reason - the
146        view_mode and view_line values of a tree are propagated to
147        subtrees when they are mapped.  So, setting it later on would
148        actually have a (somewhat unpredictable) effect */
149     gtk_tree_set_view_mode (GTK_TREE (subtree), GTK_TREE_VIEW_ITEM);
150     /* Set this item's subtree - note that you cannot do this until
151        AFTER the item has been added to its parent tree! */
152     gtk_tree_item_set_subtree (GTK_TREE_ITEM (item), subtree);
153
154     for (j = 0; j < 5; j++){
155       GtkWidget *subitem;
156
157       /* Create a subtree item, in much the same way */
158       subitem = gtk_tree_item_new_with_label (itemnames[j]);
159       /* Connect all GtkItem:: and GtkTreeItem:: signals */
160       g_signal_connect (G_OBJECT (subitem), "select",
161                           G_CALLBACK (cb_itemsignal), "select");
162       g_signal_connect (G_OBJECT (subitem), "deselect",
163                           G_CALLBACK (cb_itemsignal), "deselect");
164       g_signal_connect (G_OBJECT (subitem), "toggle",
165                           G_CALLBACK (cb_itemsignal), "toggle");
166       g_signal_connect (G_OBJECT (subitem), "expand",
167                           G_CALLBACK (cb_itemsignal), "expand");
168       g_signal_connect (G_OBJECT (subitem), "collapse",
169                           G_CALLBACK (cb_itemsignal), "collapse");
170       g_print ("-> -> item %s->%p\n", itemnames[j], subitem);
171       /* Add it to its parent tree */
172       gtk_tree_append (GTK_TREE (subtree), subitem);
173       /* Show it */
174       gtk_widget_show (subitem);
175     }
176   }
177
178   /* Show the window and loop endlessly */
179   gtk_widget_show (window);
180
181   gtk_main();
182
183   return 0;
184 }