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