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