]> Pileus Git - ~andy/gtk/blob - gtk/gtktree.c
Intern type names in code generated by glib-mkenums, too.
[~andy/gtk] / gtk / gtktree.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef GTK_DISABLE_DEPRECATED
28
29 #include <config.h>
30 #include "gtkmain.h"
31 #include "gtkmarshalers.h"
32 #include "gtksignal.h"
33 #include "gtklist.h"
34
35 #define GTK_ENABLE_BROKEN
36 #include "gtktree.h"
37 #include "gtktreeitem.h"
38 #include "gtkalias.h"
39
40 enum {
41   SELECTION_CHANGED,
42   SELECT_CHILD,
43   UNSELECT_CHILD,
44   LAST_SIGNAL
45 };
46
47 static void gtk_tree_class_init      (GtkTreeClass   *klass);
48 static void gtk_tree_init            (GtkTree        *tree);
49 static void gtk_tree_destroy         (GtkObject      *object);
50 static void gtk_tree_map             (GtkWidget      *widget);
51 static void gtk_tree_parent_set      (GtkWidget      *widget,
52                                       GtkWidget      *previous_parent);
53 static void gtk_tree_unmap           (GtkWidget      *widget);
54 static void gtk_tree_realize         (GtkWidget      *widget);
55 static gint gtk_tree_motion_notify   (GtkWidget      *widget,
56                                       GdkEventMotion *event);
57 static gint gtk_tree_button_press    (GtkWidget      *widget,
58                                       GdkEventButton *event);
59 static gint gtk_tree_button_release  (GtkWidget      *widget,
60                                       GdkEventButton *event);
61 static void gtk_tree_size_request    (GtkWidget      *widget,
62                                       GtkRequisition *requisition);
63 static void gtk_tree_size_allocate   (GtkWidget      *widget,
64                                       GtkAllocation  *allocation);
65 static void gtk_tree_add             (GtkContainer   *container,
66                                       GtkWidget      *widget);
67 static void gtk_tree_forall          (GtkContainer   *container,
68                                       gboolean        include_internals,
69                                       GtkCallback     callback,
70                                       gpointer        callback_data);
71
72 static void gtk_real_tree_select_child   (GtkTree       *tree,
73                                           GtkWidget     *child);
74 static void gtk_real_tree_unselect_child (GtkTree       *tree,
75                                           GtkWidget     *child);
76
77 static GtkType gtk_tree_child_type  (GtkContainer   *container);
78
79 static GtkContainerClass *parent_class = NULL;
80 static guint tree_signals[LAST_SIGNAL] = { 0 };
81
82 GtkType
83 gtk_tree_get_type (void)
84 {
85   static GtkType tree_type = 0;
86   
87   if (!tree_type)
88     {
89       static const GtkTypeInfo tree_info =
90       {
91         "GtkTree",
92         sizeof (GtkTree),
93         sizeof (GtkTreeClass),
94         (GtkClassInitFunc) gtk_tree_class_init,
95         (GtkObjectInitFunc) gtk_tree_init,
96         /* reserved_1 */ NULL,
97         /* reserved_2 */ NULL,
98         (GtkClassInitFunc) NULL,
99       };
100       
101       g_intern_static_string ("GtkTree");
102       tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
103     }
104   
105   return tree_type;
106 }
107
108 static void
109 gtk_tree_class_init (GtkTreeClass *class)
110 {
111   GtkObjectClass *object_class;
112   GtkWidgetClass *widget_class;
113   GtkContainerClass *container_class;
114   
115   object_class = (GtkObjectClass*) class;
116   widget_class = (GtkWidgetClass*) class;
117   container_class = (GtkContainerClass*) class;
118   
119   parent_class = gtk_type_class (gtk_container_get_type ());
120   
121   
122   object_class->destroy = gtk_tree_destroy;
123   
124   widget_class->map = gtk_tree_map;
125   widget_class->unmap = gtk_tree_unmap;
126   widget_class->parent_set = gtk_tree_parent_set;
127   widget_class->realize = gtk_tree_realize;
128   widget_class->motion_notify_event = gtk_tree_motion_notify;
129   widget_class->button_press_event = gtk_tree_button_press;
130   widget_class->button_release_event = gtk_tree_button_release;
131   widget_class->size_request = gtk_tree_size_request;
132   widget_class->size_allocate = gtk_tree_size_allocate;
133   
134   container_class->add = gtk_tree_add;
135   container_class->remove = 
136     (void (*)(GtkContainer *, GtkWidget *)) gtk_tree_remove_item;
137   container_class->forall = gtk_tree_forall;
138   container_class->child_type = gtk_tree_child_type;
139   
140   class->selection_changed = NULL;
141   class->select_child = gtk_real_tree_select_child;
142   class->unselect_child = gtk_real_tree_unselect_child;
143
144   tree_signals[SELECTION_CHANGED] =
145     gtk_signal_new ("selection_changed",
146                     GTK_RUN_FIRST,
147                     GTK_CLASS_TYPE (object_class),
148                     GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
149                     _gtk_marshal_VOID__VOID,
150                     GTK_TYPE_NONE, 0);
151   tree_signals[SELECT_CHILD] =
152     gtk_signal_new ("select_child",
153                     GTK_RUN_FIRST,
154                     GTK_CLASS_TYPE (object_class),
155                     GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
156                     _gtk_marshal_VOID__OBJECT,
157                     GTK_TYPE_NONE, 1,
158                     GTK_TYPE_WIDGET);
159   tree_signals[UNSELECT_CHILD] =
160     gtk_signal_new ("unselect_child",
161                     GTK_RUN_FIRST,
162                     GTK_CLASS_TYPE (object_class),
163                     GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
164                     _gtk_marshal_VOID__OBJECT,
165                     GTK_TYPE_NONE, 1,
166                     GTK_TYPE_WIDGET);
167 }
168
169 static GtkType
170 gtk_tree_child_type (GtkContainer     *container)
171 {
172   return GTK_TYPE_TREE_ITEM;
173 }
174
175 static void
176 gtk_tree_init (GtkTree *tree)
177 {
178   tree->children = NULL;
179   tree->root_tree = tree;
180   tree->selection = NULL;
181   tree->tree_owner = NULL;
182   tree->selection_mode = GTK_SELECTION_SINGLE;
183   tree->indent_value = 9;
184   tree->current_indent = 0;
185   tree->level = 0;
186   tree->view_mode = GTK_TREE_VIEW_LINE;
187   tree->view_line = TRUE;
188 }
189
190 GtkWidget*
191 gtk_tree_new (void)
192 {
193   return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
194 }
195
196 void
197 gtk_tree_append (GtkTree   *tree,
198                  GtkWidget *tree_item)
199 {
200   g_return_if_fail (GTK_IS_TREE (tree));
201   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
202   
203   gtk_tree_insert (tree, tree_item, -1);
204 }
205
206 void
207 gtk_tree_prepend (GtkTree   *tree,
208                   GtkWidget *tree_item)
209 {
210   g_return_if_fail (GTK_IS_TREE (tree));
211   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
212   
213   gtk_tree_insert (tree, tree_item, 0);
214 }
215
216 void
217 gtk_tree_insert (GtkTree   *tree,
218                  GtkWidget *tree_item,
219                  gint       position)
220 {
221   gint nchildren;
222   
223   g_return_if_fail (GTK_IS_TREE (tree));
224   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
225   
226   nchildren = g_list_length (tree->children);
227   
228   if ((position < 0) || (position > nchildren))
229     position = nchildren;
230   
231   if (position == nchildren)
232     tree->children = g_list_append (tree->children, tree_item);
233   else
234     tree->children = g_list_insert (tree->children, tree_item, position);
235   
236   gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
237 }
238
239 static void
240 gtk_tree_add (GtkContainer *container,
241               GtkWidget    *child)
242 {
243   GtkTree *tree;
244   
245   g_return_if_fail (GTK_IS_TREE (container));
246   g_return_if_fail (GTK_IS_TREE_ITEM (child));
247   
248   tree = GTK_TREE (container);
249   
250   tree->children = g_list_append (tree->children, child);
251   
252   gtk_widget_set_parent (child, GTK_WIDGET (container));
253   
254   if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
255     gtk_tree_select_child (tree, child);
256 }
257
258 static gint
259 gtk_tree_button_press (GtkWidget      *widget,
260                        GdkEventButton *event)
261 {
262   GtkTree *tree;
263   GtkWidget *item;
264   
265   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
266   g_return_val_if_fail (event != NULL, FALSE);
267   
268   tree = GTK_TREE (widget);
269   item = gtk_get_event_widget ((GdkEvent*) event);
270   
271   while (item && !GTK_IS_TREE_ITEM (item))
272     item = item->parent;
273   
274   if (!item || (item->parent != widget))
275     return FALSE;
276   
277   switch(event->button) 
278     {
279     case 1:
280       gtk_tree_select_child (tree, item);
281       break;
282     case 2:
283       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
284       break;
285     case 3:
286       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
287       break;
288     }
289   
290   return TRUE;
291 }
292
293 static gint
294 gtk_tree_button_release (GtkWidget      *widget,
295                          GdkEventButton *event)
296 {
297   GtkTree *tree;
298   GtkWidget *item;
299   
300   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
301   g_return_val_if_fail (event != NULL, FALSE);
302   
303   tree = GTK_TREE (widget);
304   item = gtk_get_event_widget ((GdkEvent*) event);
305   
306   return TRUE;
307 }
308
309 gint
310 gtk_tree_child_position (GtkTree   *tree,
311                          GtkWidget *child)
312 {
313   GList *children;
314   gint pos;
315   
316   
317   g_return_val_if_fail (GTK_IS_TREE (tree), -1);
318   g_return_val_if_fail (child != NULL, -1);
319   
320   pos = 0;
321   children = tree->children;
322   
323   while (children)
324     {
325       if (child == GTK_WIDGET (children->data)) 
326         return pos;
327       
328       pos += 1;
329       children = children->next;
330     }
331   
332   
333   return -1;
334 }
335
336 void
337 gtk_tree_clear_items (GtkTree *tree,
338                       gint     start,
339                       gint     end)
340 {
341   GtkWidget *widget;
342   GList *clear_list;
343   GList *tmp_list;
344   guint nchildren;
345   guint index;
346   
347   g_return_if_fail (GTK_IS_TREE (tree));
348   
349   nchildren = g_list_length (tree->children);
350   
351   if (nchildren > 0)
352     {
353       if ((end < 0) || (end > nchildren))
354         end = nchildren;
355       
356       if (start >= end)
357         return;
358       
359       tmp_list = g_list_nth (tree->children, start);
360       clear_list = NULL;
361       index = start;
362       while (tmp_list && index <= end)
363         {
364           widget = tmp_list->data;
365           tmp_list = tmp_list->next;
366           index++;
367           
368           clear_list = g_list_prepend (clear_list, widget);
369         }
370       
371       gtk_tree_remove_items (tree, clear_list);
372     }
373 }
374
375 static void
376 gtk_tree_destroy (GtkObject *object)
377 {
378   GtkTree *tree;
379   GtkWidget *child;
380   GList *children;
381   
382   g_return_if_fail (GTK_IS_TREE (object));
383   
384   tree = GTK_TREE (object);
385   
386   children = tree->children;
387   while (children)
388     {
389       child = children->data;
390       children = children->next;
391       
392       gtk_widget_ref (child);
393       gtk_widget_unparent (child);
394       gtk_widget_destroy (child);
395       gtk_widget_unref (child);
396     }
397   
398   g_list_free (tree->children);
399   tree->children = NULL;
400   
401   if (tree->root_tree == tree)
402     {
403       GList *node;
404       for (node = tree->selection; node; node = node->next)
405         gtk_widget_unref ((GtkWidget *)node->data);
406       g_list_free (tree->selection);
407       tree->selection = NULL;
408     }
409   
410   if (GTK_OBJECT_CLASS (parent_class)->destroy)
411     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
412 }
413
414 static void
415 gtk_tree_forall (GtkContainer *container,
416                  gboolean      include_internals,
417                  GtkCallback   callback,
418                  gpointer      callback_data)
419 {
420   GtkTree *tree;
421   GtkWidget *child;
422   GList *children;
423   
424   
425   g_return_if_fail (GTK_IS_TREE (container));
426   g_return_if_fail (callback != NULL);
427   
428   tree = GTK_TREE (container);
429   children = tree->children;
430   
431   while (children)
432     {
433       child = children->data;
434       children = children->next;
435       
436       (* callback) (child, callback_data);
437     }
438 }
439
440 static void
441 gtk_tree_unselect_all (GtkTree *tree)
442 {
443   GList *tmp_list, *selection;
444   GtkWidget *tmp_item;
445       
446   selection = tree->selection;
447   tree->selection = NULL;
448
449   tmp_list = selection;
450   while (tmp_list)
451     {
452       tmp_item = selection->data;
453
454       if (tmp_item->parent &&
455           GTK_IS_TREE (tmp_item->parent) &&
456           GTK_TREE (tmp_item->parent)->root_tree == tree)
457         gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
458
459       gtk_widget_unref (tmp_item);
460
461       tmp_list = tmp_list->next;
462     }
463
464   g_list_free (selection);
465 }
466
467 static void
468 gtk_tree_parent_set (GtkWidget *widget,
469                      GtkWidget *previous_parent)
470 {
471   GtkTree *tree = GTK_TREE (widget);
472   GtkWidget *child;
473   GList *children;
474   
475   if (widget->parent && GTK_IS_TREE (widget->parent))
476     {
477       gtk_tree_unselect_all (tree);
478       
479       /* set root tree for this tree */
480       tree->root_tree = GTK_TREE(widget->parent)->root_tree;
481       
482       tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
483       tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
484       tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent + 
485         tree->indent_value;
486       tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
487       tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
488     }
489   else
490     {
491       tree->root_tree = tree;
492       
493       tree->level = 0;
494       tree->current_indent = 0;
495     }
496
497   children = tree->children;
498   while (children)
499     {
500       child = children->data;
501       children = children->next;
502       
503       if (GTK_TREE_ITEM (child)->subtree)
504         gtk_tree_parent_set (GTK_TREE_ITEM (child)->subtree, child);
505     }
506 }
507
508 static void
509 gtk_tree_map (GtkWidget *widget)
510 {
511   GtkTree *tree = GTK_TREE (widget);
512   GtkWidget *child;
513   GList *children;
514   
515   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
516   
517   children = tree->children;
518   while (children)
519     {
520       child = children->data;
521       children = children->next;
522       
523       if (GTK_WIDGET_VISIBLE (child) &&
524           !GTK_WIDGET_MAPPED (child))
525         gtk_widget_map (child);
526       
527       if (GTK_TREE_ITEM (child)->subtree)
528         {
529           child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
530           
531           if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
532             gtk_widget_map (child);
533         }
534     }
535
536   gdk_window_show (widget->window);
537 }
538
539 static gint
540 gtk_tree_motion_notify (GtkWidget      *widget,
541                         GdkEventMotion *event)
542 {
543   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
544   g_return_val_if_fail (event != NULL, FALSE);
545   
546 #ifdef TREE_DEBUG
547   g_message("gtk_tree_motion_notify\n");
548 #endif /* TREE_DEBUG */
549   
550   return FALSE;
551 }
552
553 static void
554 gtk_tree_realize (GtkWidget *widget)
555 {
556   GdkWindowAttr attributes;
557   gint attributes_mask;
558   
559   
560   g_return_if_fail (GTK_IS_TREE (widget));
561   
562   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
563   
564   attributes.window_type = GDK_WINDOW_CHILD;
565   attributes.x = widget->allocation.x;
566   attributes.y = widget->allocation.y;
567   attributes.width = widget->allocation.width;
568   attributes.height = widget->allocation.height;
569   attributes.wclass = GDK_INPUT_OUTPUT;
570   attributes.visual = gtk_widget_get_visual (widget);
571   attributes.colormap = gtk_widget_get_colormap (widget);
572   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
573   
574   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
575   
576   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
577   gdk_window_set_user_data (widget->window, widget);
578   
579   widget->style = gtk_style_attach (widget->style, widget->window);
580   gdk_window_set_background (widget->window, 
581                              &widget->style->base[GTK_STATE_NORMAL]);
582 }
583
584 void
585 gtk_tree_remove_item (GtkTree      *container,
586                       GtkWidget    *widget)
587 {
588   GList *item_list;
589   
590   g_return_if_fail (GTK_IS_TREE (container));
591   g_return_if_fail (widget != NULL);
592   g_return_if_fail (container == GTK_TREE (widget->parent));
593   
594   item_list = g_list_append (NULL, widget);
595   
596   gtk_tree_remove_items (GTK_TREE (container), item_list);
597   
598   g_list_free (item_list);
599 }
600
601 /* used by gtk_tree_remove_items to make the function independent of
602    order in list of items to remove.
603    Sort item by depth in tree */
604 static gint 
605 gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
606 {
607   if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
608     return 1;
609   if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
610     return -1;
611   
612   return 0;
613 }
614
615 void
616 gtk_tree_remove_items (GtkTree *tree,
617                        GList   *items)
618 {
619   GtkWidget *widget;
620   GList *selected_widgets;
621   GList *tmp_list;
622   GList *sorted_list;
623   GtkTree *real_tree;
624   GtkTree *root_tree;
625   
626   g_return_if_fail (GTK_IS_TREE (tree));
627   
628 #ifdef TREE_DEBUG
629   g_message("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
630 #endif /* TREE_DEBUG */
631   
632   /* We may not yet be mapped, so we actively have to find our
633    * root tree
634    */
635   if (tree->root_tree)
636     root_tree = tree->root_tree;
637   else
638     {
639       GtkWidget *tmp = GTK_WIDGET (tree);
640       while (tmp->parent && GTK_IS_TREE (tmp->parent))
641         tmp = tmp->parent;
642       
643       root_tree = GTK_TREE (tmp);
644     }
645   
646   tmp_list = items;
647   selected_widgets = NULL;
648   sorted_list = NULL;
649   widget = NULL;
650   
651 #ifdef TREE_DEBUG
652   g_message("* sort list by depth\n");
653 #endif /* TREE_DEBUG */
654   
655   while (tmp_list)
656     {
657       
658 #ifdef TREE_DEBUG
659       g_message ("* item [%#x] depth [%d]\n", 
660                  (int)tmp_list->data,
661                  (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
662 #endif /* TREE_DEBUG */
663       
664       sorted_list = g_list_insert_sorted(sorted_list,
665                                          tmp_list->data,
666                                          (GCompareFunc)gtk_tree_sort_item_by_depth);
667       tmp_list = g_list_next(tmp_list);
668     }
669   
670 #ifdef TREE_DEBUG
671   /* print sorted list */
672   g_message("* sorted list result\n");
673   tmp_list = sorted_list;
674   while(tmp_list)
675     {
676       g_message("* item [%#x] depth [%d]\n", 
677                 (int)tmp_list->data,
678                 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
679       tmp_list = g_list_next(tmp_list);
680     }
681 #endif /* TREE_DEBUG */
682   
683 #ifdef TREE_DEBUG
684   g_message("* scan sorted list\n");
685 #endif /* TREE_DEBUG */
686   
687   tmp_list = sorted_list;
688   while (tmp_list)
689     {
690       widget = tmp_list->data;
691       tmp_list = tmp_list->next;
692       
693 #ifdef TREE_DEBUG
694       g_message("* item [%#x] subtree [%#x]\n", 
695                 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
696 #endif /* TREE_DEBUG */
697       
698       /* get real owner of this widget */
699       real_tree = GTK_TREE(widget->parent);
700 #ifdef TREE_DEBUG
701       g_message("* subtree having this widget [%#x]\n", (int)real_tree);
702 #endif /* TREE_DEBUG */
703       
704       
705       if (widget->state == GTK_STATE_SELECTED)
706         {
707           selected_widgets = g_list_prepend (selected_widgets, widget);
708 #ifdef TREE_DEBUG
709           g_message("* selected widget - adding it in selected list [%#x]\n",
710                     (int)selected_widgets);
711 #endif /* TREE_DEBUG */
712         }
713       
714       /* remove this item from its real parent */
715 #ifdef TREE_DEBUG
716       g_message("* remove widget from its owner tree\n");
717 #endif /* TREE_DEBUG */
718       real_tree->children = g_list_remove (real_tree->children, widget);
719       
720       /* remove subtree associate at this item if it exist */      
721       if(GTK_TREE_ITEM(widget)->subtree) 
722         {
723 #ifdef TREE_DEBUG
724           g_message("* remove subtree associate at this item [%#x]\n",
725                     (int) GTK_TREE_ITEM(widget)->subtree);
726 #endif /* TREE_DEBUG */
727           if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
728             gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
729           
730           gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
731           GTK_TREE_ITEM(widget)->subtree = NULL;
732         }
733       
734       /* really remove widget for this item */
735 #ifdef TREE_DEBUG
736       g_message("* unmap and unparent widget [%#x]\n", (int)widget);
737 #endif /* TREE_DEBUG */
738       if (GTK_WIDGET_MAPPED (widget))
739         gtk_widget_unmap (widget);
740       
741       gtk_widget_unparent (widget);
742       
743       /* delete subtree if there is no children in it */
744       if(real_tree->children == NULL && 
745          real_tree != root_tree)
746         {
747 #ifdef TREE_DEBUG
748           g_message("* owner tree don't have children ... destroy it\n");
749 #endif /* TREE_DEBUG */
750           gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
751         }
752       
753 #ifdef TREE_DEBUG
754       g_message("* next item in list\n");
755 #endif /* TREE_DEBUG */
756     }
757   
758   if (selected_widgets)
759     {
760 #ifdef TREE_DEBUG
761       g_message("* scan selected item list\n");
762 #endif /* TREE_DEBUG */
763       tmp_list = selected_widgets;
764       while (tmp_list)
765         {
766           widget = tmp_list->data;
767           tmp_list = tmp_list->next;
768           
769 #ifdef TREE_DEBUG
770           g_message("* widget [%#x] subtree [%#x]\n", 
771                     (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
772 #endif /* TREE_DEBUG */
773           
774           /* remove widget of selection */
775           root_tree->selection = g_list_remove (root_tree->selection, widget);
776           
777           /* unref it to authorize is destruction */
778           gtk_widget_unref (widget);
779         }
780       
781       /* emit only one selection_changed signal */
782       gtk_signal_emit (GTK_OBJECT (root_tree), 
783                        tree_signals[SELECTION_CHANGED]);
784     }
785   
786 #ifdef TREE_DEBUG
787   g_message("* free selected_widgets list\n");
788 #endif /* TREE_DEBUG */
789   g_list_free (selected_widgets);
790   g_list_free (sorted_list);
791   
792   if (root_tree->children && !root_tree->selection &&
793       (root_tree->selection_mode == GTK_SELECTION_BROWSE))
794     {
795 #ifdef TREE_DEBUG
796       g_message("* BROWSE mode, select another item\n");
797 #endif /* TREE_DEBUG */
798       widget = root_tree->children->data;
799       gtk_tree_select_child (root_tree, widget);
800     }
801   
802   if (GTK_WIDGET_VISIBLE (root_tree))
803     {
804 #ifdef TREE_DEBUG
805       g_message("* query queue resizing for root_tree\n");
806 #endif /* TREE_DEBUG */      
807       gtk_widget_queue_resize (GTK_WIDGET (root_tree));
808     }
809 }
810
811 void
812 gtk_tree_select_child (GtkTree   *tree,
813                        GtkWidget *tree_item)
814 {
815   g_return_if_fail (GTK_IS_TREE (tree));
816   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
817   
818   gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], tree_item);
819 }
820
821 void
822 gtk_tree_select_item (GtkTree   *tree,
823                       gint       item)
824 {
825   GList *tmp_list;
826   
827   g_return_if_fail (GTK_IS_TREE (tree));
828   
829   tmp_list = g_list_nth (tree->children, item);
830   if (tmp_list)
831     gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
832   
833 }
834
835 static void
836 gtk_tree_size_allocate (GtkWidget     *widget,
837                         GtkAllocation *allocation)
838 {
839   GtkTree *tree;
840   GtkWidget *child, *subtree;
841   GtkAllocation child_allocation;
842   GList *children;
843   
844   
845   g_return_if_fail (GTK_IS_TREE (widget));
846   g_return_if_fail (allocation != NULL);
847   
848   tree = GTK_TREE (widget);
849   
850   widget->allocation = *allocation;
851   if (GTK_WIDGET_REALIZED (widget))
852     gdk_window_move_resize (widget->window,
853                             allocation->x, allocation->y,
854                             allocation->width, allocation->height);
855   
856   if (tree->children)
857     {
858       child_allocation.x = GTK_CONTAINER (tree)->border_width;
859       child_allocation.y = GTK_CONTAINER (tree)->border_width;
860       child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
861       
862       children = tree->children;
863       
864       while (children)
865         {
866           child = children->data;
867           children = children->next;
868           
869           if (GTK_WIDGET_VISIBLE (child))
870             {
871               GtkRequisition child_requisition;
872               gtk_widget_get_child_requisition (child, &child_requisition);
873               
874               child_allocation.height = child_requisition.height;
875               
876               gtk_widget_size_allocate (child, &child_allocation);
877               
878               child_allocation.y += child_allocation.height;
879               
880               if((subtree = GTK_TREE_ITEM(child)->subtree))
881                 if(GTK_WIDGET_VISIBLE (subtree))
882                   {
883                     child_allocation.height = subtree->requisition.height;
884                     gtk_widget_size_allocate (subtree, &child_allocation);
885                     child_allocation.y += child_allocation.height;
886                   }
887             }
888         }
889     }
890   
891 }
892
893 static void
894 gtk_tree_size_request (GtkWidget      *widget,
895                        GtkRequisition *requisition)
896 {
897   GtkTree *tree;
898   GtkWidget *child, *subtree;
899   GList *children;
900   GtkRequisition child_requisition;
901   
902   
903   g_return_if_fail (GTK_IS_TREE (widget));
904   g_return_if_fail (requisition != NULL);
905   
906   tree = GTK_TREE (widget);
907   requisition->width = 0;
908   requisition->height = 0;
909   
910   children = tree->children;
911   while (children)
912     {
913       child = children->data;
914       children = children->next;
915       
916       if (GTK_WIDGET_VISIBLE (child))
917         {
918           gtk_widget_size_request (child, &child_requisition);
919           
920           requisition->width = MAX (requisition->width, child_requisition.width);
921           requisition->height += child_requisition.height;
922           
923           if((subtree = GTK_TREE_ITEM(child)->subtree) &&
924              GTK_WIDGET_VISIBLE (subtree))
925             {
926               gtk_widget_size_request (subtree, &child_requisition);
927               
928               requisition->width = MAX (requisition->width, 
929                                         child_requisition.width);
930               
931               requisition->height += child_requisition.height;
932             }
933         }
934     }
935   
936   requisition->width += GTK_CONTAINER (tree)->border_width * 2;
937   requisition->height += GTK_CONTAINER (tree)->border_width * 2;
938   
939   requisition->width = MAX (requisition->width, 1);
940   requisition->height = MAX (requisition->height, 1);
941   
942 }
943
944 static void
945 gtk_tree_unmap (GtkWidget *widget)
946 {
947   
948   g_return_if_fail (GTK_IS_TREE (widget));
949   
950   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
951   gdk_window_hide (widget->window);
952   
953 }
954
955 void
956 gtk_tree_unselect_child (GtkTree   *tree,
957                          GtkWidget *tree_item)
958 {
959   g_return_if_fail (GTK_IS_TREE (tree));
960   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
961   
962   gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
963 }
964
965 void
966 gtk_tree_unselect_item (GtkTree *tree,
967                         gint     item)
968 {
969   GList *tmp_list;
970   
971   g_return_if_fail (GTK_IS_TREE (tree));
972   
973   tmp_list = g_list_nth (tree->children, item);
974   if (tmp_list)
975     gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
976   
977 }
978
979 static void
980 gtk_real_tree_select_child (GtkTree   *tree,
981                             GtkWidget *child)
982 {
983   GList *selection, *root_selection;
984   GList *tmp_list;
985   GtkWidget *tmp_item;
986   
987   g_return_if_fail (GTK_IS_TREE (tree));
988   g_return_if_fail (GTK_IS_TREE_ITEM (child));
989
990   root_selection = tree->root_tree->selection;
991   
992   switch (tree->root_tree->selection_mode)
993     {
994     case GTK_SELECTION_SINGLE:
995       
996       selection = root_selection;
997       
998       /* remove old selection list */
999       while (selection)
1000         {
1001           tmp_item = selection->data;
1002           
1003           if (tmp_item != child)
1004             {
1005               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1006               
1007               tmp_list = selection;
1008               selection = selection->next;
1009               
1010               root_selection = g_list_remove_link (root_selection, tmp_list);
1011               gtk_widget_unref (tmp_item);
1012               
1013               g_list_free (tmp_list);
1014             }
1015           else
1016             selection = selection->next;
1017         }
1018       
1019       if (child->state == GTK_STATE_NORMAL)
1020         {
1021           gtk_tree_item_select (GTK_TREE_ITEM (child));
1022           root_selection = g_list_prepend (root_selection, child);
1023           gtk_widget_ref (child);
1024         }
1025       else if (child->state == GTK_STATE_SELECTED)
1026         {
1027           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1028           root_selection = g_list_remove (root_selection, child);
1029           gtk_widget_unref (child);
1030         }
1031       
1032       tree->root_tree->selection = root_selection;
1033       
1034       gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1035                        tree_signals[SELECTION_CHANGED]);
1036       break;
1037       
1038       
1039     case GTK_SELECTION_BROWSE:
1040       selection = root_selection;
1041       
1042       while (selection)
1043         {
1044           tmp_item = selection->data;
1045           
1046           if (tmp_item != child)
1047             {
1048               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1049               
1050               tmp_list = selection;
1051               selection = selection->next;
1052               
1053               root_selection = g_list_remove_link (root_selection, tmp_list);
1054               gtk_widget_unref (tmp_item);
1055               
1056               g_list_free (tmp_list);
1057             }
1058           else
1059             selection = selection->next;
1060         }
1061       
1062       tree->root_tree->selection = root_selection;
1063       
1064       if (child->state == GTK_STATE_NORMAL)
1065         {
1066           gtk_tree_item_select (GTK_TREE_ITEM (child));
1067           root_selection = g_list_prepend (root_selection, child);
1068           gtk_widget_ref (child);
1069           tree->root_tree->selection = root_selection;
1070           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1071                            tree_signals[SELECTION_CHANGED]);
1072         }
1073       break;
1074       
1075     case GTK_SELECTION_MULTIPLE:
1076       break;
1077     }
1078 }
1079
1080 static void
1081 gtk_real_tree_unselect_child (GtkTree   *tree,
1082                               GtkWidget *child)
1083 {
1084   g_return_if_fail (GTK_IS_TREE (tree));
1085   g_return_if_fail (GTK_IS_TREE_ITEM (child));
1086   
1087   switch (tree->selection_mode)
1088     {
1089     case GTK_SELECTION_SINGLE:
1090     case GTK_SELECTION_BROWSE:
1091       if (child->state == GTK_STATE_SELECTED)
1092         {
1093           GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1094           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1095           root_tree->selection = g_list_remove (root_tree->selection, child);
1096           gtk_widget_unref (child);
1097           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1098                            tree_signals[SELECTION_CHANGED]);
1099         }
1100       break;
1101       
1102     case GTK_SELECTION_MULTIPLE:
1103       break;
1104     }
1105 }
1106
1107 void
1108 gtk_tree_set_selection_mode (GtkTree       *tree,
1109                              GtkSelectionMode mode) 
1110 {
1111   g_return_if_fail (GTK_IS_TREE (tree));
1112   
1113   tree->selection_mode = mode;
1114 }
1115
1116 void
1117 gtk_tree_set_view_mode (GtkTree       *tree,
1118                         GtkTreeViewMode mode) 
1119 {
1120   g_return_if_fail (GTK_IS_TREE (tree));
1121   
1122   tree->view_mode = mode;
1123 }
1124
1125 void
1126 gtk_tree_set_view_lines (GtkTree       *tree,
1127                          gboolean       flag) 
1128 {
1129   g_return_if_fail (GTK_IS_TREE (tree));
1130   
1131   tree->view_line = flag;
1132 }
1133
1134 #define __GTK_TREE_C__
1135 #include "gtkaliasdef.c"