1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
21 #include "gtktreeitem.h"
22 #include "gtkeventbox.h"
23 #include "gtkpixmap.h"
25 #include "gtksignal.h"
27 #include "tree_plus.xpm"
28 #include "tree_minus.xpm"
30 #define DEFAULT_DELTA 9
38 typedef struct _GtkTreePixmaps GtkTreePixmaps;
40 struct _GtkTreePixmaps {
42 GdkColormap *colormap;
44 GdkPixmap *pixmap_plus;
45 GdkPixmap *pixmap_minus;
47 GdkBitmap *mask_minus;
50 static GList *pixmaps = NULL;
52 static void gtk_tree_item_class_init (GtkTreeItemClass *klass);
53 static void gtk_tree_item_init (GtkTreeItem *tree_item);
54 static void gtk_tree_item_realize (GtkWidget *widget);
55 static void gtk_tree_item_size_request (GtkWidget *widget,
56 GtkRequisition *requisition);
57 static void gtk_tree_item_size_allocate (GtkWidget *widget,
58 GtkAllocation *allocation);
59 static void gtk_tree_item_draw (GtkWidget *widget,
61 static void gtk_tree_item_draw_focus (GtkWidget *widget);
62 static gint gtk_tree_item_button_press (GtkWidget *widget,
63 GdkEventButton *event);
64 static gint gtk_tree_item_expose (GtkWidget *widget,
65 GdkEventExpose *event);
66 static gint gtk_tree_item_focus_in (GtkWidget *widget,
67 GdkEventFocus *event);
68 static gint gtk_tree_item_focus_out (GtkWidget *widget,
69 GdkEventFocus *event);
70 static void gtk_real_tree_item_select (GtkItem *item);
71 static void gtk_real_tree_item_deselect (GtkItem *item);
72 static void gtk_real_tree_item_toggle (GtkItem *item);
73 static void gtk_real_tree_item_expand (GtkTreeItem *item);
74 static void gtk_real_tree_item_collapse (GtkTreeItem *item);
75 static void gtk_real_tree_item_expand (GtkTreeItem *item);
76 static void gtk_real_tree_item_collapse (GtkTreeItem *item);
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);
81 static void gtk_tree_item_map(GtkWidget*);
82 static void gtk_tree_item_unmap(GtkWidget*);
84 static void gtk_tree_item_add_pixmaps (GtkTreeItem *tree_item);
85 static void gtk_tree_item_remove_pixmaps (GtkTreeItem *tree_item);
87 static GtkItemClass *parent_class = NULL;
88 static GtkContainerClass *container_class = NULL;
89 static guint tree_item_signals[LAST_SIGNAL] = { 0 };
92 gtk_tree_item_get_type (void)
94 static GtkType tree_item_type = 0;
98 GtkTypeInfo tree_item_info =
101 sizeof (GtkTreeItem),
102 sizeof (GtkTreeItemClass),
103 (GtkClassInitFunc) gtk_tree_item_class_init,
104 (GtkObjectInitFunc) gtk_tree_item_init,
105 /* reserved_1 */ NULL,
106 /* reserved_2 */ NULL,
107 (GtkClassInitFunc) NULL,
110 tree_item_type = gtk_type_unique (gtk_item_get_type (), &tree_item_info);
113 return tree_item_type;
117 gtk_tree_item_class_init (GtkTreeItemClass *class)
119 GtkObjectClass *object_class;
120 GtkWidgetClass *widget_class;
121 GtkItemClass *item_class;
123 object_class = (GtkObjectClass*) class;
124 widget_class = (GtkWidgetClass*) class;
125 item_class = (GtkItemClass*) class;
126 container_class = (GtkContainerClass*) class;
128 parent_class = gtk_type_class (gtk_item_get_type ());
130 tree_item_signals[EXPAND_TREE] =
131 gtk_signal_new ("expand",
134 GTK_SIGNAL_OFFSET (GtkTreeItemClass, expand),
135 gtk_marshal_NONE__NONE,
137 tree_item_signals[COLLAPSE_TREE] =
138 gtk_signal_new ("collapse",
141 GTK_SIGNAL_OFFSET (GtkTreeItemClass, collapse),
142 gtk_marshal_NONE__NONE,
145 gtk_object_class_add_signals (object_class, tree_item_signals, LAST_SIGNAL);
147 object_class->destroy = gtk_tree_item_destroy;
149 widget_class->realize = gtk_tree_item_realize;
150 widget_class->size_request = gtk_tree_item_size_request;
151 widget_class->size_allocate = gtk_tree_item_size_allocate;
152 widget_class->draw = gtk_tree_item_draw;
153 widget_class->draw_focus = gtk_tree_item_draw_focus;
154 widget_class->button_press_event = gtk_tree_item_button_press;
155 widget_class->expose_event = gtk_tree_item_expose;
156 widget_class->focus_in_event = gtk_tree_item_focus_in;
157 widget_class->focus_out_event = gtk_tree_item_focus_out;
158 widget_class->map = gtk_tree_item_map;
159 widget_class->unmap = gtk_tree_item_unmap;
161 item_class->select = gtk_real_tree_item_select;
162 item_class->deselect = gtk_real_tree_item_deselect;
163 item_class->toggle = gtk_real_tree_item_toggle;
165 class->expand = gtk_real_tree_item_expand;
166 class->collapse = gtk_real_tree_item_collapse;
168 container_class = (GtkContainerClass*) parent_class;
171 /* callback for event box mouse event */
173 gtk_tree_item_subtree_button_click (GtkWidget *widget)
177 g_return_if_fail (widget != NULL);
178 g_return_if_fail (GTK_IS_EVENT_BOX (widget));
180 item = (GtkTreeItem*) gtk_object_get_user_data (GTK_OBJECT (widget));
181 if (!GTK_WIDGET_IS_SENSITIVE (item))
185 gtk_tree_item_collapse (item);
187 gtk_tree_item_expand (item);
190 /* callback for event box state changed */
192 gtk_tree_item_subtree_button_changed_state (GtkWidget *widget)
194 g_return_if_fail (widget != NULL);
195 g_return_if_fail (GTK_IS_EVENT_BOX (widget));
197 if (GTK_WIDGET_VISIBLE (widget))
200 if (widget->state == GTK_STATE_NORMAL)
201 gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
203 gdk_window_set_background (widget->window, &widget->style->bg[widget->state]);
205 if (GTK_WIDGET_DRAWABLE (widget))
206 gdk_window_clear_area (widget->window, 0, 0,
207 widget->allocation.width, widget->allocation.height);
212 gtk_tree_item_init (GtkTreeItem *tree_item)
214 GtkWidget *eventbox, *pixmapwid;
216 g_return_if_fail (tree_item != NULL);
217 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
219 tree_item->expanded = FALSE;
220 tree_item->subtree = NULL;
221 GTK_WIDGET_SET_FLAGS (tree_item, GTK_CAN_FOCUS);
223 /* create an event box containing one pixmaps */
224 eventbox = gtk_event_box_new();
225 gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK);
226 gtk_signal_connect(GTK_OBJECT(eventbox), "state_changed",
227 (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
229 gtk_signal_connect(GTK_OBJECT(eventbox), "realize",
230 (GtkSignalFunc)gtk_tree_item_subtree_button_changed_state,
232 gtk_signal_connect(GTK_OBJECT(eventbox), "button_press_event",
233 (GtkSignalFunc)gtk_tree_item_subtree_button_click,
235 gtk_object_set_user_data(GTK_OBJECT(eventbox), tree_item);
236 tree_item->pixmaps_box = eventbox;
238 /* create pixmap for button '+' */
239 pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
240 if (!tree_item->expanded)
241 gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
242 gtk_widget_show (pixmapwid);
243 tree_item->plus_pix_widget = pixmapwid;
244 gtk_widget_ref (tree_item->plus_pix_widget);
245 gtk_object_sink (GTK_OBJECT (tree_item->plus_pix_widget));
247 /* create pixmap for button '-' */
248 pixmapwid = gtk_type_new (gtk_pixmap_get_type ());
249 if (tree_item->expanded)
250 gtk_container_add (GTK_CONTAINER (eventbox), pixmapwid);
251 gtk_widget_show (pixmapwid);
252 tree_item->minus_pix_widget = pixmapwid;
253 gtk_widget_ref (tree_item->minus_pix_widget);
254 gtk_object_sink (GTK_OBJECT (tree_item->minus_pix_widget));
256 gtk_widget_set_parent (eventbox, GTK_WIDGET (tree_item));
261 gtk_tree_item_new (void)
263 GtkWidget *tree_item;
265 tree_item = GTK_WIDGET (gtk_type_new (gtk_tree_item_get_type ()));
271 gtk_tree_item_new_with_label (gchar *label)
273 GtkWidget *tree_item;
274 GtkWidget *label_widget;
276 tree_item = gtk_tree_item_new ();
277 label_widget = gtk_label_new (label);
278 gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
280 gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
281 gtk_widget_show (label_widget);
288 gtk_tree_item_set_subtree (GtkTreeItem *tree_item,
291 g_return_if_fail (tree_item != NULL);
292 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
293 g_return_if_fail (subtree != NULL);
294 g_return_if_fail (GTK_IS_TREE (subtree));
296 if(tree_item->subtree) {
297 g_warning("there is already a subtree for this tree item\n");
301 tree_item->subtree = subtree;
302 GTK_TREE(subtree)->tree_owner = GTK_WIDGET(tree_item);
304 /* show subtree button */
305 if (tree_item->pixmaps_box)
306 gtk_widget_show(tree_item->pixmaps_box);
308 /* set parent widget */
309 gtk_widget_set_parent(subtree, GTK_WIDGET(tree_item)->parent);
311 if(GTK_WIDGET_VISIBLE(GTK_WIDGET(tree_item)))
313 if(GTK_WIDGET_REALIZED (GTK_WIDGET(tree_item)) &&
314 !GTK_WIDGET_REALIZED (GTK_WIDGET(subtree)))
315 gtk_widget_realize (GTK_WIDGET(subtree));
317 if(GTK_WIDGET_MAPPED (GTK_WIDGET(tree_item)) &&
318 !GTK_WIDGET_MAPPED (GTK_WIDGET(subtree)))
319 gtk_widget_map (GTK_WIDGET(subtree));
322 if(tree_item->expanded)
323 gtk_widget_show(subtree);
325 gtk_widget_hide(subtree);
327 if (GTK_WIDGET_VISIBLE (tree_item) && GTK_WIDGET_VISIBLE (tree_item))
328 gtk_widget_queue_resize (GTK_WIDGET(tree_item));
333 gtk_tree_item_select (GtkTreeItem *tree_item)
335 g_return_if_fail (tree_item != NULL);
336 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
338 gtk_item_select (GTK_ITEM (tree_item));
342 gtk_tree_item_deselect (GtkTreeItem *tree_item)
344 g_return_if_fail (tree_item != NULL);
345 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
347 gtk_item_deselect (GTK_ITEM (tree_item));
351 gtk_tree_item_expand (GtkTreeItem *tree_item)
353 g_return_if_fail (tree_item != NULL);
354 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
356 gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[EXPAND_TREE], NULL);
360 gtk_tree_item_collapse (GtkTreeItem *tree_item)
362 g_return_if_fail (tree_item != NULL);
363 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
365 gtk_signal_emit (GTK_OBJECT (tree_item), tree_item_signals[COLLAPSE_TREE], NULL);
369 gtk_tree_item_add_pixmaps (GtkTreeItem *tree_item)
372 GdkColormap *colormap;
373 GtkTreePixmaps *pixmap_node = NULL;
375 g_return_if_fail (tree_item != NULL);
376 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
378 if (tree_item->pixmaps)
381 colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_item));
386 pixmap_node = (GtkTreePixmaps *)tmp_list->data;
388 if (pixmap_node->colormap == colormap)
391 tmp_list = tmp_list->next;
396 pixmap_node->refcount++;
397 tree_item->pixmaps = tmp_list;
401 pixmap_node = g_new (GtkTreePixmaps, 1);
403 pixmap_node->colormap = colormap;
404 gdk_colormap_ref (colormap);
406 pixmap_node->refcount = 1;
408 /* create pixmaps for plus icon */
409 pixmap_node->pixmap_plus =
410 gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
411 &pixmap_node->mask_plus,
415 /* create pixmaps for minus icon */
416 pixmap_node->pixmap_minus =
417 gdk_pixmap_create_from_xpm_d (GTK_WIDGET (tree_item)->window,
418 &pixmap_node->mask_minus,
422 tree_item->pixmaps = pixmaps = g_list_prepend (pixmaps, pixmap_node);
425 gtk_pixmap_set (GTK_PIXMAP (tree_item->plus_pix_widget),
426 pixmap_node->pixmap_plus, pixmap_node->mask_plus);
427 gtk_pixmap_set (GTK_PIXMAP (tree_item->minus_pix_widget),
428 pixmap_node->pixmap_minus, pixmap_node->mask_minus);
432 gtk_tree_item_remove_pixmaps (GtkTreeItem *tree_item)
434 g_return_if_fail (tree_item != NULL);
435 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
437 if (tree_item->pixmaps)
439 GtkTreePixmaps *pixmap_node = (GtkTreePixmaps *)tree_item->pixmaps->data;
441 g_assert (pixmap_node->refcount > 0);
443 if (--pixmap_node->refcount == 0)
445 gdk_colormap_unref (pixmap_node->colormap);
446 gdk_pixmap_unref (pixmap_node->pixmap_plus);
447 gdk_bitmap_unref (pixmap_node->mask_plus);
448 gdk_pixmap_unref (pixmap_node->pixmap_minus);
449 gdk_bitmap_unref (pixmap_node->mask_minus);
451 pixmaps = g_list_remove_link (pixmaps, tree_item->pixmaps);
452 g_list_free_1 (tree_item->pixmaps);
453 g_free (pixmap_node);
456 tree_item->pixmaps = NULL;
461 gtk_tree_item_realize (GtkWidget *widget)
463 g_return_if_fail (widget != NULL);
464 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
466 if (GTK_WIDGET_CLASS (parent_class)->realize)
467 (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
469 gdk_window_set_background (widget->window,
470 &widget->style->base[GTK_STATE_NORMAL]);
472 gtk_tree_item_add_pixmaps (GTK_TREE_ITEM (widget));
476 gtk_tree_item_size_request (GtkWidget *widget,
477 GtkRequisition *requisition)
482 g_return_if_fail (widget != NULL);
483 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
484 g_return_if_fail (requisition != NULL);
486 bin = GTK_BIN (widget);
487 item = GTK_TREE_ITEM(widget);
489 requisition->width = (GTK_CONTAINER (widget)->border_width +
490 widget->style->klass->xthickness) * 2;
491 requisition->height = GTK_CONTAINER (widget)->border_width * 2;
493 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
495 gtk_widget_size_request (bin->child, &bin->child->requisition);
497 requisition->width += bin->child->requisition.width;
499 gtk_widget_size_request (item->pixmaps_box,
500 &item->pixmaps_box->requisition);
501 requisition->width += item->pixmaps_box->requisition.width + DEFAULT_DELTA +
502 GTK_TREE(widget->parent)->current_indent;
504 requisition->height += MAX(bin->child->requisition.height,
505 item->pixmaps_box->requisition.height);
510 gtk_tree_item_size_allocate (GtkWidget *widget,
511 GtkAllocation *allocation)
515 GtkAllocation child_allocation;
519 g_return_if_fail (widget != NULL);
520 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
521 g_return_if_fail (allocation != NULL);
523 widget->allocation = *allocation;
524 if (GTK_WIDGET_REALIZED (widget))
525 gdk_window_move_resize (widget->window,
526 allocation->x, allocation->y,
527 allocation->width, allocation->height);
529 bin = GTK_BIN (widget);
530 item = GTK_TREE_ITEM(widget);
534 border_width = (GTK_CONTAINER (widget)->border_width +
535 widget->style->klass->xthickness);
537 child_allocation.x = border_width + GTK_TREE(widget->parent)->current_indent;
538 child_allocation.y = GTK_CONTAINER (widget)->border_width;
540 child_allocation.width = item->pixmaps_box->requisition.width;
541 child_allocation.height = item->pixmaps_box->requisition.height;
543 temp = allocation->height - child_allocation.height;
544 child_allocation.y += ( temp / 2 ) + ( temp % 2 );
546 gtk_widget_size_allocate (item->pixmaps_box, &child_allocation);
548 child_allocation.y = GTK_CONTAINER (widget)->border_width;
549 child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
550 child_allocation.x += item->pixmaps_box->requisition.width+DEFAULT_DELTA;
552 child_allocation.width =
553 MAX (1, allocation->width - (child_allocation.x + border_width));
555 gtk_widget_size_allocate (bin->child, &child_allocation);
560 gtk_tree_item_draw_lines(GtkWidget *widget)
564 guint lx1, ly1, lx2, ly2;
566 g_return_if_fail (widget != NULL);
567 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
569 item = GTK_TREE_ITEM(widget);
570 tree = GTK_TREE(widget->parent);
572 /* draw vertical line */
573 lx1 = item->pixmaps_box->allocation.width;
574 lx1 = lx2 = ( lx1 / 2 ) + ( lx1 % 2 ) +
575 GTK_CONTAINER(widget)->border_width + 1 + tree->current_indent;
577 ly2 = widget->allocation.height;
579 if(g_list_last(tree->children)->data == (gpointer)widget)
580 ly2 = (ly2 / 2) + (ly2 % 2);
582 if(tree != tree->root_tree)
583 gdk_draw_line(widget->window, widget->style->black_gc,
586 /* draw vertical line for subtree connecting */
587 if(g_list_last(tree->children)->data != (gpointer)widget)
588 ly2 = (ly2 / 2) + (ly2 % 2);
590 lx2 += DEFAULT_DELTA;
592 if(item->subtree && item->expanded)
593 gdk_draw_line(widget->window, widget->style->black_gc,
594 lx2, ly2, lx2, widget->allocation.height);
596 /* draw horizontal line */
600 gdk_draw_line(widget->window, widget->style->black_gc,
603 lx2 -= DEFAULT_DELTA+2;
605 ly2 = widget->allocation.height;
607 if(tree != tree->root_tree)
609 item = GTK_TREE_ITEM(tree->tree_owner);
610 tree = GTK_TREE(GTK_WIDGET(tree)->parent);
611 while(tree != tree->root_tree) {
612 lx1 = lx2 -= tree->indent_value;
614 if(g_list_last(tree->children)->data != (gpointer)item)
615 gdk_draw_line(widget->window, widget->style->black_gc,
617 item = GTK_TREE_ITEM(tree->tree_owner);
618 tree = GTK_TREE(GTK_WIDGET(tree)->parent);
624 gtk_tree_item_draw (GtkWidget *widget,
628 GdkRectangle child_area, item_area;
629 GtkTreeItem* tree_item;
631 g_return_if_fail (widget != NULL);
632 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
633 g_return_if_fail (area != NULL);
635 if (GTK_WIDGET_DRAWABLE (widget))
637 bin = GTK_BIN (widget);
638 tree_item = GTK_TREE_ITEM(widget);
640 /* draw left size of tree item */
641 item_area.x = 0; item_area.y = 0;
642 item_area.width = tree_item->pixmaps_box->allocation.width+DEFAULT_DELTA +
643 (GTK_TREE(widget->parent)->current_indent + 2);
644 item_area.height = widget->allocation.height;
646 if(gdk_rectangle_intersect(&item_area, area, &child_area)) {
648 if (!GTK_WIDGET_IS_SENSITIVE (widget))
649 gtk_style_set_background (widget->style, widget->window,
650 GTK_STATE_INSENSITIVE);
651 else if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_LINE &&
652 widget->state == GTK_STATE_SELECTED)
653 gtk_style_set_background (widget->style, widget->window, widget->state);
655 gdk_window_set_background (widget->window,
656 &widget->style->base[GTK_STATE_NORMAL]);
658 gdk_window_clear_area (widget->window,
659 child_area.x, child_area.y,
660 child_area.width, child_area.height);
662 /* gtk_tree_item_draw_lines(widget); */
664 if (tree_item->pixmaps_box &&
665 GTK_WIDGET_VISIBLE(tree_item->pixmaps_box) &&
666 gtk_widget_intersect (tree_item->pixmaps_box, area, &child_area))
667 gtk_widget_draw (tree_item->pixmaps_box, &child_area);
670 /* draw right side */
671 if(gtk_widget_intersect (bin->child, area, &child_area)) {
673 if (!GTK_WIDGET_IS_SENSITIVE (widget))
674 gtk_style_set_background (widget->style, widget->window,
675 GTK_STATE_INSENSITIVE);
676 else if (widget->state == GTK_STATE_NORMAL)
677 gdk_window_set_background(widget->window, &widget->style->base[GTK_STATE_NORMAL]);
679 gtk_style_set_background (widget->style, widget->window, widget->state);
681 gdk_window_clear_area (widget->window, child_area.x, child_area.y,
682 child_area.width+1, child_area.height);
685 GTK_WIDGET_VISIBLE(bin->child) &&
686 gtk_widget_intersect (bin->child, area, &child_area))
687 gtk_widget_draw (bin->child, &child_area);
690 gtk_widget_draw_focus (widget);
695 gtk_tree_item_draw_focus (GtkWidget *widget)
700 g_return_if_fail (widget != NULL);
701 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
703 if (GTK_WIDGET_DRAWABLE (widget))
705 if (GTK_WIDGET_HAS_FOCUS (widget))
706 gc = widget->style->black_gc;
707 else if (!GTK_WIDGET_IS_SENSITIVE (widget))
708 gc = widget->style->bg_gc[GTK_STATE_INSENSITIVE];
709 else if (widget->state == GTK_STATE_NORMAL)
710 gc = widget->style->base_gc[GTK_STATE_NORMAL];
712 gc = widget->style->bg_gc[widget->state];
716 if(GTK_TREE(widget->parent)->view_mode == GTK_TREE_VIEW_ITEM)
717 dx = GTK_TREE_ITEM(widget)->pixmaps_box->allocation.width + DEFAULT_DELTA +
718 GTK_TREE(widget->parent)->current_indent+1;
720 gdk_draw_rectangle (widget->window, gc, FALSE, dx, 0,
721 widget->allocation.width - 1 - dx,
722 widget->allocation.height - 1);
724 if (GTK_TREE (widget->parent)->view_line &&
725 (!GTK_IS_ROOT_TREE (widget->parent) ||
726 (GTK_IS_ROOT_TREE (widget->parent) && GTK_TREE_ITEM(widget)->subtree)))
728 gtk_tree_item_draw_lines(widget);
734 gtk_tree_item_button_press (GtkWidget *widget,
735 GdkEventButton *event)
738 g_return_val_if_fail (widget != NULL, FALSE);
739 g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
740 g_return_val_if_fail (event != NULL, FALSE);
742 if (event->type == GDK_BUTTON_PRESS
743 && GTK_WIDGET_IS_SENSITIVE(widget)
744 && !GTK_WIDGET_HAS_FOCUS (widget))
745 gtk_widget_grab_focus (widget);
751 gtk_tree_item_expose (GtkWidget *widget,
752 GdkEventExpose *event)
754 g_return_val_if_fail (widget != NULL, FALSE);
755 g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
756 g_return_val_if_fail (event != NULL, FALSE);
758 if (GTK_WIDGET_DRAWABLE (widget))
759 gtk_tree_item_draw(widget, &event->area);
765 gtk_tree_item_focus_in (GtkWidget *widget,
766 GdkEventFocus *event)
768 g_return_val_if_fail (widget != NULL, FALSE);
769 g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
770 g_return_val_if_fail (event != NULL, FALSE);
772 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
773 gtk_widget_draw_focus (widget);
780 gtk_tree_item_focus_out (GtkWidget *widget,
781 GdkEventFocus *event)
783 g_return_val_if_fail (widget != NULL, FALSE);
784 g_return_val_if_fail (GTK_IS_TREE_ITEM (widget), FALSE);
785 g_return_val_if_fail (event != NULL, FALSE);
787 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
788 gtk_widget_draw_focus (widget);
795 gtk_real_tree_item_select (GtkItem *item)
797 g_return_if_fail (item != NULL);
798 g_return_if_fail (GTK_IS_TREE_ITEM (item));
800 if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED
801 || !GTK_WIDGET_IS_SENSITIVE(item))
804 if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
805 gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_SELECTED);
807 gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
809 gtk_widget_queue_draw (GTK_WIDGET (item));
813 gtk_real_tree_item_deselect (GtkItem *item)
815 g_return_if_fail (item != NULL);
816 g_return_if_fail (GTK_IS_TREE_ITEM (item));
818 if (GTK_WIDGET (item)->state == GTK_STATE_NORMAL)
821 if(GTK_WIDGET_MAPPED(GTK_WIDGET (item)))
823 gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
825 if(GTK_TREE(GTK_WIDGET(item)->parent)->view_mode == GTK_TREE_VIEW_LINE)
826 gtk_widget_set_state (GTK_TREE_ITEM (item)->pixmaps_box, GTK_STATE_NORMAL);
828 gtk_widget_queue_draw (GTK_WIDGET (item));
833 gtk_real_tree_item_toggle (GtkItem *item)
835 g_return_if_fail (item != NULL);
836 g_return_if_fail (GTK_IS_TREE_ITEM (item));
838 if(!GTK_WIDGET_IS_SENSITIVE(item))
841 if (GTK_WIDGET (item)->parent && GTK_IS_TREE (GTK_WIDGET (item)->parent))
842 gtk_tree_select_child (GTK_TREE (GTK_WIDGET (item)->parent),
846 /* Should we really bother with this bit? A listitem not in a list?
847 * -Johannes Keukelaar
848 * yes, always be on the save side!
851 if (GTK_WIDGET (item)->state == GTK_STATE_SELECTED)
852 gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_NORMAL);
854 gtk_widget_set_state (GTK_WIDGET (item), GTK_STATE_SELECTED);
855 gtk_widget_queue_draw (GTK_WIDGET (item));
860 gtk_real_tree_item_expand (GtkTreeItem *tree_item)
864 g_return_if_fail (tree_item != NULL);
865 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
867 if (tree_item->subtree && !tree_item->expanded)
869 tree = GTK_TREE (GTK_WIDGET (tree_item)->parent);
871 /* hide subtree widget */
872 gtk_widget_show (tree_item->subtree);
874 /* hide button '+' and show button '-' */
875 if (tree_item->pixmaps_box)
877 gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box),
878 tree_item->plus_pix_widget);
879 gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box),
880 tree_item->minus_pix_widget);
883 gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
884 tree_item->expanded = TRUE;
889 gtk_real_tree_item_collapse (GtkTreeItem *tree_item)
893 g_return_if_fail (tree_item != NULL);
894 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
896 if (tree_item->subtree && tree_item->expanded)
898 tree = GTK_TREE (GTK_WIDGET (tree_item)->parent);
900 /* hide subtree widget */
901 gtk_widget_hide (tree_item->subtree);
903 /* hide button '-' and show button '+' */
904 if (tree_item->pixmaps_box)
906 gtk_container_remove (GTK_CONTAINER (tree_item->pixmaps_box),
907 tree_item->minus_pix_widget);
908 gtk_container_add (GTK_CONTAINER (tree_item->pixmaps_box),
909 tree_item->plus_pix_widget);
912 gtk_widget_queue_resize (GTK_WIDGET (tree->root_tree));
913 tree_item->expanded = FALSE;
918 gtk_tree_item_destroy (GtkObject *object)
923 g_return_if_fail (object != NULL);
924 g_return_if_fail (GTK_IS_TREE_ITEM (object));
927 g_print("+ gtk_tree_item_destroy [object %#x]\n", (int)object);
928 #endif /* TREE_DEBUG */
930 item = GTK_TREE_ITEM(object);
932 /* free sub tree if it exist */
933 child = item->subtree;
936 gtk_widget_ref (child);
937 gtk_widget_unparent (child);
938 gtk_widget_destroy (child);
939 gtk_widget_unref (child);
940 item->subtree = NULL;
943 /* free pixmaps box */
944 child = item->pixmaps_box;
947 gtk_widget_ref (child);
948 gtk_widget_unparent (child);
949 gtk_widget_destroy (child);
950 gtk_widget_unref (child);
951 item->pixmaps_box = NULL;
955 /* destroy plus pixmap */
956 if (item->plus_pix_widget)
958 gtk_widget_destroy (item->plus_pix_widget);
959 gtk_widget_unref (item->plus_pix_widget);
960 item->plus_pix_widget = NULL;
963 /* destroy minus pixmap */
964 if (item->minus_pix_widget)
966 gtk_widget_destroy (item->minus_pix_widget);
967 gtk_widget_unref (item->minus_pix_widget);
968 item->minus_pix_widget = NULL;
971 /* By removing the pixmaps here, and not in unrealize, we depend on
972 * the fact that a widget can never change colormap or visual.
974 gtk_tree_item_remove_pixmaps (item);
976 GTK_OBJECT_CLASS (parent_class)->destroy (object);
979 g_print("- gtk_tree_item_destroy\n");
980 #endif /* TREE_DEBUG */
984 gtk_tree_item_remove_subtree (GtkTreeItem* item)
986 g_return_if_fail (item != NULL);
987 g_return_if_fail (GTK_IS_TREE_ITEM(item));
988 g_return_if_fail (item->subtree != NULL);
990 if (GTK_TREE (item->subtree)->children)
992 /* The following call will remove the children and call
993 * gtk_tree_item_remove_subtree() again. So we are done.
995 gtk_tree_remove_items (GTK_TREE (item->subtree),
996 GTK_TREE (item->subtree)->children);
1000 if (GTK_WIDGET_MAPPED (item->subtree))
1001 gtk_widget_unmap (item->subtree);
1003 gtk_widget_unparent (item->subtree);
1005 if (item->pixmaps_box)
1006 gtk_widget_hide (item->pixmaps_box);
1008 item->subtree = NULL;
1012 item->expanded = FALSE;
1013 if (item->pixmaps_box)
1015 gtk_container_remove (GTK_CONTAINER (item->pixmaps_box),
1016 item->minus_pix_widget);
1017 gtk_container_add (GTK_CONTAINER (item->pixmaps_box),
1018 item->plus_pix_widget);
1024 gtk_tree_item_map (GtkWidget *widget)
1029 g_return_if_fail (widget != NULL);
1030 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
1032 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1033 bin = GTK_BIN (widget);
1034 item = GTK_TREE_ITEM(widget);
1036 if (!GTK_WIDGET_NO_WINDOW (widget))
1037 gdk_window_show (widget->window);
1039 gtk_widget_queue_draw (widget);
1041 if(item->pixmaps_box &&
1042 GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1043 !GTK_WIDGET_MAPPED (item->pixmaps_box))
1044 gtk_widget_map (item->pixmaps_box);
1047 GTK_WIDGET_VISIBLE (bin->child) &&
1048 !GTK_WIDGET_MAPPED (bin->child))
1049 gtk_widget_map (bin->child);
1053 gtk_tree_item_unmap (GtkWidget *widget)
1058 g_return_if_fail (widget != NULL);
1059 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
1061 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1062 bin = GTK_BIN (widget);
1063 item = GTK_TREE_ITEM(widget);
1065 if (GTK_WIDGET_NO_WINDOW (widget))
1066 gdk_window_clear_area (widget->window,
1067 widget->allocation.x,
1068 widget->allocation.y,
1069 widget->allocation.width,
1070 widget->allocation.height);
1072 gdk_window_hide (widget->window);
1074 if(item->pixmaps_box &&
1075 GTK_WIDGET_VISIBLE (item->pixmaps_box) &&
1076 GTK_WIDGET_MAPPED (item->pixmaps_box))
1077 gtk_widget_unmap (bin->child);
1080 GTK_WIDGET_VISIBLE (bin->child) &&
1081 GTK_WIDGET_MAPPED (bin->child))
1082 gtk_widget_unmap (bin->child);