]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeitem.c
Change style->white to style->base[] where appropriate. Change the default
[~andy/gtk] / gtk / gtktreeitem.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 "gtklabel.h"
19 #include "gtktree.h"
20 #include "gtktreeitem.h"
21 #include "gtkeventbox.h"
22 #include "gtkpixmap.h"
23 #include "gtkmain.h"
24 #include "gtksignal.h"
25
26 /* remove comment if you want replace loading pixmap by static bitmap 
27    for icons 
28    experimental code and it is buggy */
29 /* #define WITH_BITMAP */
30
31 #define DEFAULT_DELTA 9
32
33 #ifdef WITH_BITMAP
34 #include "tree_plus.xbm"
35 #include "tree_minus.xbm"
36 #endif
37
38 enum {
39   COLLAPSE_TREE,
40   EXPAND_TREE,
41   LAST_SIGNAL
42 };
43
44 typedef void (*GtkTreeItemSignal) (GtkObject *object,
45                                    gpointer   arg1,
46                                    gpointer   data);
47
48 static void gtk_tree_item_class_init (GtkTreeItemClass *klass);
49 static void gtk_tree_item_init       (GtkTreeItem      *tree_item);
50 static void gtk_tree_item_realize       (GtkWidget        *widget);
51 static void gtk_tree_item_size_request  (GtkWidget        *widget,
52                                          GtkRequisition   *requisition);
53 static void gtk_tree_item_size_allocate (GtkWidget        *widget,
54                                          GtkAllocation    *allocation);
55 static void gtk_tree_item_draw          (GtkWidget        *widget,
56                                          GdkRectangle     *area);
57 static void gtk_tree_item_draw_focus    (GtkWidget        *widget);
58 static gint gtk_tree_item_button_press  (GtkWidget        *widget,
59                                          GdkEventButton   *event);
60 static gint gtk_tree_item_expose        (GtkWidget        *widget,
61                                          GdkEventExpose   *event);
62 static gint gtk_tree_item_focus_in      (GtkWidget        *widget,
63                                          GdkEventFocus    *event);
64 static gint gtk_tree_item_focus_out     (GtkWidget        *widget,
65                                          GdkEventFocus    *event);
66 static void gtk_real_tree_item_select   (GtkItem          *item);
67 static void gtk_real_tree_item_deselect (GtkItem          *item);
68 static void gtk_real_tree_item_toggle   (GtkItem          *item);
69 static void gtk_real_tree_item_expand   (GtkTreeItem      *item);
70 static void gtk_real_tree_item_collapse (GtkTreeItem      *item);
71 static void gtk_real_tree_item_expand   (GtkTreeItem      *item);
72 static void gtk_real_tree_item_collapse (GtkTreeItem      *item);
73 static void gtk_tree_item_marshal_signal (GtkObject      *object,
74                                           GtkSignalFunc   func,
75                                           gpointer        func_data,
76                                           GtkArg         *args);
77 static void gtk_tree_item_destroy        (GtkObject *object);
78 static void gtk_tree_item_subtree_button_click (GtkWidget *widget);
79 static void gtk_tree_item_subtree_button_changed_state (GtkWidget *widget);
80
81 static void gtk_tree_item_map(GtkWidget*);
82 static void gtk_tree_item_unmap(GtkWidget*);
83
84 static GtkItemClass *parent_class = NULL;
85 static GtkContainerClass *container_class = NULL;
86 static gint tree_item_signals[LAST_SIGNAL] = { 0 };
87
88 guint
89 gtk_tree_item_get_type ()
90 {
91   static guint tree_item_type = 0;
92
93   if (!tree_item_type)
94     {
95       GtkTypeInfo tree_item_info =
96       {
97         "GtkTreeItem",
98         sizeof (GtkTreeItem),
99         sizeof (GtkTreeItemClass),
100         (GtkClassInitFunc) gtk_tree_item_class_init,
101         (GtkObjectInitFunc) gtk_tree_item_init,
102         (GtkArgSetFunc) NULL,
103         (GtkArgGetFunc) NULL,
104       };
105
106       tree_item_type = gtk_type_unique (gtk_item_get_type (), &tree_item_info);
107     }
108
109   return tree_item_type;
110 }
111
112 static void
113 gtk_tree_item_class_init (GtkTreeItemClass *class)
114 {
115   GtkObjectClass *object_class;
116   GtkWidgetClass *widget_class;
117   GtkItemClass *item_class;
118
119   object_class = (GtkObjectClass*) class;
120   widget_class = (GtkWidgetClass*) class;
121   item_class = (GtkItemClass*) class;
122   container_class = (GtkContainerClass*) class;
123
124   parent_class = gtk_type_class (gtk_item_get_type ());
125   
126   tree_item_signals[EXPAND_TREE] =
127     gtk_signal_new ("expand",
128                     GTK_RUN_FIRST,
129                     object_class->type,
130                     GTK_SIGNAL_OFFSET (GtkTreeItemClass, expand),
131                     gtk_tree_item_marshal_signal,
132                     GTK_TYPE_NONE, 0);
133   tree_item_signals[COLLAPSE_TREE] =
134     gtk_signal_new ("collapse",
135                     GTK_RUN_FIRST,
136                     object_class->type,
137                     GTK_SIGNAL_OFFSET (GtkTreeItemClass, collapse),
138                     gtk_tree_item_marshal_signal,
139                     GTK_TYPE_NONE, 0);
140
141   gtk_object_class_add_signals (object_class, tree_item_signals, LAST_SIGNAL);
142
143   object_class->destroy = gtk_tree_item_destroy;
144
145   widget_class->realize = gtk_tree_item_realize;
146   widget_class->size_request = gtk_tree_item_size_request;
147   widget_class->size_allocate = gtk_tree_item_size_allocate;
148   widget_class->draw = gtk_tree_item_draw;
149   widget_class->draw_focus = gtk_tree_item_draw_focus;
150   widget_class->button_press_event = gtk_tree_item_button_press;
151   widget_class->expose_event = gtk_tree_item_expose;
152   widget_class->focus_in_event = gtk_tree_item_focus_in;
153   widget_class->focus_out_event = gtk_tree_item_focus_out;
154   widget_class->map = gtk_tree_item_map;
155   widget_class->unmap = gtk_tree_item_unmap;
156
157   item_class->select = gtk_real_tree_item_select;
158   item_class->deselect = gtk_real_tree_item_deselect;
159   item_class->toggle = gtk_real_tree_item_toggle;
160
161   class->expand = gtk_real_tree_item_expand;
162   class->collapse = gtk_real_tree_item_collapse;
163
164   container_class = (GtkContainerClass*) parent_class;
165 }
166
167 /* callback for event box mouse event */
168 static void 
169 gtk_tree_item_subtree_button_click (GtkWidget *widget)
170 {
171   GtkTreeItem* item;
172
173   item = (GtkTreeItem*) gtk_object_get_user_data(GTK_OBJECT(widget));
174   if(!GTK_WIDGET_IS_SENSITIVE(item))
175     return;
176
177   if(item->expanded)
178     gtk_tree_item_collapse(item);
179   else
180     gtk_tree_item_expand(item);
181 }
182
183 /* callback for event box state changed */
184 static void
185 gtk_tree_item_subtree_button_changed_state(GtkWidget *w)
186 {
187   if(GTK_WIDGET_VISIBLE (w)) {
188
189     if (w->state == GTK_STATE_NORMAL)
190       gdk_window_set_background (w->window, &w->style->base[w->state]);
191     else
192       gdk_window_set_background (w->window, &w->style->bg[w->state]);
193
194     if (GTK_WIDGET_DRAWABLE(w))
195       gdk_window_clear_area (w->window, 0, 0, 
196                              w->allocation.width, w->allocation.height);
197   }
198 }
199
200 static void
201 gtk_tree_item_init (GtkTreeItem *tree_item)
202 {
203   GtkWidget *eventbox, *pixmapwid;
204   static GdkPixmap *pixmap_plus = NULL;
205   static GdkPixmap *pixmap_minus = NULL;
206 #ifndef WITH_BITMAP
207   static GdkBitmap *mask = NULL; 
208 #endif
209   static GtkStyle *style = NULL;
210
211   tree_item->expanded = FALSE;
212   tree_item->subtree = NULL;
213   GTK_WIDGET_SET_FLAGS (tree_item, GTK_CAN_FOCUS);
214
215   if(style == NULL) 
216     {
217
218       style=gtk_widget_get_style(GTK_WIDGET(tree_item));
219
220 #ifndef WITH_BITMAP
221       /* create pixmaps for one time, based on xpm file */
222       pixmap_plus = gdk_pixmap_create_from_xpm (GTK_WIDGET(tree_item)->window, &mask, 
223                                                 &style->bg[GTK_STATE_NORMAL],
224                                                 "tree_plus.xpm");
225       if(!pixmap_plus)
226         g_warning("gtk_tree_item_init: can't find tree_plus.xpm file !\n");
227
228       pixmap_minus = gdk_pixmap_create_from_xpm (GTK_WIDGET(tree_item)->window, &mask, 
229                                                  &style->bg[GTK_STATE_NORMAL],
230                                                  "tree_minus.xpm");      
231       if(!pixmap_minus)
232         g_warning("gtk_tree_item_init: can't find tree_minus.xpm file !\n");
233 #else
234
235       pixmap_plus = gdk_pixmap_create_from_data(GTK_WIDGET(tree_item)->window,
236                                                 (gchar*) tree_plus_bits,
237                                                 tree_plus_width, tree_plus_height, -1,
238                                                 &style->black,
239                                                 &style->white);
240
241       pixmap_minus = gdk_pixmap_create_from_data(GTK_WIDGET(tree_item)->window,
242                                                  (gchar*) tree_minus_bits,
243                                                  tree_minus_width, tree_minus_height, -1,
244                                                  &style->black,
245                                                  &style->white);
246 #endif /* WITH_BITMAP */
247     }
248   
249   if(pixmap_plus && pixmap_minus) 
250     {
251       /* create an event box containing one pixmaps */
252       eventbox = gtk_event_box_new();
253       gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);
254       gtk_signal_connect(GTK_OBJECT(eventbox), "state_changed",
255                          (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state, 
256                          (gpointer)NULL);
257       gtk_signal_connect(GTK_OBJECT(eventbox), "realize",
258                          (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state, 
259                          (gpointer)NULL);
260       gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
261                          (GtkSignalFunc)gtk_tree_item_subtree_button_click,
262                          (gpointer)NULL);
263       gtk_object_set_user_data(GTK_OBJECT(eventbox), tree_item);
264       tree_item->pixmaps_box = eventbox;
265
266       /* create pixmap for button '+' */
267 #ifndef WITH_BITMAP
268       pixmapwid = gtk_pixmap_new (pixmap_plus, mask);
269 #else
270       pixmapwid = gtk_pixmap_new (pixmap_plus, NULL);
271 #endif
272       if(!tree_item->expanded) 
273         gtk_container_add(GTK_CONTAINER(eventbox), pixmapwid);
274       gtk_widget_show(pixmapwid);
275       tree_item->plus_pix_widget = pixmapwid;
276       gtk_widget_ref (tree_item->plus_pix_widget);
277       gtk_object_sink (GTK_OBJECT (tree_item->plus_pix_widget));
278       
279       /* create pixmap for button '-' */
280 #ifndef WITH_BITMAP
281       pixmapwid = gtk_pixmap_new (pixmap_minus, mask);
282 #else
283       pixmapwid = gtk_pixmap_new (pixmap_minus, NULL);
284 #endif
285       if(tree_item->expanded) 
286         gtk_container_add(GTK_CONTAINER(eventbox), pixmapwid);
287       gtk_widget_show(pixmapwid);
288       tree_item->minus_pix_widget = pixmapwid;
289       gtk_widget_ref (tree_item->minus_pix_widget);
290       gtk_object_sink (GTK_OBJECT (tree_item->minus_pix_widget));
291       
292       gtk_widget_set_parent(eventbox, GTK_WIDGET(tree_item));
293     } else
294       tree_item->pixmaps_box = NULL;
295 }
296
297
298 GtkWidget*
299 gtk_tree_item_new ()
300 {
301   GtkWidget *tree_item;
302
303   tree_item = GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
304
305   return tree_item;
306 }
307
308 GtkWidget*
309 gtk_tree_item_new_with_label (gchar *label)
310 {
311   GtkWidget *tree_item;
312   GtkWidget *label_widget;
313
314
315   tree_item = gtk_tree_item_new ();
316   label_widget = gtk_label_new (label);
317   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
318
319   gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
320   gtk_widget_show (label_widget);
321
322
323   return tree_item;
324 }
325
326 void
327 gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
328                            GtkWidget   *subtree)
329 {
330   g_return_if_fail (tree_item != NULL);
331   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
332
333   if(tree_item->subtree) {
334     g_warning("there is already a subtree for this tree item\n");
335     return;
336   }
337
338   tree_item->subtree = subtree; 
339   GTK_TREE(subtree)->tree_owner = GTK_WIDGET(tree_item);
340
341   /* set root tree for selection list */
342   GTK_TREE(subtree)->root_tree = GTK_TREE(GTK_WIDGET(tree_item)->parent)->root_tree;
343
344   /* show subtree button */
345   if(tree_item->pixmaps_box)
346     gtk_widget_show(tree_item->pixmaps_box);
347
348   /* set parent widget */
349   gtk_widget_set_parent(subtree, GTK_WIDGET(tree_item)->parent);
350
351   if(GTK_WIDGET_VISIBLE(GTK_WIDGET(tree_item))) 
352     {
353       if(GTK_WIDGET_REALIZED (GTK_WIDGET(tree_item)) &&
354          !GTK_WIDGET_REALIZED (GTK_WIDGET(subtree)))
355         gtk_widget_realize (GTK_WIDGET(subtree));
356
357       if(GTK_WIDGET_MAPPED (GTK_WIDGET(tree_item)) &&
358          !GTK_WIDGET_MAPPED (GTK_WIDGET(subtree)))
359         gtk_widget_map (GTK_WIDGET(subtree));
360     }
361
362   if(tree_item->expanded)
363     gtk_widget_show(subtree);
364   else
365     gtk_widget_hide(subtree);
366   
367   if (GTK_WIDGET_VISIBLE (tree_item) && GTK_WIDGET_VISIBLE (tree_item))
368     gtk_widget_queue_resize (GTK_WIDGET(tree_item));
369
370 }
371
372 void
373 gtk_tree_item_select (GtkTreeItem *tree_item)
374 {
375
376   gtk_item_select (GTK_ITEM (tree_item));
377
378 }
379
380 void
381 gtk_tree_item_deselect (GtkTreeItem *tree_item)
382 {
383
384   gtk_item_deselect (GTK_ITEM (tree_item));
385
386 }
387
388 void
389 gtk_tree_item_expand (GtkTreeItem *tree_item)
390 {
391
392   gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[EXPAND_TREE], NULL);
393
394 }
395
396 void
397 gtk_tree_item_collapse (GtkTreeItem *tree_item)
398 {
399
400   gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[COLLAPSE_TREE], NULL);
401
402 }
403
404 static void
405 gtk_tree_item_realize (GtkWidget *widget)
406 {    
407   g_return_if_fail (widget != NULL);
408   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
409
410   if (GTK_WIDGET_CLASS (parent_class)->realize)
411     (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
412   
413   gdk_window_set_background (widget->window, 
414                              &widget->style->base[GTK_STATE_NORMAL]);
415 }
416
417 static void
418 gtk_tree_item_size_request (GtkWidget      *widget,
419                             GtkRequisition *requisition)
420 {
421   GtkBin *bin;
422   GtkTreeItem* item;
423
424   g_return_if_fail (widget != NULL);
425   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
426   g_return_if_fail (requisition != NULL);
427
428   bin = GTK_BIN (widget);
429   item = GTK_TREE_ITEM(widget);
430
431   requisition->width = (GTK_CONTAINER (widget)->border_width +
432                         widget->style->klass->xthickness) * 2;
433   requisition->height = GTK_CONTAINER (widget)->border_width * 2;
434
435   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
436     {
437       gtk_widget_size_request (bin->child, &bin->child->requisition);
438
439       requisition->width += bin->child->requisition.width;
440
441       gtk_widget_size_request (item->pixmaps_box, 
442                                &item->pixmaps_box->requisition);
443       requisition->width += item->pixmaps_box->requisition.width + DEFAULT_DELTA + 
444         GTK_TREE(widget->parent)->current_indent;
445
446       requisition->height += MAX(bin->child->requisition.height,
447                                  item->pixmaps_box->requisition.height);
448     }
449 }
450
451 static void
452 gtk_tree_item_size_allocate (GtkWidget     *widget,
453                              GtkAllocation *allocation)
454 {
455   GtkBin *bin;
456   GtkTreeItem* item;
457   GtkAllocation child_allocation;
458   guint border_width;
459   int temp;
460
461   g_return_if_fail (widget != NULL);
462   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
463   g_return_if_fail (allocation != NULL);
464
465   widget->allocation = *allocation;
466   if (GTK_WIDGET_REALIZED (widget))
467     gdk_window_move_resize (widget->window,
468                             allocation->x, allocation->y,
469                             allocation->width, allocation->height);
470
471   bin = GTK_BIN (widget);
472   item = GTK_TREE_ITEM(widget);
473
474   if (bin->child)
475     {
476       border_width = (GTK_CONTAINER (widget)->border_width +
477                       widget->style->klass->xthickness);
478
479       child_allocation.x = border_width + GTK_TREE(widget->parent)->current_indent;
480       child_allocation.y = GTK_CONTAINER (widget)->border_width;
481
482 #if 0
483       child_allocation.height = allocation->height - child_allocation.y * 2;
484       child_allocation.width = item->pixmaps_box->requisition.width;
485
486       child_allocation.y += 1;
487       child_allocation.height -= 2;
488       gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
489
490       child_allocation.height += 2;
491 #else
492       child_allocation.width = item->pixmaps_box->requisition.width;
493       child_allocation.height = item->pixmaps_box->requisition.height;
494       
495       temp = allocation->height - child_allocation.height;
496       child_allocation.y += ( temp / 2 ) + ( temp % 2 );
497
498       gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
499
500       child_allocation.y = GTK_CONTAINER (widget)->border_width;
501       child_allocation.height = allocation->height - child_allocation.y * 2;
502 #endif
503       child_allocation.x += item->pixmaps_box->requisition.width+DEFAULT_DELTA;
504
505       child_allocation.width = 
506         allocation->width - (child_allocation.x + border_width);
507
508       gtk_widget_size_allocate (bin->child, &child_allocation);
509     }
510
511 }
512
513 static void 
514 gtk_tree_item_draw_lines(GtkWidget *widget) 
515 {
516   GtkTreeItem* item;
517   GtkTree* tree;
518   guint lx1, ly1, lx2, ly2;
519
520   item = GTK_TREE_ITEM(widget);
521   tree = GTK_TREE(widget->parent);
522
523   /* draw vertical line */
524   lx1 = item->pixmaps_box->allocation.width;
525   lx1 = lx2 = ( lx1 / 2 ) + ( lx1 % 2 ) + 
526     GTK_CONTAINER(widget)->border_width + 1 + tree->current_indent;
527   ly1 = 0;
528   ly2 = widget->allocation.height;
529
530   if(g_list_last(tree->children)->data == (gpointer)widget)
531     ly2 = (ly2 / 2) + (ly2 % 2);
532
533   if(tree != tree->root_tree)
534     gdk_draw_line(widget->window, widget->style->black_gc,
535                   lx1, ly1, lx2, ly2);
536
537   /* draw vertical line for subtree connecting */
538   if(g_list_last(tree->children)->data != (gpointer)widget)
539     ly2 = (ly2 / 2) + (ly2 % 2);
540   
541   lx2 += DEFAULT_DELTA;
542
543   if(item->subtree && item->expanded)
544     gdk_draw_line(widget->window, widget->style->black_gc,
545                   lx2, ly2, lx2, widget->allocation.height);
546
547   /* draw horizontal line */
548   ly1 = ly2;
549   lx2 += 2;
550
551   gdk_draw_line(widget->window, widget->style->black_gc,
552                 lx1, ly1, lx2, ly2);
553
554   lx2 -= DEFAULT_DELTA+2;
555   ly1 = 0;
556   ly2 = widget->allocation.height;
557
558   if(tree != tree->root_tree)
559     {
560       item = GTK_TREE_ITEM(tree->tree_owner);
561       tree = GTK_TREE(GTK_WIDGET(tree)->parent);
562       while(tree != tree->root_tree) {
563         lx1 = lx2 -= tree->indent_value;
564       
565         if(g_list_last(tree->children)->data != (gpointer)item)
566           gdk_draw_line(widget->window, widget->style->black_gc,
567                         lx1, ly1, lx2, ly2);
568         item = GTK_TREE_ITEM(tree->tree_owner);
569         tree = GTK_TREE(GTK_WIDGET(tree)->parent);
570       } 
571     }
572 }
573
574 static void
575 gtk_tree_item_draw (GtkWidget    *widget,
576                     GdkRectangle *area)
577 {
578   GtkBin *bin;
579   GdkRectangle child_area, item_area;
580   GtkTreeItem* tree_item;
581
582   g_return_if_fail (widget != NULL);
583   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
584   g_return_if_fail (area != NULL);
585
586   if (GTK_WIDGET_DRAWABLE (widget))
587     {
588       bin = GTK_BIN (widget);
589       tree_item = GTK_TREE_ITEM(widget);
590
591       /* draw left size of tree item */
592       item_area.x = 0; item_area.y = 0;
593       item_area.width = tree_item->pixmaps_box->allocation.width+DEFAULT_DELTA +
594         (GTK_TREE(widget->parent)->current_indent + 2);
595       item_area.height = widget->allocation.height;
596
597       if(gdk_rectangle_intersect(&item_area, area, &child_area)) {
598         
599         if (!GTK_WIDGET_IS_SENSITIVE (widget)) 
600           gtk_style_set_background (widget->style, widget->window, 
601                                     GTK_STATE_INSENSITIVE);
602         else if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_LINE &&
603                 widget->state == GTK_STATE_SELECTED)
604           gtk_style_set_background (widget->style, widget->window, widget->state);
605         else
606           gdk_window_set_background (widget->window, 
607                                      &widget->style->base[GTK_STATE_NORMAL]);
608
609         gdk_window_clear_area (widget->window, 
610                                child_area.x, child_area.y,
611                                child_area.width, child_area.height);
612
613 /*      gtk_tree_item_draw_lines(widget); */
614
615         if (tree_item->pixmaps_box && 
616             GTK_WIDGET_VISIBLE(tree_item->pixmaps_box) &&
617             gtk_widget_intersect (tree_item->pixmaps_box, area, &child_area))
618           gtk_widget_draw (tree_item->pixmaps_box, &child_area);
619       }
620
621       /* draw right side */
622       if(gtk_widget_intersect (bin->child, area, &child_area)) {
623
624         if (!GTK_WIDGET_IS_SENSITIVE (widget)) 
625           gtk_style_set_background (widget->style, widget->window, 
626                                     GTK_STATE_INSENSITIVE);
627         else if (widget->state == GTK_STATE_NORMAL)
628           gdk_window_set_background(widget->window, &widget->style->base[GTK_STATE_NORMAL]);
629         else
630           gtk_style_set_background (widget->style, widget->window, widget->state);
631
632         gdk_window_clear_area (widget->window, child_area.x, child_area.y,
633                                child_area.width+1, child_area.height);
634
635         if (bin->child && 
636             GTK_WIDGET_VISIBLE(bin->child) &&
637             gtk_widget_intersect (bin->child, area, &child_area))
638           gtk_widget_draw (bin->child, &child_area);
639       }
640
641       gtk_widget_draw_focus (widget);
642     }
643 }
644
645 static void
646 gtk_tree_item_draw_focus (GtkWidget *widget)
647 {
648   GdkGC *gc;
649   int dx;
650
651   g_return_if_fail (widget != NULL);
652   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
653
654   if (GTK_WIDGET_DRAWABLE (widget))
655     {
656       if (GTK_WIDGET_HAS_FOCUS (widget))
657         gc = widget->style->black_gc;
658       else if (!GTK_WIDGET_IS_SENSITIVE (widget))
659         gc = widget->style->bg_gc[GTK_STATE_INSENSITIVE];
660       else if (widget->state == GTK_STATE_NORMAL)
661         gc = widget->style->base_gc[GTK_STATE_NORMAL];
662       else
663         gc = widget->style->bg_gc[widget->state];
664
665       dx = 0;
666
667       if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_ITEM) 
668         dx = GTK_TREE_ITEM(widget)->pixmaps_box->allocation.width + DEFAULT_DELTA +
669           GTK_TREE(widget->parent)->current_indent+1;
670
671       gdk_draw_rectangle (widget->window, gc, FALSE, dx, 0,
672                           widget->allocation.width - 1 - dx,
673                           widget->allocation.height - 1);
674
675       if(GTK_TREE(widget->parent)->view_line) 
676         gtk_tree_item_draw_lines(widget);
677     }
678 }
679
680 static gint
681 gtk_tree_item_button_press (GtkWidget      *widget,
682                             GdkEventButton *event)
683 {
684
685   g_return_val_if_fail (widget != NULL, FALSE);
686   g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
687   g_return_val_if_fail (event != NULL, FALSE);
688
689   if (event->type == GDK_BUTTON_PRESS
690         && GTK_WIDGET_IS_SENSITIVE(widget)
691         && !GTK_WIDGET_HAS_FOCUS (widget))
692       gtk_widget_grab_focus (widget);
693
694   return FALSE;
695 }
696
697 static gint
698 gtk_tree_item_expose (GtkWidget      *widget,
699                       GdkEventExpose *event)
700 {
701   g_return_val_if_fail (widget != NULL, FALSE);
702   g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
703   g_return_val_if_fail (event != NULL, FALSE);
704
705   if (GTK_WIDGET_DRAWABLE (widget))
706     gtk_tree_item_draw(widget, &event->area);
707
708   return FALSE;
709 }
710
711 static gint
712 gtk_tree_item_focus_in (GtkWidget     *widget,
713                         GdkEventFocus *event)
714 {
715
716   g_return_val_if_fail (widget != NULL, FALSE);
717   g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
718   g_return_val_if_fail (event != NULL, FALSE);
719
720   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
721   gtk_widget_draw_focus (widget);
722
723
724   return FALSE;
725 }
726
727 static gint
728 gtk_tree_item_focus_out (GtkWidget     *widget,
729                          GdkEventFocus *event)
730 {
731
732   g_return_val_if_fail (widget != NULL, FALSE);
733   g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
734   g_return_val_if_fail (event != NULL, FALSE);
735
736   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
737   gtk_widget_draw_focus (widget);
738
739
740   return FALSE;
741 }
742
743 static void
744 gtk_real_tree_item_select (GtkItem *item)
745 {
746     
747   g_return_if_fail (item != NULL);
748   g_return_if_fail (GTK_IS_TREE_ITEM (item));
749
750   if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED
751         || !GTK_WIDGET_IS_SENSITIVE(item))
752     return;
753
754   if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
755     gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_SELECTED);
756
757   gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
758
759   gtk_widget_queue_draw (GTK_WIDGET (item));
760 }
761
762 static void
763 gtk_real_tree_item_deselect (GtkItem *item)
764 {
765
766   g_return_if_fail (item != NULL);
767   g_return_if_fail (GTK_IS_TREE_ITEM (item));
768
769   if (GTK_WIDGET (item)->state == GTK_STATE_NORMAL)
770     return;
771
772   if(GTK_WIDGET_MAPPED(GTK_WIDGET (item))) 
773     {
774       gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
775       
776       if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
777         gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_NORMAL);
778
779       gtk_widget_queue_draw (GTK_WIDGET (item));
780     }
781 }
782
783 static void
784 gtk_real_tree_item_toggle (GtkItem *item)
785 {
786
787   g_return_if_fail (item != NULL);
788   g_return_if_fail (GTK_IS_TREE_ITEM (item));
789
790   if(!GTK_WIDGET_IS_SENSITIVE(item))
791     return;
792
793   if (GTK_WIDGET (item)->parent && GTK_IS_TREE (GTK_WIDGET (item)->parent))
794     gtk_tree_select_child (GTK_TREE (GTK_WIDGET (item)->parent),
795                            GTK_WIDGET (item));
796   else
797     {
798       /* Should we really bother with this bit? A listitem not in a list?
799        * -Johannes Keukelaar
800        * yes, always be on the save side!
801        * -timj
802        */
803       if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
804         gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
805       else
806         gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
807       gtk_widget_queue_draw (GTK_WIDGET (item));
808     }
809 }
810
811 static void
812 gtk_tree_item_marshal_signal (GtkObject      *object,
813                               GtkSignalFunc   func,
814                               gpointer        func_data,
815                               GtkArg         *args)
816 {
817   GtkTreeItemSignal rfunc;
818
819   rfunc = (GtkTreeItemSignal) func;
820
821   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
822 }
823
824 static void
825 gtk_real_tree_item_expand (GtkTreeItem *tree_item)
826 {
827   GtkTree* tree;
828   
829   g_return_if_fail (tree_item != NULL);
830   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
831   g_return_if_fail (tree_item->subtree != NULL);
832
833
834   if(!tree_item->expanded) 
835     {
836       tree = GTK_TREE(GTK_WIDGET(tree_item)->parent); 
837
838       /* hide subtree widget */
839       gtk_widget_show(tree_item->subtree);
840
841       /* hide button '+' and show button '-' */
842       if(tree_item->pixmaps_box) {
843         gtk_container_remove(GTK_CONTAINER(tree_item->pixmaps_box), 
844                              tree_item->plus_pix_widget);
845         gtk_container_add(GTK_CONTAINER(tree_item->pixmaps_box), 
846                           tree_item->minus_pix_widget);
847       }
848       if(tree->root_tree) gtk_widget_queue_resize(GTK_WIDGET(tree->root_tree));
849       tree_item->expanded = TRUE;
850     }
851 }
852
853 static void
854 gtk_real_tree_item_collapse (GtkTreeItem *tree_item)
855 {
856   GtkTree* tree;
857
858   g_return_if_fail (tree_item != NULL);
859   g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
860   g_return_if_fail (tree_item->subtree != NULL);
861
862   if(tree_item->expanded) 
863     {
864       tree = GTK_TREE(GTK_WIDGET(tree_item)->parent);
865
866       /* hide subtree widget */
867       gtk_widget_hide(tree_item->subtree);
868
869       /* hide button '-' and show button '+' */
870       if(tree_item->pixmaps_box) {
871         gtk_container_remove(GTK_CONTAINER(tree_item->pixmaps_box), 
872                              tree_item->minus_pix_widget);
873         gtk_container_add(GTK_CONTAINER(tree_item->pixmaps_box), 
874                           tree_item->plus_pix_widget);
875       }
876       if(tree->root_tree) gtk_widget_queue_resize(GTK_WIDGET(tree->root_tree));
877       tree_item->expanded = FALSE;
878     }
879
880 }
881
882 static void
883 gtk_tree_item_destroy (GtkObject *object)
884 {
885   GtkTreeItem* item;
886   GtkWidget* child;
887
888   g_return_if_fail (object != NULL);
889   g_return_if_fail (GTK_IS_TREE_ITEM (object));
890
891   item = GTK_TREE_ITEM(object);
892
893   /* free sub tree if it exist */
894   if((child = item->subtree)) 
895     {
896       gtk_widget_ref (child);
897       gtk_widget_unparent (child);
898       gtk_widget_destroy (child);
899       gtk_widget_unref (child);
900       item->subtree = NULL;
901     }
902
903   /* free pixmaps box */
904   if((child = item->pixmaps_box))
905     {
906       gtk_widget_ref (child);
907       gtk_widget_unparent (child);
908       gtk_widget_destroy (child);
909       gtk_widget_unref (child);
910       item->pixmaps_box = NULL;
911     }
912
913   /* destroy plus pixmap */
914   if (item->plus_pix_widget)
915     {
916       gtk_widget_destroy (item->plus_pix_widget);
917       gtk_widget_unref (item->plus_pix_widget);
918       item->plus_pix_widget = NULL;
919     }
920
921   /* destroy minus pixmap */
922   if (item->minus_pix_widget)
923     {
924       gtk_widget_destroy (item->minus_pix_widget);
925       gtk_widget_unref (item->minus_pix_widget);
926       item->minus_pix_widget = NULL;
927     }
928   
929   if (GTK_OBJECT_CLASS (parent_class)->destroy)
930     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
931
932 }
933
934 void
935 gtk_tree_item_remove_subtree (GtkTreeItem* item) 
936 {
937   g_return_if_fail(item != NULL);
938   g_return_if_fail(GTK_IS_TREE_ITEM(item));
939   g_return_if_fail(item->subtree);
940
941   if(GTK_TREE(item->subtree)->children)
942     gtk_tree_remove_items(GTK_TREE(item->subtree), 
943                           GTK_TREE(item->subtree)->children);
944
945   if (GTK_WIDGET_MAPPED (item->subtree))
946     gtk_widget_unmap (item->subtree);
947
948   gtk_widget_unparent (item->subtree);
949
950   if(item->pixmaps_box)
951     gtk_widget_hide(item->pixmaps_box);
952
953   item->subtree = NULL;
954   item->expanded = FALSE;
955   if(item->pixmaps_box) {
956     gtk_container_remove(GTK_CONTAINER(item->pixmaps_box), 
957                          item->minus_pix_widget);
958     gtk_container_add(GTK_CONTAINER(item->pixmaps_box), 
959                       item->plus_pix_widget);
960   }
961 }
962
963 static void
964 gtk_tree_item_map (GtkWidget *widget)
965 {
966   GtkBin *bin;
967   GtkTreeItem* item;
968
969   g_return_if_fail (widget != NULL);
970   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
971
972   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
973   bin = GTK_BIN (widget);
974   item = GTK_TREE_ITEM(widget);
975
976   if (!GTK_WIDGET_NO_WINDOW (widget))
977     gdk_window_show (widget->window);
978   else
979     gtk_widget_queue_draw (widget);
980
981   if(item->pixmaps_box &&
982      GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
983      !GTK_WIDGET_MAPPED (item->pixmaps_box))
984     gtk_widget_map (item->pixmaps_box);
985
986   if (bin->child &&
987       GTK_WIDGET_VISIBLE (bin->child) &&
988       !GTK_WIDGET_MAPPED (bin->child))
989     gtk_widget_map (bin->child);
990 }
991
992 static void
993 gtk_tree_item_unmap (GtkWidget *widget)
994 {
995   GtkBin *bin;
996   GtkTreeItem* item;
997
998   g_return_if_fail (widget != NULL);
999   g_return_if_fail (GTK_IS_TREE_ITEM (widget));
1000
1001   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1002   bin = GTK_BIN (widget);
1003   item = GTK_TREE_ITEM(widget);
1004
1005   if (GTK_WIDGET_NO_WINDOW (widget))
1006     gdk_window_clear_area (widget->window,
1007                            widget->allocation.x,
1008                            widget->allocation.y,
1009                            widget->allocation.width,
1010                            widget->allocation.height);
1011   else
1012     gdk_window_hide (widget->window);
1013
1014   if(item->pixmaps_box &&
1015      GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1016      GTK_WIDGET_MAPPED (item->pixmaps_box))
1017     gtk_widget_unmap (bin->child);
1018
1019   if (bin->child &&
1020       GTK_WIDGET_VISIBLE (bin->child) &&
1021       GTK_WIDGET_MAPPED (bin->child))
1022     gtk_widget_unmap (bin->child);
1023 }