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