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