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