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