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