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.
20 #include "gtktreeitem.h"
22 #include "gtksignal.h"
32 typedef void (*GtkTreeSignal) (GtkObject *object,
37 static void gtk_tree_class_init (GtkTreeClass *klass);
38 static void gtk_tree_init (GtkTree *tree);
39 static void gtk_tree_destroy (GtkObject *object);
40 static void gtk_tree_map (GtkWidget *widget);
41 static void gtk_tree_unmap (GtkWidget *widget);
42 static void gtk_tree_realize (GtkWidget *widget);
43 static void gtk_tree_draw (GtkWidget *widget,
45 static gint gtk_tree_expose (GtkWidget *widget,
46 GdkEventExpose *event);
47 static gint gtk_tree_motion_notify (GtkWidget *widget,
48 GdkEventMotion *event);
49 static gint gtk_tree_button_press (GtkWidget *widget,
50 GdkEventButton *event);
51 static gint gtk_tree_button_release (GtkWidget *widget,
52 GdkEventButton *event);
53 static void gtk_tree_size_request (GtkWidget *widget,
54 GtkRequisition *requisition);
55 static void gtk_tree_size_allocate (GtkWidget *widget,
56 GtkAllocation *allocation);
57 static void gtk_tree_add (GtkContainer *container,
59 static void gtk_tree_foreach (GtkContainer *container,
61 gpointer callback_data);
63 static void gtk_real_tree_select_child (GtkTree *tree,
65 static void gtk_real_tree_unselect_child (GtkTree *tree,
68 static void gtk_tree_marshal_signal (GtkObject *object,
73 static GtkContainerClass *parent_class = NULL;
74 static guint tree_signals[LAST_SIGNAL] = { 0 };
79 static guint tree_type = 0;
83 GtkTypeInfo tree_info =
87 sizeof (GtkTreeClass),
88 (GtkClassInitFunc) gtk_tree_class_init,
89 (GtkObjectInitFunc) gtk_tree_init,
94 tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
101 gtk_tree_class_init (GtkTreeClass *class)
103 GtkObjectClass *object_class;
104 GtkWidgetClass *widget_class;
105 GtkContainerClass *container_class;
107 object_class = (GtkObjectClass*) class;
108 widget_class = (GtkWidgetClass*) class;
109 container_class = (GtkContainerClass*) class;
111 parent_class = gtk_type_class (gtk_container_get_type ());
113 tree_signals[SELECTION_CHANGED] =
114 gtk_signal_new ("selection_changed",
117 GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
118 gtk_signal_default_marshaller,
120 tree_signals[SELECT_CHILD] =
121 gtk_signal_new ("select_child",
124 GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
125 gtk_tree_marshal_signal,
128 tree_signals[UNSELECT_CHILD] =
129 gtk_signal_new ("unselect_child",
132 GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
133 gtk_tree_marshal_signal,
137 gtk_object_class_add_signals (object_class, tree_signals, LAST_SIGNAL);
139 object_class->destroy = gtk_tree_destroy;
141 widget_class->map = gtk_tree_map;
142 widget_class->unmap = gtk_tree_unmap;
143 widget_class->realize = gtk_tree_realize;
144 widget_class->draw = gtk_tree_draw;
145 widget_class->expose_event = gtk_tree_expose;
146 widget_class->motion_notify_event = gtk_tree_motion_notify;
147 widget_class->button_press_event = gtk_tree_button_press;
148 widget_class->button_release_event = gtk_tree_button_release;
149 widget_class->size_request = gtk_tree_size_request;
150 widget_class->size_allocate = gtk_tree_size_allocate;
152 container_class->add = gtk_tree_add;
153 container_class->remove =
154 (void (*)(GtkContainer *, GtkWidget *)) gtk_tree_remove_item;
155 container_class->foreach = gtk_tree_foreach;
157 class->selection_changed = NULL;
158 class->select_child = gtk_real_tree_select_child;
159 class->unselect_child = gtk_real_tree_unselect_child;
163 gtk_tree_init (GtkTree *tree)
165 tree->children = NULL;
166 tree->root_tree = NULL;
167 tree->selection = NULL;
168 tree->tree_owner = NULL;
169 tree->selection_mode = GTK_SELECTION_SINGLE;
170 tree->indent_value = 9;
171 tree->current_indent = 0;
173 tree->view_mode = GTK_TREE_VIEW_LINE;
180 return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
184 gtk_tree_append (GtkTree *tree,
185 GtkWidget *tree_item)
187 g_return_if_fail (tree != NULL);
188 g_return_if_fail (GTK_IS_TREE (tree));
189 g_return_if_fail (tree_item != NULL);
190 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
192 gtk_tree_insert(tree, tree_item, -1);
196 gtk_tree_prepend (GtkTree *tree,
197 GtkWidget *tree_item)
199 g_return_if_fail (tree != NULL);
200 g_return_if_fail (GTK_IS_TREE (tree));
201 g_return_if_fail (tree_item != NULL);
202 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
204 gtk_tree_insert(tree, tree_item, 0);
208 gtk_tree_insert (GtkTree *tree,
209 GtkWidget *tree_item,
214 g_return_if_fail (tree != NULL);
215 g_return_if_fail (GTK_IS_TREE (tree));
216 g_return_if_fail (tree_item != NULL);
217 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
219 /* set parent widget to item */
220 gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
222 if (GTK_WIDGET_VISIBLE (tree_item->parent))
224 if (GTK_WIDGET_REALIZED (tree_item->parent) &&
225 !GTK_WIDGET_REALIZED (tree_item))
226 gtk_widget_realize (tree_item);
228 if (GTK_WIDGET_MAPPED (tree_item->parent) &&
229 !GTK_WIDGET_MAPPED (tree_item))
230 gtk_widget_map (tree_item);
233 nchildren = g_list_length (tree->children);
235 if ((position < 0) || (position > nchildren))
236 position = nchildren;
238 if (position == nchildren)
240 tree->children = g_list_append(tree->children, tree_item);
244 tree->children = g_list_insert(tree->children, tree_item, position);
247 if (GTK_WIDGET_VISIBLE (tree))
248 gtk_widget_queue_resize (GTK_WIDGET (tree));
253 gtk_tree_add (GtkContainer *container,
258 g_return_if_fail (container != NULL);
259 g_return_if_fail (GTK_IS_TREE (container));
260 g_return_if_fail (widget != NULL);
261 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
263 tree = GTK_TREE (container);
265 gtk_widget_set_parent (widget, GTK_WIDGET (container));
266 if (GTK_WIDGET_VISIBLE (widget->parent))
268 if (GTK_WIDGET_REALIZED (widget->parent) &&
269 !GTK_WIDGET_REALIZED (widget))
270 gtk_widget_realize (widget);
272 if (GTK_WIDGET_MAPPED (widget->parent) &&
273 !GTK_WIDGET_MAPPED (widget))
274 gtk_widget_map (widget);
277 tree->children = g_list_append (tree->children, widget);
279 if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
281 gtk_tree_select_child (tree, widget);
284 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
285 gtk_widget_queue_resize (widget);
290 gtk_tree_button_press (GtkWidget *widget,
291 GdkEventButton *event)
296 g_return_val_if_fail (widget != NULL, FALSE);
297 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
298 g_return_val_if_fail (event != NULL, FALSE);
300 tree = GTK_TREE (widget);
301 item = gtk_get_event_widget ((GdkEvent*) event);
303 while (item && !GTK_IS_TREE_ITEM (item))
306 if (!item || (item->parent != widget))
309 switch(event->button)
312 gtk_tree_select_child (tree, item);
315 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
318 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
326 gtk_tree_button_release (GtkWidget *widget,
327 GdkEventButton *event)
332 g_return_val_if_fail (widget != NULL, FALSE);
333 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
334 g_return_val_if_fail (event != NULL, FALSE);
336 tree = GTK_TREE (widget);
337 item = gtk_get_event_widget ((GdkEvent*) event);
343 gtk_tree_child_position (GtkTree *tree,
350 g_return_val_if_fail (tree != NULL, -1);
351 g_return_val_if_fail (GTK_IS_TREE (tree), -1);
352 g_return_val_if_fail (child != NULL, -1);
355 children = tree->children;
359 if (child == GTK_WIDGET (children->data))
363 children = children->next;
371 gtk_tree_clear_items (GtkTree *tree,
381 g_return_if_fail (tree != NULL);
382 g_return_if_fail (GTK_IS_TREE (tree));
384 nchildren = g_list_length (tree->children);
388 if ((end < 0) || (end > nchildren))
394 tmp_list = g_list_nth (tree->children, start);
397 while (tmp_list && index <= end)
399 widget = tmp_list->data;
400 tmp_list = tmp_list->next;
403 clear_list = g_list_prepend (clear_list, widget);
406 gtk_tree_remove_items (tree, clear_list);
411 gtk_tree_destroy (GtkObject *object)
417 g_return_if_fail (object != NULL);
418 g_return_if_fail (GTK_IS_TREE (object));
420 tree = GTK_TREE (object);
422 children = tree->children;
425 child = children->data;
426 children = children->next;
428 gtk_widget_ref (child);
429 gtk_widget_unparent (child);
430 gtk_widget_destroy (child);
431 gtk_widget_unref (child);
434 g_list_free (tree->children);
435 tree->children = NULL;
437 if (tree->root_tree == tree)
440 for (node = tree->selection; node; node = node->next)
441 gtk_widget_unref ((GtkWidget *)node->data);
442 g_list_free (tree->selection);
443 tree->selection = NULL;
446 if (GTK_OBJECT_CLASS (parent_class)->destroy)
447 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
451 gtk_tree_draw (GtkWidget *widget,
457 GdkRectangle child_area;
461 g_return_if_fail (widget != NULL);
462 g_return_if_fail (GTK_IS_TREE (widget));
463 g_return_if_fail (area != NULL);
465 if (GTK_WIDGET_DRAWABLE (widget))
467 tree = GTK_TREE (widget);
469 children = tree->children;
472 child = children->data;
473 children = children->next;
475 if (gtk_widget_intersect (child, area, &child_area))
476 gtk_widget_draw (child, &child_area);
478 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
479 GTK_WIDGET_VISIBLE(subtree) &&
480 gtk_widget_intersect (subtree, area, &child_area))
481 gtk_widget_draw (subtree, &child_area);
488 gtk_tree_expose (GtkWidget *widget,
489 GdkEventExpose *event)
493 GdkEventExpose child_event;
497 g_return_val_if_fail (widget != NULL, FALSE);
498 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
499 g_return_val_if_fail (event != NULL, FALSE);
501 if (GTK_WIDGET_DRAWABLE (widget))
503 tree = GTK_TREE (widget);
505 child_event = *event;
507 children = tree->children;
510 child = children->data;
511 children = children->next;
513 if (GTK_WIDGET_NO_WINDOW (child) &&
514 gtk_widget_intersect (child, &event->area, &child_event.area))
515 gtk_widget_event (child, (GdkEvent*) &child_event);
524 gtk_tree_foreach (GtkContainer *container,
525 GtkCallback callback,
526 gpointer callback_data)
533 g_return_if_fail (container != NULL);
534 g_return_if_fail (GTK_IS_TREE (container));
535 g_return_if_fail (callback != NULL);
537 tree = GTK_TREE (container);
538 children = tree->children;
542 child = children->data;
543 children = children->next;
545 (* callback) (child, callback_data);
547 if(GTK_TREE_ITEM(child)->subtree)
548 (* callback)(GTK_TREE_ITEM(child)->subtree, callback_data);
553 gtk_tree_map (GtkWidget *widget)
560 g_return_if_fail (widget != NULL);
561 g_return_if_fail (GTK_IS_TREE (widget));
563 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
564 tree = GTK_TREE (widget);
566 gdk_window_show (widget->window);
568 if(GTK_IS_TREE(widget->parent))
570 /* set root tree for this tree */
571 tree->root_tree = GTK_TREE(widget->parent)->root_tree;
573 tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
574 tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
575 tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
577 tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
578 tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
581 tree->root_tree = tree;
583 children = tree->children;
586 child = children->data;
587 children = children->next;
589 if (GTK_WIDGET_VISIBLE (child) &&
590 !GTK_WIDGET_MAPPED (child))
591 gtk_widget_map (child);
593 if (GTK_TREE_ITEM (child)->subtree)
595 child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
597 if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
598 gtk_widget_map (child);
604 gtk_tree_marshal_signal (GtkObject *object,
611 rfunc = (GtkTreeSignal) func;
613 (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
617 gtk_tree_motion_notify (GtkWidget *widget,
618 GdkEventMotion *event)
620 g_return_val_if_fail (widget != NULL, FALSE);
621 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
622 g_return_val_if_fail (event != NULL, FALSE);
625 g_print("gtk_tree_motion_notify\n");
626 #endif /* TREE_DEBUG */
632 gtk_tree_realize (GtkWidget *widget)
634 GdkWindowAttr attributes;
635 gint attributes_mask;
638 g_return_if_fail (widget != NULL);
639 g_return_if_fail (GTK_IS_TREE (widget));
641 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
643 attributes.window_type = GDK_WINDOW_CHILD;
644 attributes.x = widget->allocation.x;
645 attributes.y = widget->allocation.y;
646 attributes.width = widget->allocation.width;
647 attributes.height = widget->allocation.height;
648 attributes.wclass = GDK_INPUT_OUTPUT;
649 attributes.visual = gtk_widget_get_visual (widget);
650 attributes.colormap = gtk_widget_get_colormap (widget);
651 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
653 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
655 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
656 gdk_window_set_user_data (widget->window, widget);
658 widget->style = gtk_style_attach (widget->style, widget->window);
659 gdk_window_set_background (widget->window,
660 &widget->style->base[GTK_STATE_NORMAL]);
664 gtk_tree_remove_item (GtkTree *container,
669 g_return_if_fail (container != NULL);
670 g_return_if_fail (GTK_IS_TREE (container));
671 g_return_if_fail (widget != NULL);
672 g_return_if_fail (container == GTK_TREE (widget->parent));
674 item_list = g_list_append (NULL, widget);
676 gtk_tree_remove_items (GTK_TREE (container), item_list);
678 g_list_free (item_list);
681 /* used by gtk_tree_remove_items to make the function independant of
682 order in list of items to remove.
683 Sort item bu depth in tree */
685 gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
687 if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
689 if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
696 gtk_tree_remove_items (GtkTree *tree,
700 GList *selected_widgets;
706 g_return_if_fail (tree != NULL);
707 g_return_if_fail (GTK_IS_TREE (tree));
710 g_print("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
711 #endif /* TREE_DEBUG */
713 root_tree = GTK_TREE(GTK_TREE_ROOT_TREE(tree));
715 selected_widgets = NULL;
720 g_print("* sort list by depth\n");
721 #endif /* TREE_DEBUG */
727 g_print("* item [%#x] depth [%d]\n",
729 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
730 #endif /* TREE_DEBUG */
732 sorted_list = g_list_insert_sorted(sorted_list,
734 (GCompareFunc)gtk_tree_sort_item_by_depth);
735 tmp_list = g_list_next(tmp_list);
739 /* print sorted list */
740 g_print("* sorted list result\n");
741 tmp_list = sorted_list;
744 g_print("* item [%#x] depth [%d]\n",
746 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
747 tmp_list = g_list_next(tmp_list);
749 #endif /* TREE_DEBUG */
752 g_print("* scan sorted list\n");
753 #endif /* TREE_DEBUG */
755 tmp_list = sorted_list;
758 widget = tmp_list->data;
759 tmp_list = tmp_list->next;
762 g_print("* item [%#x] subtree [%#x]\n",
763 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
764 #endif /* TREE_DEBUG */
766 /* get real owner of this widget */
767 real_tree = GTK_TREE(widget->parent);
769 g_print("* subtree having this widget [%#x]\n", (int)real_tree);
770 #endif /* TREE_DEBUG */
773 if (widget->state == GTK_STATE_SELECTED)
775 selected_widgets = g_list_prepend (selected_widgets, widget);
777 g_print("* selected widget - adding it in selected list [%#x]\n",
778 (int)selected_widgets);
779 #endif /* TREE_DEBUG */
782 /* remove this item of his real parent */
784 g_print("* remove widget of his owner tree\n");
785 #endif /* TREE_DEBUG */
786 real_tree->children = g_list_remove (real_tree->children, widget);
788 /* remove subtree associate at this item if it exist */
789 if(GTK_TREE_ITEM(widget)->subtree)
792 g_print("* remove subtree associate at this item [%#x]\n",
793 (int) GTK_TREE_ITEM(widget)->subtree);
794 #endif /* TREE_DEBUG */
795 if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
796 gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
798 gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
799 GTK_TREE_ITEM(widget)->subtree = NULL;
802 /* really remove widget for this item */
804 g_print("* unmap and unparent widget [%#x]\n", (int)widget);
805 #endif /* TREE_DEBUG */
806 if (GTK_WIDGET_MAPPED (widget))
807 gtk_widget_unmap (widget);
809 gtk_widget_unparent (widget);
811 /* delete subtree if there is no children in it */
812 if(real_tree->children == NULL &&
813 real_tree != root_tree)
816 g_print("* owner tree don't have children ... destroy it\n");
817 #endif /* TREE_DEBUG */
818 gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
822 g_print("* next item in list\n");
823 #endif /* TREE_DEBUG */
826 if (selected_widgets)
829 g_print("* scan selected item list\n");
830 #endif /* TREE_DEBUG */
831 tmp_list = selected_widgets;
834 widget = tmp_list->data;
835 tmp_list = tmp_list->next;
838 g_print("* widget [%#x] subtree [%#x]\n",
839 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
840 #endif /* TREE_DEBUG */
842 /* remove widget of selection */
843 root_tree->selection = g_list_remove (root_tree->selection, widget);
845 /* unref it to authorize is destruction */
846 gtk_widget_unref (widget);
849 /* emit only one selection_changed signal */
850 gtk_signal_emit (GTK_OBJECT (root_tree),
851 tree_signals[SELECTION_CHANGED]);
855 g_print("* free selected_widgets list\n");
856 #endif /* TREE_DEBUG */
857 g_list_free (selected_widgets);
858 g_list_free (sorted_list);
860 if (root_tree->children && !root_tree->selection &&
861 (root_tree->selection_mode == GTK_SELECTION_BROWSE))
864 g_print("* BROWSE mode, select another item\n");
865 #endif /* TREE_DEBUG */
866 widget = root_tree->children->data;
867 gtk_tree_select_child (root_tree, widget);
870 if (GTK_WIDGET_VISIBLE (root_tree))
873 g_print("* query queue resizing for root_tree\n");
874 #endif /* TREE_DEBUG */
875 gtk_widget_queue_resize (GTK_WIDGET (root_tree));
880 gtk_tree_select_child (GtkTree *tree,
881 GtkWidget *tree_item)
883 g_return_if_fail (tree != NULL);
884 g_return_if_fail (GTK_IS_TREE (tree));
885 g_return_if_fail (tree_item != NULL);
886 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
888 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], tree_item);
892 gtk_tree_select_item (GtkTree *tree,
897 g_return_if_fail (tree != NULL);
898 g_return_if_fail (GTK_IS_TREE (tree));
900 tmp_list = g_list_nth (tree->children, item);
902 gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
907 gtk_tree_size_allocate (GtkWidget *widget,
908 GtkAllocation *allocation)
911 GtkWidget *child, *subtree;
912 GtkAllocation child_allocation;
916 g_return_if_fail (widget != NULL);
917 g_return_if_fail (GTK_IS_TREE (widget));
918 g_return_if_fail (allocation != NULL);
920 tree = GTK_TREE (widget);
922 widget->allocation = *allocation;
923 if (GTK_WIDGET_REALIZED (widget))
924 gdk_window_move_resize (widget->window,
925 allocation->x, allocation->y,
926 allocation->width, allocation->height);
930 child_allocation.x = GTK_CONTAINER (tree)->border_width;
931 child_allocation.y = GTK_CONTAINER (tree)->border_width;
932 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
934 children = tree->children;
938 child = children->data;
939 children = children->next;
941 if (GTK_WIDGET_VISIBLE (child))
943 child_allocation.height = child->requisition.height;
945 gtk_widget_size_allocate (child, &child_allocation);
947 child_allocation.y += child_allocation.height;
949 if((subtree = GTK_TREE_ITEM(child)->subtree))
950 if(GTK_WIDGET_VISIBLE (subtree))
952 child_allocation.height = subtree->requisition.height;
953 gtk_widget_size_allocate (subtree, &child_allocation);
954 child_allocation.y += child_allocation.height;
963 gtk_tree_size_request (GtkWidget *widget,
964 GtkRequisition *requisition)
967 GtkWidget *child, *subtree;
971 g_return_if_fail (widget != NULL);
972 g_return_if_fail (GTK_IS_TREE (widget));
973 g_return_if_fail (requisition != NULL);
975 tree = GTK_TREE (widget);
976 requisition->width = 0;
977 requisition->height = 0;
979 children = tree->children;
982 child = children->data;
983 children = children->next;
985 if (GTK_WIDGET_VISIBLE (child))
987 gtk_widget_size_request (child, &child->requisition);
989 requisition->width = MAX (requisition->width, child->requisition.width);
990 requisition->height += child->requisition.height;
992 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
993 GTK_WIDGET_VISIBLE (subtree))
995 gtk_widget_size_request (subtree, &subtree->requisition);
997 requisition->width = MAX (requisition->width,
998 subtree->requisition.width);
1000 requisition->height += subtree->requisition.height;
1005 requisition->width += GTK_CONTAINER (tree)->border_width * 2;
1006 requisition->height += GTK_CONTAINER (tree)->border_width * 2;
1008 requisition->width = MAX (requisition->width, 1);
1009 requisition->height = MAX (requisition->height, 1);
1014 gtk_tree_unmap (GtkWidget *widget)
1017 g_return_if_fail (widget != NULL);
1018 g_return_if_fail (GTK_IS_TREE (widget));
1020 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1021 gdk_window_hide (widget->window);
1026 gtk_tree_unselect_child (GtkTree *tree,
1027 GtkWidget *tree_item)
1029 g_return_if_fail (tree != NULL);
1030 g_return_if_fail (GTK_IS_TREE (tree));
1031 g_return_if_fail (tree_item != NULL);
1032 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1034 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1038 gtk_tree_unselect_item (GtkTree *tree,
1043 g_return_if_fail (tree != NULL);
1044 g_return_if_fail (GTK_IS_TREE (tree));
1046 tmp_list = g_list_nth (tree->children, item);
1048 gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1053 gtk_real_tree_select_child (GtkTree *tree,
1056 GList *selection, *root_selection;
1058 GtkWidget *tmp_item;
1060 g_return_if_fail (tree != NULL);
1061 g_return_if_fail (GTK_IS_TREE (tree));
1062 g_return_if_fail (child != NULL);
1063 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1065 root_selection = tree->root_tree->selection;
1067 switch (tree->root_tree->selection_mode)
1069 case GTK_SELECTION_SINGLE:
1071 selection = root_selection;
1073 /* remove old selection list */
1076 tmp_item = selection->data;
1078 if (tmp_item != child)
1080 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1082 tmp_list = selection;
1083 selection = selection->next;
1085 root_selection = g_list_remove_link (root_selection, tmp_list);
1086 gtk_widget_unref (tmp_item);
1088 g_list_free (tmp_list);
1091 selection = selection->next;
1094 if (child->state == GTK_STATE_NORMAL)
1096 gtk_tree_item_select (GTK_TREE_ITEM (child));
1097 root_selection = g_list_prepend (root_selection, child);
1098 gtk_widget_ref (child);
1100 else if (child->state == GTK_STATE_SELECTED)
1102 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1103 root_selection = g_list_remove (root_selection, child);
1104 gtk_widget_unref (child);
1107 tree->root_tree->selection = root_selection;
1109 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1110 tree_signals[SELECTION_CHANGED]);
1114 case GTK_SELECTION_BROWSE:
1115 selection = root_selection;
1119 tmp_item = selection->data;
1121 if (tmp_item != child)
1123 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1125 tmp_list = selection;
1126 selection = selection->next;
1128 root_selection = g_list_remove_link (root_selection, tmp_list);
1129 gtk_widget_unref (tmp_item);
1131 g_list_free (tmp_list);
1134 selection = selection->next;
1137 tree->root_tree->selection = root_selection;
1139 if (child->state == GTK_STATE_NORMAL)
1141 gtk_tree_item_select (GTK_TREE_ITEM (child));
1142 root_selection = g_list_prepend (root_selection, child);
1143 gtk_widget_ref (child);
1144 tree->root_tree->selection = root_selection;
1145 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1146 tree_signals[SELECTION_CHANGED]);
1150 case GTK_SELECTION_MULTIPLE:
1151 if (child->state == GTK_STATE_NORMAL)
1153 gtk_tree_item_select (GTK_TREE_ITEM (child));
1154 root_selection = g_list_prepend (root_selection, child);
1155 gtk_widget_ref (child);
1156 tree->root_tree->selection = root_selection;
1157 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1158 tree_signals[SELECTION_CHANGED]);
1160 else if (child->state == GTK_STATE_SELECTED)
1162 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1163 root_selection = g_list_remove (root_selection, child);
1164 gtk_widget_unref (child);
1165 tree->root_tree->selection = root_selection;
1166 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1167 tree_signals[SELECTION_CHANGED]);
1171 case GTK_SELECTION_EXTENDED:
1177 gtk_real_tree_unselect_child (GtkTree *tree,
1180 g_return_if_fail (tree != NULL);
1181 g_return_if_fail (GTK_IS_TREE (tree));
1182 g_return_if_fail (child != NULL);
1183 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1185 switch (tree->selection_mode)
1187 case GTK_SELECTION_SINGLE:
1188 case GTK_SELECTION_MULTIPLE:
1189 case GTK_SELECTION_BROWSE:
1190 if (child->state == GTK_STATE_SELECTED)
1192 GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1193 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1194 root_tree->selection = g_list_remove (root_tree->selection, child);
1195 gtk_widget_unref (child);
1196 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1197 tree_signals[SELECTION_CHANGED]);
1201 case GTK_SELECTION_EXTENDED:
1207 gtk_tree_set_selection_mode (GtkTree *tree,
1208 GtkSelectionMode mode)
1210 g_return_if_fail (tree != NULL);
1211 g_return_if_fail (GTK_IS_TREE (tree));
1213 tree->selection_mode = mode;
1217 gtk_tree_set_view_mode (GtkTree *tree,
1218 GtkTreeViewMode mode)
1220 g_return_if_fail (tree != NULL);
1221 g_return_if_fail (GTK_IS_TREE (tree));
1223 tree->view_mode = mode;
1227 gtk_tree_set_view_lines (GtkTree *tree,
1230 g_return_if_fail (tree != NULL);
1231 g_return_if_fail (GTK_IS_TREE (tree));
1233 tree->view_line = flag;