]> Pileus Git - ~andy/gtk/blob - gtk/gtktree.c
Fixes to GtkTree, courtesy of Erik Troan <ewt@redhat.com>
[~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 = (void *) gtk_tree_remove_item;
153   container_class->foreach = gtk_tree_foreach;
154
155   class->selection_changed = NULL;
156   class->select_child = gtk_real_tree_select_child;
157   class->unselect_child = gtk_real_tree_unselect_child;
158 }
159
160 static void
161 gtk_tree_init (GtkTree *tree)
162 {
163   tree->children = NULL;
164   tree->root_tree = NULL;
165   tree->selection = NULL;
166   tree->tree_owner = NULL;
167   tree->selection_mode = GTK_SELECTION_SINGLE;
168   tree->indent_value = 9;
169   tree->current_indent = 0;
170   tree->level = 0;
171   tree->view_mode = GTK_TREE_VIEW_LINE;
172   tree->view_line = 1;
173 }
174
175 GtkWidget*
176 gtk_tree_new ()
177 {
178   return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
179 }
180
181 void
182 gtk_tree_append (GtkTree   *tree,
183                  GtkWidget *child)
184 {
185
186   g_return_if_fail (tree != NULL);
187   g_return_if_fail (GTK_IS_TREE_ITEM (child));
188
189   gtk_tree_insert(tree, child, -1);
190 }
191
192 void
193 gtk_tree_prepend (GtkTree   *tree,
194                   GtkWidget *child)
195 {
196   g_return_if_fail (tree != NULL);
197   g_return_if_fail (GTK_IS_TREE_ITEM (child));
198
199   gtk_tree_insert(tree, child, 0);
200
201 }
202
203 void
204 gtk_tree_insert (GtkTree   *tree,
205                  GtkWidget *child,
206                  gint       position)
207 {
208   gint nchildren;
209     
210   g_return_if_fail (tree != NULL || child != NULL);
211   g_return_if_fail (GTK_IS_TREE_ITEM(child));
212
213   /* set parent widget to item */
214   gtk_widget_set_parent (child, GTK_WIDGET (tree));
215     
216   if (GTK_WIDGET_VISIBLE (child->parent))
217     {
218       if (GTK_WIDGET_REALIZED (child->parent) &&
219           !GTK_WIDGET_REALIZED (child))
220         gtk_widget_realize (child);
221
222       if (GTK_WIDGET_MAPPED (child->parent) &&
223           !GTK_WIDGET_MAPPED (child))
224         gtk_widget_map (child);
225     }
226
227   nchildren = g_list_length (tree->children);
228     
229   if ((position < 0) || (position > nchildren))
230     position = nchildren;
231
232   if (position == nchildren)
233     {
234       tree->children = g_list_append(tree->children, child);
235     }
236   else
237     {
238       tree->children = g_list_insert(tree->children, child, position);
239     }
240     
241   if (GTK_WIDGET_VISIBLE (tree))
242     gtk_widget_queue_resize (GTK_WIDGET (tree));
243
244 }
245
246 static void
247 gtk_tree_add (GtkContainer *container,
248               GtkWidget    *widget)
249 {
250   GtkTree *tree;
251
252   g_return_if_fail (container != NULL);
253   g_return_if_fail (GTK_IS_TREE (container));
254   g_return_if_fail (widget != NULL);
255
256   tree = GTK_TREE (container);
257
258   gtk_widget_set_parent (widget, GTK_WIDGET (container));
259   if (GTK_WIDGET_VISIBLE (widget->parent))
260     {
261       if (GTK_WIDGET_REALIZED (widget->parent) &&
262           !GTK_WIDGET_REALIZED (widget))
263         gtk_widget_realize (widget);
264
265       if (GTK_WIDGET_MAPPED (widget->parent) &&
266           !GTK_WIDGET_MAPPED (widget))
267         gtk_widget_map (widget);
268     }
269
270   tree->children = g_list_append (tree->children, widget);
271
272   if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
273     {
274       gtk_tree_select_child (tree, widget);
275     }
276
277   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
278     gtk_widget_queue_resize (widget);
279
280 }
281
282 static gint
283 gtk_tree_button_press (GtkWidget      *widget,
284                        GdkEventButton *event)
285 {
286   GtkTree *tree;
287   GtkWidget *item;
288
289   g_return_val_if_fail (widget != NULL, FALSE);
290   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
291   g_return_val_if_fail (event != NULL, FALSE);
292
293   tree = GTK_TREE (widget);
294   item = gtk_get_event_widget ((GdkEvent*) event);
295
296   while (!gtk_type_is_a (GTK_WIDGET_TYPE (item), gtk_tree_item_get_type ()))
297     item = item->parent;
298
299   switch(event->button) 
300     {
301     case 1:
302       gtk_tree_select_child (tree, item);
303       break;
304     case 2:
305       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
306       break;
307     case 3:
308       if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
309       break;
310     }
311
312   return TRUE;
313 }
314
315 static gint
316 gtk_tree_button_release (GtkWidget      *widget,
317                          GdkEventButton *event)
318 {
319   GtkTree *tree;
320   GtkWidget *item;
321
322   g_return_val_if_fail (widget != NULL, FALSE);
323   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
324   g_return_val_if_fail (event != NULL, FALSE);
325
326   tree = GTK_TREE (widget);
327   item = gtk_get_event_widget ((GdkEvent*) event);
328
329   return TRUE;
330 }
331
332 gint
333 gtk_tree_child_position (GtkTree   *tree,
334                          GtkWidget *child)
335 {
336   GList *children;
337   gint pos;
338
339
340   g_return_val_if_fail (tree != NULL, -1);
341   g_return_val_if_fail (GTK_IS_TREE (tree), -1);
342   g_return_val_if_fail (child != NULL, -1);
343
344   pos = 0;
345   children = tree->children;
346
347   while (children)
348     {
349       if (child == GTK_WIDGET (children->data)) 
350         return pos;
351
352       pos += 1;
353       children = children->next;
354     }
355
356
357   return -1;
358 }
359
360 void
361 gtk_tree_clear_items (GtkTree *tree,
362                       gint     start,
363                       gint     end)
364 {
365   g_return_if_fail (tree != NULL);
366   g_return_if_fail (GTK_IS_TREE (tree));
367
368 }
369
370 static void
371 gtk_tree_destroy (GtkObject *object)
372 {
373   GtkTree *tree;
374   GtkWidget *child;
375   GList *children;
376
377   g_return_if_fail (object != NULL);
378   g_return_if_fail (GTK_IS_TREE (object));
379
380   tree = GTK_TREE (object);
381
382   children = tree->children;
383   while (children)
384     {
385       child = children->data;
386       children = children->next;
387       
388       gtk_widget_ref (child);
389       gtk_widget_unparent (child);
390       gtk_widget_destroy (child);
391       gtk_widget_unref (child);
392     }
393
394   g_list_free (tree->children);
395   tree->children = NULL;
396
397   if (tree->root_tree == tree)
398     {
399       GList *node;
400       for (node = tree->selection; node; node = node->next)
401         gtk_widget_unref ((GtkWidget *)node->data);
402       g_list_free (tree->selection);
403       tree->selection = NULL;
404     }
405
406   if (GTK_OBJECT_CLASS (parent_class)->destroy)
407     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
408 }
409
410 static void
411 gtk_tree_draw (GtkWidget    *widget,
412                GdkRectangle *area)
413 {
414   GtkTree *tree;
415   GtkWidget *subtree;
416   GtkWidget *child;
417   GdkRectangle child_area;
418   GList *children;
419
420
421   g_return_if_fail (widget != NULL);
422   g_return_if_fail (GTK_IS_TREE (widget));
423   g_return_if_fail (area != NULL);
424
425   if (GTK_WIDGET_DRAWABLE (widget))
426     {
427       tree = GTK_TREE (widget);
428
429       children = tree->children;
430       while (children)
431         {
432           child = children->data;
433           children = children->next;
434
435           if (gtk_widget_intersect (child, area, &child_area))
436             gtk_widget_draw (child, &child_area);
437
438           if((subtree = GTK_TREE_ITEM(child)->subtree) &&
439              GTK_WIDGET_VISIBLE(subtree) &&
440              gtk_widget_intersect (subtree, area, &child_area))
441             gtk_widget_draw (subtree, &child_area);
442         }
443     }
444
445 }
446
447 static gint
448 gtk_tree_expose (GtkWidget      *widget,
449                  GdkEventExpose *event)
450 {
451   GtkTree *tree;
452   GtkWidget *child;
453   GdkEventExpose child_event;
454   GList *children;
455
456
457   g_return_val_if_fail (widget != NULL, FALSE);
458   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
459   g_return_val_if_fail (event != NULL, FALSE);
460
461   if (GTK_WIDGET_DRAWABLE (widget))
462     {
463       tree = GTK_TREE (widget);
464
465       child_event = *event;
466
467       children = tree->children;
468       while (children)
469         {
470           child = children->data;
471           children = children->next;
472
473           if (GTK_WIDGET_NO_WINDOW (child) &&
474               gtk_widget_intersect (child, &event->area, &child_event.area))
475             gtk_widget_event (child, (GdkEvent*) &child_event);
476         }
477     }
478
479
480   return FALSE;
481 }
482
483 static void
484 gtk_tree_foreach (GtkContainer *container,
485                   GtkCallback   callback,
486                   gpointer      callback_data)
487 {
488   GtkTree *tree;
489   GtkWidget *child;
490   GList *children;
491
492
493   g_return_if_fail (container != NULL);
494   g_return_if_fail (GTK_IS_TREE (container));
495   g_return_if_fail (callback != NULL);
496
497   tree = GTK_TREE (container);
498   children = tree->children;
499
500   while (children)
501     {
502       child = children->data;
503       children = children->next;
504
505       (* callback) (child, callback_data);
506
507       if(GTK_TREE_ITEM(child)->subtree)
508         (* callback)(GTK_TREE_ITEM(child)->subtree, callback_data);
509     }
510 }
511
512 static void
513 gtk_tree_map (GtkWidget *widget)
514 {
515   GtkTree *tree;
516   GtkWidget *child;
517   GList *children;
518
519
520   g_return_if_fail (widget != NULL);
521   g_return_if_fail (GTK_IS_TREE (widget));
522
523   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
524   tree = GTK_TREE (widget);
525
526   gdk_window_show (widget->window);
527
528   if(GTK_IS_TREE(widget->parent)) 
529     {
530       /* set root tree for this tree */
531       tree->root_tree = GTK_TREE(widget->parent)->root_tree;
532
533       tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
534       tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
535       tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent + 
536         tree->indent_value;
537       tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
538       tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
539     } 
540   else
541     tree->root_tree = tree;
542
543   children = tree->children;
544   while (children)
545     {
546       child = children->data;
547       children = children->next;
548
549       if (GTK_WIDGET_VISIBLE (child) &&
550           !GTK_WIDGET_MAPPED (child))
551         gtk_widget_map (child);
552
553       if ((child = GTK_WIDGET(GTK_TREE_ITEM(child)->subtree)) &&
554           GTK_WIDGET_VISIBLE (child) &&
555           !GTK_WIDGET_MAPPED (child))
556         gtk_widget_map (child);
557     }
558 }
559
560 static void
561 gtk_tree_marshal_signal (GtkObject      *object,
562                          GtkSignalFunc   func,
563                          gpointer        func_data,
564                          GtkArg         *args)
565 {
566   GtkTreeSignal rfunc;
567
568   rfunc = (GtkTreeSignal) func;
569
570   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
571 }
572
573 static gint
574 gtk_tree_motion_notify (GtkWidget      *widget,
575                         GdkEventMotion *event)
576 {
577   g_return_val_if_fail (widget != NULL, FALSE);
578   g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
579   g_return_val_if_fail (event != NULL, FALSE);
580
581   g_print("gtk_tree_motion_notify\n");
582
583   return FALSE;
584 }
585
586 static void
587 gtk_tree_realize (GtkWidget *widget)
588 {
589   GdkWindowAttr attributes;
590   gint attributes_mask;
591
592
593   g_return_if_fail (widget != NULL);
594   g_return_if_fail (GTK_IS_TREE (widget));
595
596   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
597
598   attributes.window_type = GDK_WINDOW_CHILD;
599   attributes.x = widget->allocation.x;
600   attributes.y = widget->allocation.y;
601   attributes.width = widget->allocation.width;
602   attributes.height = widget->allocation.height;
603   attributes.wclass = GDK_INPUT_OUTPUT;
604   attributes.visual = gtk_widget_get_visual (widget);
605   attributes.colormap = gtk_widget_get_colormap (widget);
606   attributes.event_mask = GDK_EXPOSURE_MASK;
607
608   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
609
610   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
611   gdk_window_set_user_data (widget->window, widget);
612
613   widget->style = gtk_style_attach (widget->style, widget->window);
614   gdk_window_set_background (widget->window, 
615                              &widget->style->base[GTK_STATE_NORMAL]);
616
617 }
618
619 void
620 gtk_tree_remove_item (GtkTree *container,
621                  GtkWidget    *widget)
622 {
623   GList *item_list;
624
625   g_return_if_fail (container != NULL);
626   g_return_if_fail (GTK_IS_TREE (container));
627   g_return_if_fail (widget != NULL);
628   g_return_if_fail (container == GTK_TREE (widget->parent));
629
630   item_list = g_list_alloc ();
631   item_list->data = widget;
632   
633   gtk_tree_remove_items (GTK_TREE (container), item_list);
634
635   g_list_free (item_list);
636 }
637
638 void
639 gtk_tree_remove_items (GtkTree *tree,
640                        GList   *items)
641 {
642   GtkWidget *widget;
643   GList *selected_widgets;
644   GList *tmp_list;
645   GtkTree *real_tree, *root_tree;
646
647   g_return_if_fail (tree != NULL);
648   g_return_if_fail (GTK_IS_TREE (tree));
649
650   root_tree = GTK_TREE(GTK_TREE_ROOT_TREE(tree));
651   tmp_list = items;
652   selected_widgets = NULL;
653   widget = NULL;
654
655   while (tmp_list)
656     {
657       widget = tmp_list->data;
658       tmp_list = tmp_list->next;
659
660       /* get real owner of this widget */
661       real_tree = GTK_TREE(widget->parent);
662       
663       if (widget->state == GTK_STATE_SELECTED)
664         selected_widgets = g_list_prepend (selected_widgets, widget);
665
666       /* remove this item of his real parent */
667       real_tree->children = g_list_remove (real_tree->children, widget);
668
669       /* delete subtree if there is no children in it */
670       if(real_tree->children == NULL && 
671          real_tree != root_tree)
672         {
673           gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
674         }
675
676       /* remove subtree associate at this item if it exist */      
677       if(GTK_TREE_ITEM(widget)->subtree) 
678         {
679           if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
680             gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
681
682           gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
683           GTK_TREE_ITEM(widget)->subtree = NULL;
684         }
685
686       /* remove really widget for this item */
687       if (GTK_WIDGET_MAPPED (widget))
688         gtk_widget_unmap (widget);
689
690       gtk_widget_unparent (widget);
691     }
692
693   if (selected_widgets)
694     {
695       tmp_list = selected_widgets;
696       while (tmp_list)
697         {
698           widget = tmp_list->data;
699           tmp_list = tmp_list->next;
700
701           gtk_tree_unselect_child (tree, widget);
702         }
703     }
704
705   g_list_free (selected_widgets);
706
707   if (root_tree->children && !root_tree->selection &&
708       (root_tree->selection_mode == GTK_SELECTION_BROWSE))
709     {
710       widget = root_tree->children->data;
711       gtk_tree_select_child (root_tree, widget);
712     }
713
714   if (GTK_WIDGET_VISIBLE (root_tree))
715     gtk_widget_queue_resize (GTK_WIDGET (root_tree));
716 }
717  
718 void
719 gtk_tree_select_child (GtkTree   *tree,
720                        GtkWidget *child)
721 {
722
723   gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], child);
724
725 }
726
727 void
728 gtk_tree_select_item (GtkTree   *tree,
729                       gint     item)
730 {
731   GList *tmp_list;
732
733
734   g_return_if_fail (tree != NULL);
735   g_return_if_fail (GTK_IS_TREE (tree));
736
737   tmp_list = g_list_nth (tree->children, item);
738   if (tmp_list)
739     gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
740
741 }
742
743 static void
744 gtk_tree_size_allocate (GtkWidget     *widget,
745                         GtkAllocation *allocation)
746 {
747   GtkTree *tree;
748   GtkWidget *child, *subtree;
749   GtkAllocation child_allocation;
750   GList *children;
751
752
753   g_return_if_fail (widget != NULL);
754   g_return_if_fail (GTK_IS_TREE (widget));
755   g_return_if_fail (allocation != NULL);
756
757   tree = GTK_TREE (widget);
758
759   widget->allocation = *allocation;
760   if (GTK_WIDGET_REALIZED (widget))
761     gdk_window_move_resize (widget->window,
762                             allocation->x, allocation->y,
763                             allocation->width, allocation->height);
764   
765   if (tree->children)
766     {
767       child_allocation.x = GTK_CONTAINER (tree)->border_width;
768       child_allocation.y = GTK_CONTAINER (tree)->border_width;
769       child_allocation.width = allocation->width - child_allocation.x * 2;
770
771       children = tree->children;
772
773       while (children)
774         {
775           child = children->data;
776           children = children->next;
777
778           if (GTK_WIDGET_VISIBLE (child))
779             {
780               child_allocation.height = child->requisition.height;
781
782               gtk_widget_size_allocate (child, &child_allocation);
783
784               child_allocation.y += child_allocation.height;
785
786               if((subtree = GTK_TREE_ITEM(child)->subtree))
787                 if(GTK_WIDGET_VISIBLE (subtree))
788                   {
789                     child_allocation.height = subtree->requisition.height;
790                     gtk_widget_size_allocate (subtree, &child_allocation);
791                     child_allocation.y += child_allocation.height;
792                   }
793             }
794         }
795     }
796
797 }
798
799 static void
800 gtk_tree_size_request (GtkWidget      *widget,
801                        GtkRequisition *requisition)
802 {
803   GtkTree *tree;
804   GtkWidget *child, *subtree;
805   GList *children;
806
807
808   g_return_if_fail (widget != NULL);
809   g_return_if_fail (GTK_IS_TREE (widget));
810   g_return_if_fail (requisition != NULL);
811
812   tree = GTK_TREE (widget);
813   requisition->width = 0;
814   requisition->height = 0;
815
816   children = tree->children;
817   while (children)
818     {
819       child = children->data;
820       children = children->next;
821
822       if (GTK_WIDGET_VISIBLE (child))
823         {
824           gtk_widget_size_request (child, &child->requisition);
825
826           requisition->width = MAX (requisition->width, child->requisition.width);
827           requisition->height += child->requisition.height;
828
829           if((subtree = GTK_TREE_ITEM(child)->subtree) &&
830              GTK_WIDGET_VISIBLE (subtree))
831             {
832               gtk_widget_size_request (subtree, &subtree->requisition);
833
834               requisition->width = MAX (requisition->width, 
835                                         subtree->requisition.width);
836
837               requisition->height += subtree->requisition.height;
838             }
839         }
840     }
841
842   requisition->width += GTK_CONTAINER (tree)->border_width * 2;
843   requisition->height += GTK_CONTAINER (tree)->border_width * 2;
844
845   requisition->width = MAX (requisition->width, 1);
846   requisition->height = MAX (requisition->height, 1);
847
848 }
849
850 static void
851 gtk_tree_unmap (GtkWidget *widget)
852 {
853
854   g_return_if_fail (widget != NULL);
855   g_return_if_fail (GTK_IS_TREE (widget));
856
857   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
858   gdk_window_hide (widget->window);
859
860 }
861
862 void
863 gtk_tree_unselect_child (GtkTree   *tree,
864                          GtkWidget *child)
865 {
866   gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], child);
867 }
868
869 void
870 gtk_tree_unselect_item (GtkTree *tree,
871                         gint     item)
872 {
873   GList *tmp_list;
874
875
876   g_return_if_fail (tree != NULL);
877   g_return_if_fail (GTK_IS_TREE (tree));
878
879   tmp_list = g_list_nth (tree->children, item);
880   if (tmp_list)
881     gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
882
883 }
884
885 static void
886 gtk_real_tree_select_child (GtkTree   *tree,
887                             GtkWidget *child)
888 {
889   GList *selection, *root_selection;
890   GList *tmp_list;
891   GtkWidget *tmp_item;
892
893
894   g_return_if_fail (tree != NULL);
895   g_return_if_fail (GTK_IS_TREE (tree));
896   g_return_if_fail (child != NULL);
897   g_return_if_fail (GTK_IS_TREE_ITEM (child));
898
899   root_selection = tree->root_tree->selection;
900   
901   switch (tree->root_tree->selection_mode)
902     {
903     case GTK_SELECTION_SINGLE:
904
905       selection = root_selection;
906
907       /* remove old selection list */
908       while (selection)
909         {
910           tmp_item = selection->data;
911
912           if (tmp_item != child)
913             {
914               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
915
916               tmp_list = selection;
917               selection = selection->next;
918
919               root_selection = g_list_remove_link (root_selection, tmp_list);
920               gtk_widget_unref (tmp_item);
921               
922               g_list_free (tmp_list);
923             }
924           else
925             selection = selection->next;
926         }
927
928       if (child->state == GTK_STATE_NORMAL)
929         {
930           gtk_tree_item_select (GTK_TREE_ITEM (child));
931           root_selection = g_list_prepend (root_selection, child);
932           gtk_widget_ref (child);
933         }
934       else if (child->state == GTK_STATE_SELECTED)
935         {
936           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
937           root_selection = g_list_remove (root_selection, child);
938           gtk_widget_unref (child);
939         }
940
941       tree->root_tree->selection = root_selection;
942
943       gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
944                        tree_signals[SELECTION_CHANGED]);
945       break;
946
947
948     case GTK_SELECTION_BROWSE:
949       selection = root_selection;
950
951       while (selection)
952         {
953           tmp_item = selection->data;
954
955           if (tmp_item != child)
956             {
957               gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
958
959               tmp_list = selection;
960               selection = selection->next;
961
962               root_selection = g_list_remove_link (root_selection, tmp_list);
963               gtk_widget_unref (tmp_item);
964
965               g_list_free (tmp_list);
966             }
967           else
968             selection = selection->next;
969         }
970
971       tree->root_tree->selection = root_selection;
972
973       if (child->state == GTK_STATE_NORMAL)
974         {
975           gtk_tree_item_select (GTK_TREE_ITEM (child));
976           root_selection = g_list_prepend (root_selection, child);
977           gtk_widget_ref (child);
978           tree->root_tree->selection = root_selection;
979           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
980                            tree_signals[SELECTION_CHANGED]);
981         }
982       break;
983
984     case GTK_SELECTION_MULTIPLE:
985       if (child->state == GTK_STATE_NORMAL)
986         {
987           gtk_tree_item_select (GTK_TREE_ITEM (child));
988           root_selection = g_list_prepend (root_selection, child);
989           gtk_widget_ref (child);
990           tree->root_tree->selection = root_selection;
991           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
992                            tree_signals[SELECTION_CHANGED]);
993         }
994       else if (child->state == GTK_STATE_SELECTED)
995         {
996           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
997           root_selection = g_list_remove (root_selection, child);
998           gtk_widget_unref (child);
999           tree->root_tree->selection = root_selection;
1000           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1001                            tree_signals[SELECTION_CHANGED]);
1002         }
1003       break;
1004
1005     case GTK_SELECTION_EXTENDED:
1006       break;
1007     }
1008 }
1009
1010 static void
1011 gtk_real_tree_unselect_child (GtkTree   *tree,
1012                               GtkWidget *child)
1013 {
1014
1015   g_return_if_fail (tree != NULL);
1016   g_return_if_fail (GTK_IS_TREE (tree));
1017   g_return_if_fail (child != NULL);
1018   g_return_if_fail (GTK_IS_TREE_ITEM (child));
1019
1020   switch (tree->selection_mode)
1021     {
1022     case GTK_SELECTION_SINGLE:
1023     case GTK_SELECTION_MULTIPLE:
1024     case GTK_SELECTION_BROWSE:
1025       if (child->state == GTK_STATE_SELECTED)
1026         {
1027           GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1028           gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1029           root_tree->selection = g_list_remove (root_tree->selection, child);
1030           gtk_widget_unref (child);
1031           gtk_signal_emit (GTK_OBJECT (tree->root_tree), 
1032                            tree_signals[SELECTION_CHANGED]);
1033         }
1034       break;
1035
1036     case GTK_SELECTION_EXTENDED:
1037       break;
1038     }
1039 }
1040
1041 void
1042 gtk_tree_set_selection_mode (GtkTree       *tree,
1043                              GtkSelectionMode mode) 
1044 {
1045   g_return_if_fail (tree != NULL);
1046   g_return_if_fail (GTK_IS_TREE (tree));
1047
1048   tree->selection_mode = mode;
1049 }
1050
1051 void
1052 gtk_tree_set_view_mode (GtkTree       *tree,
1053                         GtkTreeViewMode mode) 
1054 {
1055   g_return_if_fail (tree != NULL);
1056   g_return_if_fail (GTK_IS_TREE (tree));
1057
1058   tree->view_mode = mode;
1059 }
1060
1061 void
1062 gtk_tree_set_view_lines (GtkTree       *tree,
1063                          guint          flag) 
1064 {
1065   g_return_if_fail (tree != NULL);
1066   g_return_if_fail (GTK_IS_TREE (tree));
1067
1068   tree->view_line = flag;
1069 }