]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/lablgtk/lablgtk_20000829-0.1.0/applications/radtest/gtktreeitem2.c
Initial revision
[helm.git] / helm / DEVEL / lablgtk / lablgtk_20000829-0.1.0 / applications / radtest / gtktreeitem2.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <gtk/gtklabel.h>
28 #include "gtktree2.h"
29 #include "gtktreeitem2.h"
30 #include <gtk/gtkeventbox.h>
31 #include <gtk/gtkpixmap.h>
32 #include <gtk/gtkmain.h>
33 #include <gtk/gtksignal.h>
34
35 #include "tree_plus.xpm"
36 #include "tree_minus.xpm"
37
38 #define DEFAULT_DELTA 9
39
40 enum {
41   COLLAPSE_TREE,
42   EXPAND_TREE,
43   LAST_SIGNAL
44 };
45
46 typedef struct _GtkTree2Pixmaps GtkTree2Pixmaps;
47
48 struct _GtkTree2Pixmaps {
49   gint refcount;
50   GdkColormap *colormap;
51   
52   GdkPixmap *pixmap_plus;
53   GdkPixmap *pixmap_minus;
54   GdkBitmap *mask_plus;
55   GdkBitmap *mask_minus;
56 };
57
58 static GList *pixmaps = NULL;
59
60 static void gtk_tree_item2_class_init (GtkTreeItem2Class *klass);
61 static void gtk_tree_item2_init       (GtkTreeItem2      *tree_item);
62 static void gtk_tree_item2_realize       (GtkWidget        *widget);
63 static void gtk_tree_item2_size_request  (GtkWidget        *widget,
64                                          GtkRequisition   *requisition);
65 static void gtk_tree_item2_size_allocate (GtkWidget        *widget,
66                                          GtkAllocation    *allocation);
67 static void gtk_tree_item2_draw          (GtkWidget        *widget,
68                                          GdkRectangle     *area);
69 static void gtk_tree_item2_draw_focus    (GtkWidget        *widget);
70 static void gtk_tree_item2_paint         (GtkWidget        *widget,
71                                          GdkRectangle     *area);
72 static gint gtk_tree_item2_button_press  (GtkWidget        *widget,
73                                          GdkEventButton   *event);
74 static gint gtk_tree_item2_expose        (GtkWidget        *widget,
75                                          GdkEventExpose   *event);
76 static gint gtk_tree_item2_focus_in      (GtkWidget        *widget,
77                                          GdkEventFocus    *event);
78 static gint gtk_tree_item2_focus_out     (GtkWidget        *widget,
79                                          GdkEventFocus    *event);
80 static void gtk_tree_item2_forall        (GtkContainer    *container,
81                                          gboolean         include_internals,
82                                          GtkCallback      callback,
83                                          gpointer         callback_data);
84
85 static void gtk_real_tree_item2_select   (GtkItem          *item);
86 static void gtk_real_tree_item2_deselect (GtkItem          *item);
87 static void gtk_real_tree_item2_toggle   (GtkItem          *item);
88 static void gtk_real_tree_item2_expand   (GtkTreeItem2      *item);
89 static void gtk_real_tree_item2_collapse (GtkTreeItem2      *item);
90 static void gtk_real_tree_item2_expand   (GtkTreeItem2      *item);
91 static void gtk_real_tree_item2_collapse (GtkTreeItem2      *item);
92 static void gtk_tree_item2_destroy        (GtkObject *object);
93 static void gtk_tree_item2_subtree_button_click (GtkWidget *widget);
94 static void gtk_tree_item2_subtree_button_changed_state (GtkWidget *widget);
95
96 static void gtk_tree_item2_map(GtkWidget*);
97 static void gtk_tree_item2_unmap(GtkWidget*);
98
99 static void gtk_tree_item2_add_pixmaps    (GtkTreeItem2       *tree_item);
100 static void gtk_tree_item2_remove_pixmaps (GtkTreeItem2       *tree_item);
101
102 static GtkItemClass *parent_class = NULL;
103 static guint tree_item_signals[LAST_SIGNAL] = { 0 };
104
105 GtkType
106 gtk_tree_item2_get_type (void)
107 {
108   static GtkType tree_item_type = 0;
109
110   if (!tree_item_type)
111     {
112       static const GtkTypeInfo tree_item_info =
113       {
114         "GtkTreeItem",
115         sizeof (GtkTreeItem2),
116         sizeof (GtkTreeItem2Class),
117         (GtkClassInitFunc) gtk_tree_item2_class_init,
118         (GtkObjectInitFunc) gtk_tree_item2_init,
119         /* reserved_1 */ NULL,
120         /* reserved_2 */ NULL,
121         (GtkClassInitFunc) NULL,
122       };
123
124       tree_item_type = gtk_type_unique (gtk_item_get_type (), &tree_item_info);
125     }
126
127   return tree_item_type;
128 }
129
130 static void
131 gtk_tree_item2_class_init (GtkTreeItem2Class *class)
132 {
133   GtkObjectClass *object_class;
134   GtkWidgetClass *widget_class;
135   GtkContainerClass *container_class;
136   GtkItemClass *item_class;
137
138   object_class = (GtkObjectClass*) class;
139   widget_class = (GtkWidgetClass*) class;
140   item_class = (GtkItemClass*) class;
141   container_class = (GtkContainerClass*) class;
142
143   parent_class = gtk_type_class (gtk_item_get_type ());
144   
145   tree_item_signals[EXPAND_TREE] =
146     gtk_signal_new ("expand",
147                     GTK_RUN_FIRST,
148                     object_class->type,
149                     GTK_SIGNAL_OFFSET (GtkTreeItem2Class, expand),
150                     gtk_marshal_NONE__NONE,
151                     GTK_TYPE_NONE, 0);
152   tree_item_signals[COLLAPSE_TREE] =
153     gtk_signal_new ("collapse",
154                     GTK_RUN_FIRST,
155                     object_class->type,
156                     GTK_SIGNAL_OFFSET (GtkTreeItem2Class, collapse),
157                     gtk_marshal_NONE__NONE,
158                     GTK_TYPE_NONE, 0);
159
160   gtk_object_class_add_signals (object_class, tree_item_signals, LAST_SIGNAL);
161
162   object_class->destroy = gtk_tree_item2_destroy;
163
164   widget_class->realize = gtk_tree_item2_realize;
165   widget_class->size_request = gtk_tree_item2_size_request;
166   widget_class->size_allocate = gtk_tree_item2_size_allocate;
167   widget_class->draw = gtk_tree_item2_draw;
168   widget_class->draw_focus = gtk_tree_item2_draw_focus;
169   widget_class->button_press_event = gtk_tree_item2_button_press;
170   widget_class->expose_event = gtk_tree_item2_expose;
171   widget_class->focus_in_event = gtk_tree_item2_focus_in;
172   widget_class->focus_out_event = gtk_tree_item2_focus_out;
173   widget_class->map = gtk_tree_item2_map;
174   widget_class->unmap = gtk_tree_item2_unmap;
175
176   container_class->forall = gtk_tree_item2_forall;
177
178   item_class->select = gtk_real_tree_item2_select;
179   item_class->deselect = gtk_real_tree_item2_deselect;
180   item_class->toggle = gtk_real_tree_item2_toggle;
181
182   class->expand = gtk_real_tree_item2_expand;
183   class->collapse = gtk_real_tree_item2_collapse;
184 }
185
186 /* callback for event box mouse event */
187 static void 
188 gtk_tree_item2_subtree_button_click (GtkWidget *widget)
189 {
190   GtkTreeItem2* item;
191   
192   g_return_if_fail (widget != NULL);
193   g_return_if_fail (GTK_IS_EVENT_BOX (widget));
194   
195   item = (GtkTreeItem2*) gtk_object_get_user_data (GTK_OBJECT (widget));
196   if (!GTK_WIDGET_IS_SENSITIVE (item))
197     return;
198   
199   if (item->expanded)
200     gtk_tree_item2_collapse (item);
201   else
202     gtk_tree_item2_expand (item);
203 }
204
205 /* callback for event box state changed */
206 static void
207 gtk_tree_item2_subtree_button_changed_state (GtkWidget *widget)
208 {
209   g_return_if_fail (widget != NULL);
210   g_return_if_fail (GTK_IS_EVENT_BOX (widget));
211   
212   if (GTK_WIDGET_VISIBLE (widget))
213     {
214       
215       if (widget->state == GTK_STATE_NORMAL)
216         gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
217       else
218         gdk_window_set_background (widget->window, &widget->style->bg[widget->state]);
219       
220       if (GTK_WIDGET_DRAWABLE (widget))
221         gdk_window_clear_area (widget->window, 0, 0, 
222                                widget->allocation.width, widget->allocation.height);
223     }
224 }
225
226 static void
227 gtk_tree_item2_init (GtkTreeItem2 *tree_item)
228 {
229   GtkWidget *eventbox, *pixmapwid;
230   
231   g_return_if_fail (tree_item != NULL);
232   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
233
234   tree_item->expanded = FALSE;
235   tree_item->subtree = NULL;
236   GTK_WIDGET_SET_FLAGS (tree_item, GTK_CAN_FOCUS);
237   
238   /* create an event box containing one pixmaps */
239   eventbox = gtk_event_box_new();
240   gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);
241   gtk_signal_connect(GTK_OBJECT(eventbox), "state_changed",
242                      (GtkSignalFunc)gtk_tree_item2_subtree_button_changed_state, 
243                      (gpointer)NULL);
244   gtk_signal_connect(GTK_OBJECT(eventbox), "realize",
245                      (GtkSignalFunc)gtk_tree_item2_subtree_button_changed_state, 
246                      (gpointer)NULL);
247 /* HF inutile
248   gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
249                      (GtkSignalFunc)gtk_tree_item2_subtree_button_click,
250                      (gpointer)NULL);
251 */
252   gtk_object_set_user_data(GTK_OBJECT(eventbox), tree_item);
253   tree_item->pixmaps_box = eventbox;
254
255   /* create pixmap for button '+' */
256   pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
257   if (!tree_item->expanded) 
258     gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
259   gtk_widget_show (pixmapwid);
260   tree_item->plus_pix_widget = pixmapwid;
261   gtk_widget_ref (tree_item->plus_pix_widget);
262   gtk_object_sink (GTK_OBJECT (tree_item->plus_pix_widget));
263   
264   /* create pixmap for button '-' */
265   pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
266   if (tree_item->expanded) 
267     gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
268   gtk_widget_show (pixmapwid);
269   tree_item->minus_pix_widget = pixmapwid;
270   gtk_widget_ref (tree_item->minus_pix_widget);
271   gtk_object_sink (GTK_OBJECT (tree_item->minus_pix_widget));
272   
273   gtk_widget_set_parent (eventbox, GTK_WIDGET (tree_item));
274 }
275
276
277 GtkWidget*
278 gtk_tree_item2_new (void)
279 {
280   GtkWidget *tree_item;
281
282   tree_item = GTK_WIDGET (gtk_type_new (gtk_tree_item2_get_type ()));
283
284   return tree_item;
285 }
286
287 GtkWidget*
288 gtk_tree_item2_new_with_label (gchar *label)
289 {
290   GtkWidget *tree_item;
291   GtkWidget *label_widget;
292
293   tree_item = gtk_tree_item2_new ();
294   label_widget = gtk_label_new (label);
295   gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
296
297   gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
298   gtk_widget_show (label_widget);
299
300
301   return tree_item;
302 }
303
304 void
305 gtk_tree_item2_set_subtree (GtkTreeItem2 *tree_item,
306                            GtkWidget   *subtree)
307 {
308   g_return_if_fail (tree_item != NULL);
309   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
310   g_return_if_fail (subtree != NULL);
311   g_return_if_fail (GTK_IS_TREE2 (subtree));
312
313   if (tree_item->subtree)
314     {
315       g_warning("there is already a subtree for this tree item\n");
316       return;
317     }
318
319   tree_item->subtree = subtree; 
320   GTK_TREE2 (subtree)->tree_owner = GTK_WIDGET (tree_item);
321
322   /* show subtree button */
323   if (tree_item->pixmaps_box)
324     gtk_widget_show (tree_item->pixmaps_box);
325
326   if (tree_item->expanded)
327     gtk_widget_show (subtree);
328   else
329     gtk_widget_hide (subtree);
330
331   gtk_widget_set_parent (subtree, GTK_WIDGET (tree_item)->parent);
332
333   if (GTK_WIDGET_REALIZED (subtree->parent))
334     gtk_widget_realize (subtree);
335
336   if (GTK_WIDGET_VISIBLE (subtree->parent) && GTK_WIDGET_VISIBLE (subtree))
337     {
338       if (GTK_WIDGET_MAPPED (subtree->parent))
339         gtk_widget_map (subtree);
340
341       gtk_widget_queue_resize (subtree);
342     }
343 }
344
345 void
346 gtk_tree_item2_select (GtkTreeItem2 *tree_item)
347 {
348   g_return_if_fail (tree_item != NULL);
349   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
350
351   gtk_item_select (GTK_ITEM (tree_item));
352 }
353
354 void
355 gtk_tree_item2_deselect (GtkTreeItem2 *tree_item)
356 {
357   g_return_if_fail (tree_item != NULL);
358   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
359
360   gtk_item_deselect (GTK_ITEM (tree_item));
361 }
362
363 void
364 gtk_tree_item2_expand (GtkTreeItem2 *tree_item)
365 {
366   g_return_if_fail (tree_item != NULL);
367   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
368
369   gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[EXPAND_TREE], NULL);
370 }
371
372 void
373 gtk_tree_item2_collapse (GtkTreeItem2 *tree_item)
374 {
375   g_return_if_fail (tree_item != NULL);
376   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
377
378   gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[COLLAPSE_TREE], NULL);
379 }
380
381 static void
382 gtk_tree_item2_add_pixmaps (GtkTreeItem2 *tree_item)
383 {
384   GList *tmp_list;
385   GdkColormap *colormap;
386   GtkTree2Pixmaps *pixmap_node = NULL;
387
388   g_return_if_fail (tree_item != NULL);
389   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
390
391   if (tree_item->pixmaps)
392     return;
393
394   colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_item));
395
396   tmp_list = pixmaps;
397   while (tmp_list)
398     {
399       pixmap_node = (GtkTree2Pixmaps *)tmp_list->data;
400
401       if (pixmap_node->colormap == colormap)
402         break;
403       
404       tmp_list = tmp_list->next;
405     }
406
407   if (tmp_list)
408     {
409       pixmap_node->refcount++;
410       tree_item->pixmaps = tmp_list;
411     }
412   else
413     {
414       pixmap_node = g_new (GtkTree2Pixmaps, 1);
415
416       pixmap_node->colormap = colormap;
417       gdk_colormap_ref (colormap);
418
419       pixmap_node->refcount = 1;
420
421       /* create pixmaps for plus icon */
422       pixmap_node->pixmap_plus = 
423         gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
424                                       &pixmap_node->mask_plus,
425                                       NULL,
426                                       tree_plus);
427       
428       /* create pixmaps for minus icon */
429       pixmap_node->pixmap_minus = 
430         gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
431                                       &pixmap_node->mask_minus,
432                                       NULL,
433                                       tree_minus);
434
435       tree_item->pixmaps = pixmaps = g_list_prepend (pixmaps, pixmap_node);
436     }
437   
438   gtk_pixmap_set (GTK_PIXMAP (tree_item->plus_pix_widget), 
439                   pixmap_node->pixmap_plus, pixmap_node->mask_plus);
440   gtk_pixmap_set (GTK_PIXMAP (tree_item->minus_pix_widget), 
441                   pixmap_node->pixmap_minus, pixmap_node->mask_minus);
442 }
443
444 static void
445 gtk_tree_item2_remove_pixmaps (GtkTreeItem2 *tree_item)
446 {
447   g_return_if_fail (tree_item != NULL);
448   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
449
450   if (tree_item->pixmaps)
451     {
452       GtkTree2Pixmaps *pixmap_node = (GtkTree2Pixmaps *)tree_item->pixmaps->data;
453       
454       g_assert (pixmap_node->refcount > 0);
455       
456       if (--pixmap_node->refcount == 0)
457         {
458           gdk_colormap_unref (pixmap_node->colormap);
459           gdk_pixmap_unref (pixmap_node->pixmap_plus);
460           gdk_bitmap_unref (pixmap_node->mask_plus);
461           gdk_pixmap_unref (pixmap_node->pixmap_minus);
462           gdk_bitmap_unref (pixmap_node->mask_minus);
463           
464           pixmaps = g_list_remove_link (pixmaps, tree_item->pixmaps);
465           g_list_free_1 (tree_item->pixmaps);
466           g_free (pixmap_node);
467         }
468
469       tree_item->pixmaps = NULL;
470     }
471 }
472
473 static void
474 gtk_tree_item2_realize (GtkWidget *widget)
475 {    
476   g_return_if_fail (widget != NULL);
477   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
478
479   if (GTK_WIDGET_CLASS (parent_class)->realize)
480     (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
481   
482   gdk_window_set_background (widget->window, 
483                              &widget->style->base[GTK_STATE_NORMAL]);
484
485   gtk_tree_item2_add_pixmaps (GTK_TREE_ITEM2 (widget));
486 }
487
488 static void
489 gtk_tree_item2_size_request (GtkWidget      *widget,
490                             GtkRequisition *requisition)
491 {
492   GtkBin *bin;
493   GtkTreeItem2* item;
494   GtkRequisition child_requisition;
495
496   g_return_if_fail (widget != NULL);
497   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
498   g_return_if_fail (requisition != NULL);
499
500   bin = GTK_BIN (widget);
501   item = GTK_TREE_ITEM2(widget);
502
503   requisition->width = (GTK_CONTAINER (widget)->border_width +
504                         widget->style->klass->xthickness) * 2;
505   requisition->height = GTK_CONTAINER (widget)->border_width * 2;
506
507   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
508     {
509       GtkRequisition pix_requisition;
510       
511       gtk_widget_size_request (bin->child, &child_requisition);
512
513       requisition->width += child_requisition.width;
514
515       gtk_widget_size_request (item->pixmaps_box, 
516                                &pix_requisition);
517       requisition->width += pix_requisition.width + DEFAULT_DELTA + 
518         GTK_TREE2 (widget->parent)->current_indent;
519
520       requisition->height += MAX (child_requisition.height,
521                                   pix_requisition.height);
522     }
523 }
524
525 static void
526 gtk_tree_item2_size_allocate (GtkWidget     *widget,
527                              GtkAllocation *allocation)
528 {
529   GtkBin *bin;
530   GtkTreeItem2* item;
531   GtkAllocation child_allocation;
532   guint border_width;
533   int temp;
534
535   g_return_if_fail (widget != NULL);
536   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
537   g_return_if_fail (allocation != NULL);
538
539   widget->allocation = *allocation;
540   if (GTK_WIDGET_REALIZED (widget))
541     gdk_window_move_resize (widget->window,
542                             allocation->x, allocation->y,
543                             allocation->width, allocation->height);
544
545   bin = GTK_BIN (widget);
546   item = GTK_TREE_ITEM2(widget);
547
548   if (bin->child)
549     {
550       border_width = (GTK_CONTAINER (widget)->border_width +
551                       widget->style->klass->xthickness);
552
553       child_allocation.x = border_width + GTK_TREE2(widget->parent)->current_indent;
554       child_allocation.y = GTK_CONTAINER (widget)->border_width;
555
556       child_allocation.width = item->pixmaps_box->requisition.width;
557       child_allocation.height = item->pixmaps_box->requisition.height;
558       
559       temp = allocation->height - child_allocation.height;
560       child_allocation.y += ( temp / 2 ) + ( temp % 2 );
561
562       gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
563
564       child_allocation.y = GTK_CONTAINER (widget)->border_width;
565       child_allocation.height = MAX (1, (gint)allocation->height - child_allocation.y * 2);
566       child_allocation.x += item->pixmaps_box->requisition.width+DEFAULT_DELTA;
567
568       child_allocation.width = 
569         MAX (1, (gint)allocation->width - ((gint)child_allocation.x + border_width));
570
571       gtk_widget_size_allocate (bin->child, &child_allocation);
572     }
573 }
574
575 static void 
576 gtk_tree_item2_draw_lines (GtkWidget *widget) 
577 {
578   GtkTreeItem2* item;
579   GtkTree2* tree;
580   guint lx1, ly1, lx2, ly2;
581
582   g_return_if_fail (widget != NULL);
583   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
584
585   item = GTK_TREE_ITEM2(widget);
586   tree = GTK_TREE2(widget->parent);
587
588   /* draw vertical line */
589   lx1 = item->pixmaps_box->allocation.width;
590   lx1 = lx2 = ((lx1 / 2) + (lx1 % 2) + 
591                GTK_CONTAINER (widget)->border_width + 1 + tree->current_indent);
592   ly1 = 0;
593   ly2 = widget->allocation.height;
594
595   if (g_list_last (tree->children)->data == widget)
596     ly2 = (ly2 / 2) + (ly2 % 2);
597
598   if (tree != tree->root_tree)
599     gdk_draw_line (widget->window, widget->style->black_gc, lx1, ly1, lx2, ly2);
600
601   /* draw vertical line for subtree connecting */
602   if(g_list_last(tree->children)->data != (gpointer)widget)
603     ly2 = (ly2 / 2) + (ly2 % 2);
604   
605   lx2 += DEFAULT_DELTA;
606
607   if (item->subtree && item->expanded)
608     gdk_draw_line (widget->window, widget->style->black_gc,
609                    lx2, ly2, lx2, widget->allocation.height);
610
611   /* draw horizontal line */
612   ly1 = ly2;
613   lx2 += 2;
614
615   gdk_draw_line (widget->window, widget->style->black_gc,
616                  lx1, ly1, lx2, ly2);
617
618   lx2 -= DEFAULT_DELTA+2;
619   ly1 = 0;
620   ly2 = widget->allocation.height;
621
622   if (tree != tree->root_tree)
623     {
624       item = GTK_TREE_ITEM2 (tree->tree_owner);
625       tree = GTK_TREE2 (GTK_WIDGET (tree)->parent);
626       while (tree != tree->root_tree)
627         {
628           lx1 = lx2 -= tree->indent_value;
629           
630           if (g_list_last (tree->children)->data != item)
631             gdk_draw_line (widget->window, widget->style->black_gc, lx1, ly1, lx2, ly2);
632           item = GTK_TREE_ITEM2 (tree->tree_owner);
633           tree = GTK_TREE2 (GTK_WIDGET (tree)->parent);
634         } 
635     }
636 }
637
638 static void
639 gtk_tree_item2_paint (GtkWidget    *widget,
640                      GdkRectangle *area)
641 {
642   GtkBin *bin;
643   GdkRectangle child_area, item_area;
644   GtkTreeItem2* tree_item;
645
646   g_return_if_fail (widget != NULL);
647   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
648   g_return_if_fail (area != NULL);
649
650   if (GTK_WIDGET_DRAWABLE (widget))
651     {
652       bin = GTK_BIN (widget);
653       tree_item = GTK_TREE_ITEM2(widget);
654
655       if (widget->state == GTK_STATE_NORMAL)
656         {
657           gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
658           gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
659         }
660       else 
661         {
662           if (!GTK_WIDGET_IS_SENSITIVE (widget)) 
663             gtk_paint_flat_box(widget->style, widget->window,
664                                widget->state, GTK_STATE_INSENSITIVE,
665                                area, widget, "treeitem",
666                                0, 0, -1, -1);
667           else
668             gtk_paint_flat_box(widget->style, widget->window,
669                                widget->state, GTK_SHADOW_ETCHED_OUT,
670                                area, widget, "treeitem",
671                                0, 0, -1, -1);
672         }
673
674       /* draw left size of tree item */
675       item_area.x = 0;
676       item_area.y = 0;
677       item_area.width = (tree_item->pixmaps_box->allocation.width + DEFAULT_DELTA +
678                          GTK_TREE2 (widget->parent)->current_indent + 2);
679       item_area.height = widget->allocation.height;
680
681
682       if (gdk_rectangle_intersect(&item_area, area, &child_area)) 
683         {
684           
685           gtk_tree_item2_draw_lines(widget);
686
687           if (tree_item->pixmaps_box && 
688               GTK_WIDGET_VISIBLE(tree_item->pixmaps_box) &&
689               gtk_widget_intersect (tree_item->pixmaps_box, area, &child_area))
690             gtk_widget_draw (tree_item->pixmaps_box, &child_area);
691         }
692
693       if (GTK_WIDGET_HAS_FOCUS (widget))
694         gtk_paint_focus (widget->style, widget->window,
695                          NULL, widget, "treeitem",
696                          0, 0,
697                          widget->allocation.width - 1,
698                          widget->allocation.height - 1);
699       
700     }
701 }
702
703 static void
704 gtk_tree_item2_draw (GtkWidget    *widget,
705                     GdkRectangle *area)
706 {
707   GtkBin *bin;
708   GdkRectangle child_area;
709
710   g_return_if_fail (widget != NULL);
711   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
712   g_return_if_fail (area != NULL);
713
714   if (GTK_WIDGET_DRAWABLE (widget))
715     {
716       bin = GTK_BIN (widget);
717
718       gtk_tree_item2_paint (widget, area);
719      
720       if (bin->child && 
721           gtk_widget_intersect (bin->child, area, &child_area))
722         gtk_widget_draw (bin->child, &child_area);
723
724     }
725 }
726
727 static void
728 gtk_tree_item2_draw_focus (GtkWidget *widget)
729 {
730   g_return_if_fail (widget != NULL);
731   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
732
733   gtk_widget_draw(widget, NULL);
734 }
735
736 static gint
737 gtk_tree_item2_button_press (GtkWidget      *widget,
738                             GdkEventButton *event)
739 {
740 /* HF
741   g_return_val_if_fail (widget != NULL, FALSE);
742   g_return_val_if_fail (GTK_IS_TREE_ITEM2 (widget), FALSE);
743   g_return_val_if_fail (event != NULL, FALSE);
744
745   if (event->type == GDK_BUTTON_PRESS
746         && GTK_WIDGET_IS_SENSITIVE(widget)
747         && !GTK_WIDGET_HAS_FOCUS (widget))
748       gtk_widget_grab_focus (widget);
749
750   return FALSE;
751
752 */
753 }
754
755 static gint
756 gtk_tree_item2_expose (GtkWidget      *widget,
757                       GdkEventExpose *event)
758 {
759   GdkEventExpose child_event;
760   GtkBin *bin;
761
762   g_return_val_if_fail (widget != NULL, FALSE);
763   g_return_val_if_fail (GTK_IS_TREE_ITEM2 (widget), FALSE);
764   g_return_val_if_fail (event != NULL, FALSE);
765
766   if (GTK_WIDGET_DRAWABLE (widget))
767     {
768       bin = GTK_BIN (widget);
769       
770       gtk_tree_item2_paint (widget, &event->area);
771
772       child_event = *event;
773       if (bin->child && GTK_WIDGET_NO_WINDOW (bin->child) &&
774           gtk_widget_intersect (bin->child, &event->area, &child_event.area))
775         gtk_widget_event (bin->child, (GdkEvent*) &child_event);
776    }
777
778   return FALSE;
779 }
780
781 static gint
782 gtk_tree_item2_focus_in (GtkWidget     *widget,
783                         GdkEventFocus *event)
784 {
785   g_return_val_if_fail (widget != NULL, FALSE);
786   g_return_val_if_fail (GTK_IS_TREE_ITEM2 (widget), FALSE);
787   g_return_val_if_fail (event != NULL, FALSE);
788
789   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
790   gtk_widget_draw_focus (widget);
791
792
793   return FALSE;
794 }
795
796 static gint
797 gtk_tree_item2_focus_out (GtkWidget     *widget,
798                          GdkEventFocus *event)
799 {
800   g_return_val_if_fail (widget != NULL, FALSE);
801   g_return_val_if_fail (GTK_IS_TREE_ITEM2 (widget), FALSE);
802   g_return_val_if_fail (event != NULL, FALSE);
803
804   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
805   gtk_widget_draw_focus (widget);
806
807
808   return FALSE;
809 }
810
811 static void
812 gtk_real_tree_item2_select (GtkItem *item)
813 {    
814   GtkTreeItem2 *tree_item;
815   GtkWidget *widget;
816
817   g_return_if_fail (item != NULL);
818   g_return_if_fail (GTK_IS_TREE_ITEM2 (item));
819
820   tree_item = GTK_TREE_ITEM2 (item);
821   widget = GTK_WIDGET (item);
822
823   gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
824
825   if (!widget->parent || GTK_TREE2 (widget->parent)->view_mode == GTK_TREE2_VIEW_LINE)
826     gtk_widget_set_state (GTK_TREE_ITEM2 (item)->pixmaps_box, GTK_STATE_SELECTED);
827 }
828
829 static void
830 gtk_real_tree_item2_deselect (GtkItem *item)
831 {
832   GtkTreeItem2 *tree_item;
833   GtkWidget *widget;
834
835   g_return_if_fail (item != NULL);
836   g_return_if_fail (GTK_IS_TREE_ITEM2 (item));
837
838   tree_item = GTK_TREE_ITEM2 (item);
839   widget = GTK_WIDGET (item);
840
841   gtk_widget_set_state (widget, GTK_STATE_NORMAL);
842
843   if (!widget->parent || GTK_TREE2 (widget->parent)->view_mode == GTK_TREE2_VIEW_LINE)
844     gtk_widget_set_state (tree_item->pixmaps_box, GTK_STATE_NORMAL);
845 }
846
847 static void
848 gtk_real_tree_item2_toggle (GtkItem *item)
849 {
850   g_return_if_fail (item != NULL);
851   g_return_if_fail (GTK_IS_TREE_ITEM2 (item));
852
853   if(!GTK_WIDGET_IS_SENSITIVE(item))
854     return;
855
856   if (GTK_WIDGET (item)->parent && GTK_IS_TREE2 (GTK_WIDGET (item)->parent))
857     gtk_tree2_select_child (GTK_TREE2 (GTK_WIDGET (item)->parent),
858                            GTK_WIDGET (item));
859   else
860     {
861       /* Should we really bother with this bit? A listitem not in a list?
862        * -Johannes Keukelaar
863        * yes, always be on the safe side!
864        * -timj
865        */
866       if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
867         gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
868       else
869         gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
870     }
871 }
872
873 static void
874 gtk_real_tree_item2_expand (GtkTreeItem2 *tree_item)
875 {
876   GtkTree2* tree;
877   
878   g_return_if_fail (tree_item != NULL);
879   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
880   
881   if (tree_item->subtree && !tree_item->expanded)
882     {
883       tree = GTK_TREE2 (GTK_WIDGET (tree_item)->parent); 
884       
885       /* hide subtree widget */
886       gtk_widget_show (tree_item->subtree);
887       
888       /* hide button '+' and show button '-' */
889       if (tree_item->pixmaps_box)
890         {
891           gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box), 
892                                 tree_item->plus_pix_widget);
893           gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box), 
894                              tree_item->minus_pix_widget);
895         }
896       if (tree->root_tree)
897         gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
898       tree_item->expanded = TRUE;
899     }
900 }
901
902 static void
903 gtk_real_tree_item2_collapse (GtkTreeItem2 *tree_item)
904 {
905   GtkTree2* tree;
906   
907   g_return_if_fail (tree_item != NULL);
908   g_return_if_fail (GTK_IS_TREE_ITEM2 (tree_item));
909   
910   if (tree_item->subtree && tree_item->expanded) 
911     {
912       tree = GTK_TREE2 (GTK_WIDGET (tree_item)->parent);
913       
914       /* hide subtree widget */
915       gtk_widget_hide (tree_item->subtree);
916       
917       /* hide button '-' and show button '+' */
918       if (tree_item->pixmaps_box)
919         {
920           gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box), 
921                                 tree_item->minus_pix_widget);
922           gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box), 
923                              tree_item->plus_pix_widget);
924         }
925       if (tree->root_tree)
926         gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
927       tree_item->expanded = FALSE;
928     }
929 }
930
931 static void
932 gtk_tree_item2_destroy (GtkObject *object)
933 {
934   GtkTreeItem2* item;
935   GtkWidget* child;
936
937   g_return_if_fail (object != NULL);
938   g_return_if_fail (GTK_IS_TREE_ITEM2 (object));
939
940 #ifdef TREE_DEBUG
941   g_message("+ gtk_tree_item2_destroy [object %#x]\n", (int)object);
942 #endif /* TREE_DEBUG */
943
944   item = GTK_TREE_ITEM2(object);
945
946   /* free sub tree if it exist */
947   child = item->subtree;
948   if (child)
949     {
950       gtk_widget_ref (child);
951       gtk_widget_unparent (child);
952       gtk_widget_destroy (child);
953       gtk_widget_unref (child);
954       item->subtree = NULL;
955     }
956   
957   /* free pixmaps box */
958   child = item->pixmaps_box;
959   if (child)
960     {
961       gtk_widget_ref (child);
962       gtk_widget_unparent (child);
963       gtk_widget_destroy (child);
964       gtk_widget_unref (child);
965       item->pixmaps_box = NULL;
966     }
967   
968   
969   /* destroy plus pixmap */
970   if (item->plus_pix_widget)
971     {
972       gtk_widget_destroy (item->plus_pix_widget);
973       gtk_widget_unref (item->plus_pix_widget);
974       item->plus_pix_widget = NULL;
975     }
976   
977   /* destroy minus pixmap */
978   if (item->minus_pix_widget)
979     {
980       gtk_widget_destroy (item->minus_pix_widget);
981       gtk_widget_unref (item->minus_pix_widget);
982       item->minus_pix_widget = NULL;
983     }
984   
985   /* By removing the pixmaps here, and not in unrealize, we depend on
986    * the fact that a widget can never change colormap or visual.
987    */
988   gtk_tree_item2_remove_pixmaps (item);
989   
990   GTK_OBJECT_CLASS (parent_class)->destroy (object);
991   
992 #ifdef TREE_DEBUG
993   g_message("- gtk_tree_item2_destroy\n");
994 #endif /* TREE_DEBUG */
995 }
996
997 void
998 gtk_tree_item2_remove_subtree (GtkTreeItem2* item) 
999 {
1000   g_return_if_fail (item != NULL);
1001   g_return_if_fail (GTK_IS_TREE_ITEM2(item));
1002   g_return_if_fail (item->subtree != NULL);
1003   
1004   if (GTK_TREE2 (item->subtree)->children)
1005     {
1006       /* The following call will remove the children and call
1007        * gtk_tree_item2_remove_subtree() again. So we are done.
1008        */
1009       gtk_tree2_remove_items (GTK_TREE2 (item->subtree), 
1010                              GTK_TREE2 (item->subtree)->children);
1011       return;
1012     }
1013
1014   if (GTK_WIDGET_MAPPED (item->subtree))
1015     gtk_widget_unmap (item->subtree);
1016       
1017   gtk_widget_unparent (item->subtree);
1018   
1019   if (item->pixmaps_box)
1020     gtk_widget_hide (item->pixmaps_box);
1021   
1022   item->subtree = NULL;
1023
1024   if (item->expanded)
1025     {
1026       item->expanded = FALSE;
1027       if (item->pixmaps_box)
1028         {
1029           gtk_container_remove (GTK_CONTAINER (item->pixmaps_box), 
1030                                 item->minus_pix_widget);
1031           gtk_container_add (GTK_CONTAINER (item->pixmaps_box), 
1032                              item->plus_pix_widget);
1033         }
1034     }
1035 }
1036
1037 static void
1038 gtk_tree_item2_map (GtkWidget *widget)
1039 {
1040   GtkBin *bin;
1041   GtkTreeItem2* item;
1042
1043   g_return_if_fail (widget != NULL);
1044   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
1045
1046   bin = GTK_BIN (widget);
1047   item = GTK_TREE_ITEM2(widget);
1048
1049   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1050
1051   if(item->pixmaps_box &&
1052      GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1053      !GTK_WIDGET_MAPPED (item->pixmaps_box))
1054     gtk_widget_map (item->pixmaps_box);
1055
1056   if (bin->child &&
1057       GTK_WIDGET_VISIBLE (bin->child) &&
1058       !GTK_WIDGET_MAPPED (bin->child))
1059     gtk_widget_map (bin->child);
1060
1061   gdk_window_show (widget->window);
1062 }
1063
1064 static void
1065 gtk_tree_item2_unmap (GtkWidget *widget)
1066 {
1067   GtkBin *bin;
1068   GtkTreeItem2* item;
1069
1070   g_return_if_fail (widget != NULL);
1071   g_return_if_fail (GTK_IS_TREE_ITEM2 (widget));
1072
1073   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1074   bin = GTK_BIN (widget);
1075   item = GTK_TREE_ITEM2(widget);
1076
1077   gdk_window_hide (widget->window);
1078
1079   if(item->pixmaps_box &&
1080      GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1081      GTK_WIDGET_MAPPED (item->pixmaps_box))
1082     gtk_widget_unmap (bin->child);
1083
1084   if (bin->child &&
1085       GTK_WIDGET_VISIBLE (bin->child) &&
1086       GTK_WIDGET_MAPPED (bin->child))
1087     gtk_widget_unmap (bin->child);
1088 }
1089
1090 static void
1091 gtk_tree_item2_forall (GtkContainer *container,
1092                       gboolean      include_internals,
1093                       GtkCallback   callback,
1094                       gpointer      callback_data)
1095 {
1096   GtkBin *bin;
1097   GtkTreeItem2 *tree_item;
1098
1099   g_return_if_fail (container != NULL);
1100   g_return_if_fail (GTK_IS_TREE_ITEM2 (container));
1101   g_return_if_fail (callback != NULL);
1102
1103   bin = GTK_BIN (container);
1104   tree_item = GTK_TREE_ITEM2 (container);
1105
1106   if (bin->child)
1107     (* callback) (bin->child, callback_data);
1108 /*  if (include_internals && tree_item->subtree)
1109     (* callback) (tree_item->subtree, callback_data); */
1110 }