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