]> Pileus Git - ~andy/gtk/blob - gtk/gtktree.c
More extensive debugging output
[~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 guint 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 *tree_item)
185 {
186   g_return_if_fail (tree != NULL);
187   g_return_if_fail (GTK_IS_TREE (tree));
188   g_return_if_fail (tree_item != NULL);
189   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
190
191   gtk_tree_insert(tree, tree_item, -1);
192 }
193
194 void
195 gtk_tree_prepend (GtkTree   *tree,
196                   GtkWidget *tree_item)
197 {
198   g_return_if_fail (tree != NULL);
199   g_return_if_fail (GTK_IS_TREE (tree));
200   g_return_if_fail (tree_item != NULL);
201   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
202
203   gtk_tree_insert(tree, tree_item, 0);
204 }
205
206 void
207 gtk_tree_insert (GtkTree   *tree,
208                  GtkWidget *tree_item,
209                  gint       position)
210 {
211   gint nchildren;
212     
213   g_return_if_fail (tree != NULL);
214   g_return_if_fail (GTK_IS_TREE (tree));
215   g_return_if_fail (tree_item != NULL);
216   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
217
218   /* set parent widget to item */
219   gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
220     
221   if (GTK_WIDGET_VISIBLE (tree_item->parent))
222     {
223       if (GTK_WIDGET_REALIZED (tree_item->parent) &&
224           !GTK_WIDGET_REALIZED (tree_item))
225         gtk_widget_realize (tree_item);
226
227       if (GTK_WIDGET_MAPPED (tree_item->parent) &&
228           !GTK_WIDGET_MAPPED (tree_item))
229         gtk_widget_map (tree_item);
230     }
231
232   nchildren = g_list_length (tree->children);
233     
234   if ((position < 0) || (position > nchildren))
235     position = nchildren;
236
237   if (position == nchildren)
238     {
239       tree->children = g_list_append(tree->children, tree_item);
240     }
241   else
242     {
243       tree->children = g_list_insert(tree->children, tree_item, position);
244     }
245     
246   if (GTK_WIDGET_VISIBLE (tree))
247     gtk_widget_queue_resize (GTK_WIDGET (tree));
248
249 }
250
251 static void
252 gtk_tree_add (GtkContainer *container,
253               GtkWidget    *widget)
254 {
255   GtkTree *tree;
256
257   g_return_if_fail (container != NULL);
258   g_return_if_fail (GTK_IS_TREE (container));
259   g_return_if_fail (widget != NULL);
260   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
261
262   tree = GTK_TREE (container);
263
264   gtk_widget_set_parent (widget, GTK_WIDGET (container));
265   if (GTK_WIDGET_VISIBLE (widget->parent))
266     {
267       if (GTK_WIDGET_REALIZED (widget->parent) &&
268           !GTK_WIDGET_REALIZED (widget))
269         gtk_widget_realize (widget);
270
271       if (GTK_WIDGET_MAPPED (widget->parent) &&
272           !GTK_WIDGET_MAPPED (widget))
273         gtk_widget_map (widget);
274     }
275
276   tree->children = g_list_append (tree->children, widget);
277
278   if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
279     {
280       gtk_tree_select_child (tree, widget);
281     }
282
283   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
284     gtk_widget_queue_resize (widget);
285
286 }
287
288 static gint
289 gtk_tree_button_press (GtkWidget      *widget,
290                        GdkEventButton *event)
291 {
292   GtkTree *tree;
293   GtkWidget *item;
294
295   g_return_val_if_fail (widget != NULL, FALSE);
296   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
297   g_return_val_if_fail (event != NULL, FALSE);
298
299   tree = GTK_TREE (widget);
300   item = gtk_get_event_widget ((GdkEvent*) event);
301
302   while (item && !GTK_IS_TREE_ITEM (item))
303     item = item->parent;
304
305   if (!item || (item->parent != widget))
306     return FALSE;
307   
308   switch(event->button) 
309     {
310     case 1:
311       gtk_tree_select_child (tree, item);
312       break;
313     case 2:
314       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
315       break;
316     case 3:
317       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
318       break;
319     }
320
321   return TRUE;
322 }
323
324 static gint
325 gtk_tree_button_release (GtkWidget      *widget,
326                          GdkEventButton *event)
327 {
328   GtkTree *tree;
329   GtkWidget *item;
330
331   g_return_val_if_fail (widget != NULL, FALSE);
332   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
333   g_return_val_if_fail (event != NULL, FALSE);
334
335   tree = GTK_TREE (widget);
336   item = gtk_get_event_widget ((GdkEvent*) event);
337
338   return TRUE;
339 }
340
341 gint
342 gtk_tree_child_position (GtkTree   *tree,
343                          GtkWidget *child)
344 {
345   GList *children;
346   gint pos;
347
348
349   g_return_val_if_fail (tree != NULL, -1);
350   g_return_val_if_fail (GTK_IS_TREE (tree), -1);
351   g_return_val_if_fail (child != NULL, -1);
352
353   pos = 0;
354   children = tree->children;
355
356   while (children)
357     {
358       if (child == GTK_WIDGET (children->data)) 
359         return pos;
360
361       pos += 1;
362       children = children->next;
363     }
364
365
366   return -1;
367 }
368
369 void
370 gtk_tree_clear_items (GtkTree *tree,
371                       gint     start,
372                       gint     end)
373 {
374   GtkWidget *widget;
375   GList *clear_list;
376   GList *tmp_list;
377   guint nchildren;
378   guint index;
379   
380   g_return_if_fail (tree != NULL);
381   g_return_if_fail (GTK_IS_TREE (tree));
382   
383   nchildren = g_list_length (tree->children);
384   
385   if (nchildren > 0)
386     {
387       if ((end < 0) || (end > nchildren))
388         end = nchildren;
389       
390       if (start >= end)
391         return;
392       
393       tmp_list = g_list_nth (tree->children, start);
394       clear_list = NULL;
395       index = start;
396       while (tmp_list && index <= end)
397         {
398           widget = tmp_list->data;
399           tmp_list = tmp_list->next;
400           index++;
401           
402           clear_list = g_list_prepend (clear_list, widget);
403         }
404       
405       gtk_tree_remove_items (tree, clear_list);
406     }
407 }
408
409 static void
410 gtk_tree_destroy (GtkObject *object)
411 {
412   GtkTree *tree;
413   GtkWidget *child;
414   GList *children;
415
416   g_return_if_fail (object != NULL);
417   g_return_if_fail (GTK_IS_TREE (object));
418
419   tree = GTK_TREE (object);
420
421   children = tree->children;
422   while (children)
423     {
424       child = children->data;
425       children = children->next;
426       
427       gtk_widget_ref (child);
428       gtk_widget_unparent (child);
429       gtk_widget_destroy (child);
430       gtk_widget_unref (child);
431     }
432
433   g_list_free (tree->children);
434   tree->children = NULL;
435
436   if (tree->root_tree == tree)
437     {
438       GList *node;
439       for (node = tree->selection; node; node = node->next)
440         gtk_widget_unref ((GtkWidget *)node->data);
441       g_list_free (tree->selection);
442       tree->selection = NULL;
443     }
444
445   if (GTK_OBJECT_CLASS (parent_class)->destroy)
446     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
447 }
448
449 static void
450 gtk_tree_draw (GtkWidget    *widget,
451                GdkRectangle *area)
452 {
453   GtkTree *tree;
454   GtkWidget *subtree;
455   GtkWidget *child;
456   GdkRectangle child_area;
457   GList *children;
458
459
460   g_return_if_fail (widget != NULL);
461   g_return_if_fail (GTK_IS_TREE (widget));
462   g_return_if_fail (area != NULL);
463
464   if (GTK_WIDGET_DRAWABLE (widget))
465     {
466       tree = GTK_TREE (widget);
467
468       children = tree->children;
469       while (children)
470         {
471           child = children->data;
472           children = children->next;
473
474           if (gtk_widget_intersect (child, area, &child_area))
475             gtk_widget_draw (child, &child_area);
476
477           if((subtree = GTK_TREE_ITEM(child)->subtree) &&
478              GTK_WIDGET_VISIBLE(subtree) &&
479              gtk_widget_intersect (subtree, area, &child_area))
480             gtk_widget_draw (subtree, &child_area);
481         }
482     }
483
484 }
485
486 static gint
487 gtk_tree_expose (GtkWidget      *widget,
488                  GdkEventExpose *event)
489 {
490   GtkTree *tree;
491   GtkWidget *child;
492   GdkEventExpose child_event;
493   GList *children;
494
495
496   g_return_val_if_fail (widget != NULL, FALSE);
497   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
498   g_return_val_if_fail (event != NULL, FALSE);
499
500   if (GTK_WIDGET_DRAWABLE (widget))
501     {
502       tree = GTK_TREE (widget);
503
504       child_event = *event;
505
506       children = tree->children;
507       while (children)
508         {
509           child = children->data;
510           children = children->next;
511
512           if (GTK_WIDGET_NO_WINDOW (child) &&
513               gtk_widget_intersect (child, &event->area, &child_event.area))
514             gtk_widget_event (child, (GdkEvent*) &child_event);
515         }
516     }
517
518
519   return FALSE;
520 }
521
522 static void
523 gtk_tree_foreach (GtkContainer *container,
524                   GtkCallback   callback,
525                   gpointer      callback_data)
526 {
527   GtkTree *tree;
528   GtkWidget *child;
529   GList *children;
530
531
532   g_return_if_fail (container != NULL);
533   g_return_if_fail (GTK_IS_TREE (container));
534   g_return_if_fail (callback != NULL);
535
536   tree = GTK_TREE (container);
537   children = tree->children;
538
539   while (children)
540     {
541       child = children->data;
542       children = children->next;
543
544       (* callback) (child, callback_data);
545
546       if(GTK_TREE_ITEM(child)->subtree)
547         (* callback)(GTK_TREE_ITEM(child)->subtree, 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   gdk_window_show (widget->window);
566
567   if(GTK_IS_TREE(widget->parent)) 
568     {
569       /* set root tree for this tree */
570       tree->root_tree = GTK_TREE(widget->parent)->root_tree;
571
572       tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
573       tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
574       tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent + 
575         tree->indent_value;
576       tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
577       tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
578     } 
579   else
580     tree->root_tree = tree;
581
582   children = tree->children;
583   while (children)
584     {
585       child = children->data;
586       children = children->next;
587
588       if (GTK_WIDGET_VISIBLE (child) &&
589           !GTK_WIDGET_MAPPED (child))
590         gtk_widget_map (child);
591
592       if (GTK_TREE_ITEM (child)->subtree)
593         {
594           child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
595
596           if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
597             gtk_widget_map (child);
598         }
599     }
600 }
601
602 static void
603 gtk_tree_marshal_signal (GtkObject      *object,
604                          GtkSignalFunc   func,
605                          gpointer        func_data,
606                          GtkArg         *args)
607 {
608   GtkTreeSignal rfunc;
609
610   rfunc = (GtkTreeSignal) func;
611
612   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
613 }
614
615 static gint
616 gtk_tree_motion_notify (GtkWidget      *widget,
617                         GdkEventMotion *event)
618 {
619   g_return_val_if_fail (widget != NULL, FALSE);
620   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
621   g_return_val_if_fail (event != NULL, FALSE);
622
623 #ifdef TREE_DEBUG
624   g_print("gtk_tree_motion_notify\n");
625 #endif /* TREE_DEBUG */
626
627   return FALSE;
628 }
629
630 static void
631 gtk_tree_realize (GtkWidget *widget)
632 {
633   GdkWindowAttr attributes;
634   gint attributes_mask;
635
636
637   g_return_if_fail (widget != NULL);
638   g_return_if_fail (GTK_IS_TREE (widget));
639
640   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
641
642   attributes.window_type = GDK_WINDOW_CHILD;
643   attributes.x = widget->allocation.x;
644   attributes.y = widget->allocation.y;
645   attributes.width = widget->allocation.width;
646   attributes.height = widget->allocation.height;
647   attributes.wclass = GDK_INPUT_OUTPUT;
648   attributes.visual = gtk_widget_get_visual (widget);
649   attributes.colormap = gtk_widget_get_colormap (widget);
650   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
651
652   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
653
654   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
655   gdk_window_set_user_data (widget->window, widget);
656
657   widget->style = gtk_style_attach (widget->style, widget->window);
658   gdk_window_set_background (widget->window, 
659                              &widget->style->base[GTK_STATE_NORMAL]);
660 }
661
662 void
663 gtk_tree_remove_item (GtkTree      *container,
664                       GtkWidget    *widget)
665 {
666   GList *item_list;
667
668   g_return_if_fail (container != NULL);
669   g_return_if_fail (GTK_IS_TREE (container));
670   g_return_if_fail (widget != NULL);
671   g_return_if_fail (container == GTK_TREE (widget->parent));
672
673   item_list = g_list_append (NULL, widget);
674   
675   gtk_tree_remove_items (GTK_TREE (container), item_list);
676
677   g_list_free (item_list);
678 }
679
680 /* used by gtk_tree_remove_items to make the function independant of
681    order in list of items to remove.
682    Sort item bu depth in tree */
683 static gint 
684 gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
685 {
686   if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
687     return 1;
688   if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
689     return -1;
690
691   return 0;
692 }
693
694 void
695 gtk_tree_remove_items (GtkTree *tree,
696                        GList   *items)
697 {
698   GtkWidget *widget;
699   GList *selected_widgets;
700   GList *tmp_list;
701   GList *sorted_list;
702   GtkTree *real_tree;
703   GtkTree *root_tree;
704
705   g_return_if_fail (tree != NULL);
706   g_return_if_fail (GTK_IS_TREE (tree));
707
708 #ifdef TREE_DEBUG
709   g_print("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
710 #endif /* TREE_DEBUG */
711
712   root_tree = GTK_TREE(GTK_TREE_ROOT_TREE(tree));
713   tmp_list = items;
714   selected_widgets = NULL;
715   sorted_list = NULL;
716   widget = NULL;
717
718 #ifdef TREE_DEBUG
719   g_print("* sort list by depth\n");
720 #endif /* TREE_DEBUG */
721
722   while (tmp_list)
723     {
724
725 #ifdef TREE_DEBUG
726       g_print("* 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_print("* sorted list result\n");
740   tmp_list = sorted_list;
741   while(tmp_list)
742     {
743       g_print("* 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_print("* 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_print("* 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_print("* 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_print("* selected widget - adding it in selected list [%#x]\n",
777                   (int)selected_widgets);
778 #endif /* TREE_DEBUG */
779         }
780
781       /* remove this item of his real parent */
782 #ifdef TREE_DEBUG
783       g_print("* remove widget of his 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_print("* 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_print("* 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_print("* 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_print("* next item in list\n");
822 #endif /* TREE_DEBUG */
823     }
824
825   if (selected_widgets)
826     {
827 #ifdef TREE_DEBUG
828       g_print("* 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_print("* 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_print("* 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_print("* 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_print("* 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 (0, 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               child_allocation.height = child->requisition.height;
943
944               gtk_widget_size_allocate (child, &child_allocation);
945
946               child_allocation.y += child_allocation.height;
947
948               if((subtree = GTK_TREE_ITEM(child)->subtree))
949                 if(GTK_WIDGET_VISIBLE (subtree))
950                   {
951                     child_allocation.height = subtree->requisition.height;
952                     gtk_widget_size_allocate (subtree, &child_allocation);
953                     child_allocation.y += child_allocation.height;
954                   }
955             }
956         }
957     }
958
959 }
960
961 static void
962 gtk_tree_size_request (GtkWidget      *widget,
963                        GtkRequisition *requisition)
964 {
965   GtkTree *tree;
966   GtkWidget *child, *subtree;
967   GList *children;
968
969
970   g_return_if_fail (widget != NULL);
971   g_return_if_fail (GTK_IS_TREE (widget));
972   g_return_if_fail (requisition != NULL);
973
974   tree = GTK_TREE (widget);
975   requisition->width = 0;
976   requisition->height = 0;
977
978   children = tree->children;
979   while (children)
980     {
981       child = children->data;
982       children = children->next;
983
984       if (GTK_WIDGET_VISIBLE (child))
985         {
986           gtk_widget_size_request (child, &child->requisition);
987
988           requisition->width = MAX (requisition->width, child->requisition.width);
989           requisition->height += child->requisition.height;
990
991           if((subtree = GTK_TREE_ITEM(child)->subtree) &&
992              GTK_WIDGET_VISIBLE (subtree))
993             {
994               gtk_widget_size_request (subtree, &subtree->requisition);
995
996               requisition->width = MAX (requisition->width, 
997                                         subtree->requisition.width);
998
999               requisition->height += subtree->requisition.height;
1000             }
1001         }
1002     }
1003
1004   requisition->width += GTK_CONTAINER (tree)->border_width * 2;
1005   requisition->height += GTK_CONTAINER (tree)->border_width * 2;
1006
1007   requisition->width = MAX (requisition->width, 1);
1008   requisition->height = MAX (requisition->height, 1);
1009
1010 }
1011
1012 static void
1013 gtk_tree_unmap (GtkWidget *widget)
1014 {
1015
1016   g_return_if_fail (widget != NULL);
1017   g_return_if_fail (GTK_IS_TREE (widget));
1018
1019   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1020   gdk_window_hide (widget->window);
1021
1022 }
1023
1024 void
1025 gtk_tree_unselect_child (GtkTree   *tree,
1026                          GtkWidget *tree_item)
1027 {
1028   g_return_if_fail (tree != NULL);
1029   g_return_if_fail (GTK_IS_TREE (tree));
1030   g_return_if_fail (tree_item != NULL);
1031   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1032
1033   gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1034 }
1035
1036 void
1037 gtk_tree_unselect_item (GtkTree *tree,
1038                         gint     item)
1039 {
1040   GList *tmp_list;
1041
1042   g_return_if_fail (tree != NULL);
1043   g_return_if_fail (GTK_IS_TREE (tree));
1044
1045   tmp_list = g_list_nth (tree->children, item);
1046   if (tmp_list)
1047     gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1048
1049 }
1050
1051 static void
1052 gtk_real_tree_select_child (GtkTree   *tree,
1053                             GtkWidget *child)
1054 {
1055   GList *selection, *root_selection;
1056   GList *tmp_list;
1057   GtkWidget *tmp_item;
1058
1059   g_return_if_fail (tree != NULL);
1060   g_return_if_fail (GTK_IS_TREE (tree));
1061   g_return_if_fail (child != NULL);
1062   g_return_if_fail (GTK_IS_TREE_ITEM (child));
1063
1064   root_selection = tree->root_tree->selection;
1065   
1066   switch (tree->root_tree->selection_mode)
1067     {
1068     case GTK_SELECTION_SINGLE:
1069
1070       selection = root_selection;
1071
1072       /* remove old selection list */
1073       while (selection)
1074         {
1075           tmp_item = selection->data;
1076
1077           if (tmp_item != child)
1078             {
1079               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1080
1081               tmp_list = selection;
1082               selection = selection->next;
1083
1084               root_selection = g_list_remove_link (root_selection, tmp_list);
1085               gtk_widget_unref (tmp_item);
1086               
1087               g_list_free (tmp_list);
1088             }
1089           else
1090             selection = selection->next;
1091         }
1092
1093       if (child->state == GTK_STATE_NORMAL)
1094         {
1095           gtk_tree_item_select (GTK_TREE_ITEM (child));
1096           root_selection = g_list_prepend (root_selection, child);
1097           gtk_widget_ref (child);
1098         }
1099       else if (child->state == GTK_STATE_SELECTED)
1100         {
1101           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1102           root_selection = g_list_remove (root_selection, child);
1103           gtk_widget_unref (child);
1104         }
1105
1106       tree->root_tree->selection = root_selection;
1107
1108       gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1109                        tree_signals[SELECTION_CHANGED]);
1110       break;
1111
1112
1113     case GTK_SELECTION_BROWSE:
1114       selection = root_selection;
1115
1116       while (selection)
1117         {
1118           tmp_item = selection->data;
1119
1120           if (tmp_item != child)
1121             {
1122               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1123
1124               tmp_list = selection;
1125               selection = selection->next;
1126
1127               root_selection = g_list_remove_link (root_selection, tmp_list);
1128               gtk_widget_unref (tmp_item);
1129
1130               g_list_free (tmp_list);
1131             }
1132           else
1133             selection = selection->next;
1134         }
1135
1136       tree->root_tree->selection = root_selection;
1137
1138       if (child->state == GTK_STATE_NORMAL)
1139         {
1140           gtk_tree_item_select (GTK_TREE_ITEM (child));
1141           root_selection = g_list_prepend (root_selection, child);
1142           gtk_widget_ref (child);
1143           tree->root_tree->selection = root_selection;
1144           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1145                            tree_signals[SELECTION_CHANGED]);
1146         }
1147       break;
1148
1149     case GTK_SELECTION_MULTIPLE:
1150       if (child->state == GTK_STATE_NORMAL)
1151         {
1152           gtk_tree_item_select (GTK_TREE_ITEM (child));
1153           root_selection = g_list_prepend (root_selection, child);
1154           gtk_widget_ref (child);
1155           tree->root_tree->selection = root_selection;
1156           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1157                            tree_signals[SELECTION_CHANGED]);
1158         }
1159       else if (child->state == GTK_STATE_SELECTED)
1160         {
1161           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1162           root_selection = g_list_remove (root_selection, child);
1163           gtk_widget_unref (child);
1164           tree->root_tree->selection = root_selection;
1165           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1166                            tree_signals[SELECTION_CHANGED]);
1167         }
1168       break;
1169
1170     case GTK_SELECTION_EXTENDED:
1171       break;
1172     }
1173 }
1174
1175 static void
1176 gtk_real_tree_unselect_child (GtkTree   *tree,
1177                               GtkWidget *child)
1178 {
1179   g_return_if_fail (tree != NULL);
1180   g_return_if_fail (GTK_IS_TREE (tree));
1181   g_return_if_fail (child != NULL);
1182   g_return_if_fail (GTK_IS_TREE_ITEM (child));
1183
1184   switch (tree->selection_mode)
1185     {
1186     case GTK_SELECTION_SINGLE:
1187     case GTK_SELECTION_MULTIPLE:
1188     case GTK_SELECTION_BROWSE:
1189       if (child->state == GTK_STATE_SELECTED)
1190         {
1191           GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1192           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1193           root_tree->selection = g_list_remove (root_tree->selection, child);
1194           gtk_widget_unref (child);
1195           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1196                            tree_signals[SELECTION_CHANGED]);
1197         }
1198       break;
1199
1200     case GTK_SELECTION_EXTENDED:
1201       break;
1202     }
1203 }
1204
1205 void
1206 gtk_tree_set_selection_mode (GtkTree       *tree,
1207                              GtkSelectionMode mode) 
1208 {
1209   g_return_if_fail (tree != NULL);
1210   g_return_if_fail (GTK_IS_TREE (tree));
1211
1212   tree->selection_mode = mode;
1213 }
1214
1215 void
1216 gtk_tree_set_view_mode (GtkTree       *tree,
1217                         GtkTreeViewMode mode) 
1218 {
1219   g_return_if_fail (tree != NULL);
1220   g_return_if_fail (GTK_IS_TREE (tree));
1221
1222   tree->view_mode = mode;
1223 }
1224
1225 void
1226 gtk_tree_set_view_lines (GtkTree       *tree,
1227                          guint          flag) 
1228 {
1229   g_return_if_fail (tree != NULL);
1230   g_return_if_fail (GTK_IS_TREE (tree));
1231
1232   tree->view_line = flag;
1233 }