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