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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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 * Modified by the GTK+ Team and others 1997-2000. 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/.
28 #include "gtksignal.h"
31 #define GTK_ENABLE_BROKEN
33 #include "gtktreeitem.h"
42 static void gtk_tree_class_init (GtkTreeClass *klass);
43 static void gtk_tree_init (GtkTree *tree);
44 static void gtk_tree_destroy (GtkObject *object);
45 static void gtk_tree_map (GtkWidget *widget);
46 static void gtk_tree_parent_set (GtkWidget *widget,
47 GtkWidget *previous_parent);
48 static void gtk_tree_unmap (GtkWidget *widget);
49 static void gtk_tree_realize (GtkWidget *widget);
50 static gint gtk_tree_motion_notify (GtkWidget *widget,
51 GdkEventMotion *event);
52 static gint gtk_tree_button_press (GtkWidget *widget,
53 GdkEventButton *event);
54 static gint gtk_tree_button_release (GtkWidget *widget,
55 GdkEventButton *event);
56 static void gtk_tree_size_request (GtkWidget *widget,
57 GtkRequisition *requisition);
58 static void gtk_tree_size_allocate (GtkWidget *widget,
59 GtkAllocation *allocation);
60 static void gtk_tree_add (GtkContainer *container,
62 static void gtk_tree_forall (GtkContainer *container,
63 gboolean include_internals,
65 gpointer callback_data);
67 static void gtk_real_tree_select_child (GtkTree *tree,
69 static void gtk_real_tree_unselect_child (GtkTree *tree,
72 static GtkType gtk_tree_child_type (GtkContainer *container);
74 static GtkContainerClass *parent_class = NULL;
75 static guint tree_signals[LAST_SIGNAL] = { 0 };
78 gtk_tree_get_type (void)
80 static GtkType tree_type = 0;
84 static const GtkTypeInfo tree_info =
88 sizeof (GtkTreeClass),
89 (GtkClassInitFunc) gtk_tree_class_init,
90 (GtkObjectInitFunc) gtk_tree_init,
91 /* reserved_1 */ NULL,
92 /* reserved_2 */ NULL,
93 (GtkClassInitFunc) NULL,
96 tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
103 gtk_tree_class_init (GtkTreeClass *class)
105 GtkObjectClass *object_class;
106 GtkWidgetClass *widget_class;
107 GtkContainerClass *container_class;
109 object_class = (GtkObjectClass*) class;
110 widget_class = (GtkWidgetClass*) class;
111 container_class = (GtkContainerClass*) class;
113 parent_class = gtk_type_class (gtk_container_get_type ());
116 object_class->destroy = gtk_tree_destroy;
118 widget_class->map = gtk_tree_map;
119 widget_class->unmap = gtk_tree_unmap;
120 widget_class->parent_set = gtk_tree_parent_set;
121 widget_class->realize = gtk_tree_realize;
122 widget_class->motion_notify_event = gtk_tree_motion_notify;
123 widget_class->button_press_event = gtk_tree_button_press;
124 widget_class->button_release_event = gtk_tree_button_release;
125 widget_class->size_request = gtk_tree_size_request;
126 widget_class->size_allocate = gtk_tree_size_allocate;
128 container_class->add = gtk_tree_add;
129 container_class->remove =
130 (void (*)(GtkContainer *, GtkWidget *)) gtk_tree_remove_item;
131 container_class->forall = gtk_tree_forall;
132 container_class->child_type = gtk_tree_child_type;
134 class->selection_changed = NULL;
135 class->select_child = gtk_real_tree_select_child;
136 class->unselect_child = gtk_real_tree_unselect_child;
138 tree_signals[SELECTION_CHANGED] =
139 gtk_signal_new ("selection_changed",
141 GTK_CLASS_TYPE (object_class),
142 GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
143 gtk_marshal_VOID__VOID,
145 tree_signals[SELECT_CHILD] =
146 gtk_signal_new ("select_child",
148 GTK_CLASS_TYPE (object_class),
149 GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
150 gtk_marshal_VOID__OBJECT,
153 tree_signals[UNSELECT_CHILD] =
154 gtk_signal_new ("unselect_child",
156 GTK_CLASS_TYPE (object_class),
157 GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
158 gtk_marshal_VOID__OBJECT,
164 gtk_tree_child_type (GtkContainer *container)
166 return GTK_TYPE_TREE_ITEM;
170 gtk_tree_init (GtkTree *tree)
172 tree->children = NULL;
173 tree->root_tree = tree;
174 tree->selection = NULL;
175 tree->tree_owner = NULL;
176 tree->selection_mode = GTK_SELECTION_SINGLE;
177 tree->indent_value = 9;
178 tree->current_indent = 0;
180 tree->view_mode = GTK_TREE_VIEW_LINE;
187 return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
191 gtk_tree_append (GtkTree *tree,
192 GtkWidget *tree_item)
194 g_return_if_fail (tree != NULL);
195 g_return_if_fail (GTK_IS_TREE (tree));
196 g_return_if_fail (tree_item != NULL);
197 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
199 gtk_tree_insert (tree, tree_item, -1);
203 gtk_tree_prepend (GtkTree *tree,
204 GtkWidget *tree_item)
206 g_return_if_fail (tree != NULL);
207 g_return_if_fail (GTK_IS_TREE (tree));
208 g_return_if_fail (tree_item != NULL);
209 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
211 gtk_tree_insert (tree, tree_item, 0);
215 gtk_tree_insert (GtkTree *tree,
216 GtkWidget *tree_item,
221 g_return_if_fail (tree != NULL);
222 g_return_if_fail (GTK_IS_TREE (tree));
223 g_return_if_fail (tree_item != NULL);
224 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
226 nchildren = g_list_length (tree->children);
228 if ((position < 0) || (position > nchildren))
229 position = nchildren;
231 if (position == nchildren)
232 tree->children = g_list_append (tree->children, tree_item);
234 tree->children = g_list_insert (tree->children, tree_item, position);
236 gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
238 if (GTK_WIDGET_REALIZED (tree_item->parent))
239 gtk_widget_realize (tree_item);
241 if (GTK_WIDGET_VISIBLE (tree_item->parent) && GTK_WIDGET_VISIBLE (tree_item))
243 if (GTK_WIDGET_MAPPED (tree_item->parent))
244 gtk_widget_map (tree_item);
246 gtk_widget_queue_resize (tree_item);
251 gtk_tree_add (GtkContainer *container,
256 g_return_if_fail (container != NULL);
257 g_return_if_fail (GTK_IS_TREE (container));
258 g_return_if_fail (GTK_IS_TREE_ITEM (child));
260 tree = GTK_TREE (container);
262 tree->children = g_list_append (tree->children, child);
264 gtk_widget_set_parent (child, GTK_WIDGET (container));
266 if (GTK_WIDGET_REALIZED (child->parent))
267 gtk_widget_realize (child);
269 if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
271 if (GTK_WIDGET_MAPPED (child->parent))
272 gtk_widget_map (child);
274 gtk_widget_queue_resize (child);
277 if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
278 gtk_tree_select_child (tree, child);
282 gtk_tree_button_press (GtkWidget *widget,
283 GdkEventButton *event)
288 g_return_val_if_fail (widget != NULL, FALSE);
289 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
290 g_return_val_if_fail (event != NULL, FALSE);
292 tree = GTK_TREE (widget);
293 item = gtk_get_event_widget ((GdkEvent*) event);
295 while (item && !GTK_IS_TREE_ITEM (item))
298 if (!item || (item->parent != widget))
301 switch(event->button)
304 gtk_tree_select_child (tree, item);
307 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
310 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
318 gtk_tree_button_release (GtkWidget *widget,
319 GdkEventButton *event)
324 g_return_val_if_fail (widget != NULL, FALSE);
325 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
326 g_return_val_if_fail (event != NULL, FALSE);
328 tree = GTK_TREE (widget);
329 item = gtk_get_event_widget ((GdkEvent*) event);
335 gtk_tree_child_position (GtkTree *tree,
342 g_return_val_if_fail (tree != NULL, -1);
343 g_return_val_if_fail (GTK_IS_TREE (tree), -1);
344 g_return_val_if_fail (child != NULL, -1);
347 children = tree->children;
351 if (child == GTK_WIDGET (children->data))
355 children = children->next;
363 gtk_tree_clear_items (GtkTree *tree,
373 g_return_if_fail (tree != NULL);
374 g_return_if_fail (GTK_IS_TREE (tree));
376 nchildren = g_list_length (tree->children);
380 if ((end < 0) || (end > nchildren))
386 tmp_list = g_list_nth (tree->children, start);
389 while (tmp_list && index <= end)
391 widget = tmp_list->data;
392 tmp_list = tmp_list->next;
395 clear_list = g_list_prepend (clear_list, widget);
398 gtk_tree_remove_items (tree, clear_list);
403 gtk_tree_destroy (GtkObject *object)
409 g_return_if_fail (object != NULL);
410 g_return_if_fail (GTK_IS_TREE (object));
412 tree = GTK_TREE (object);
414 children = tree->children;
417 child = children->data;
418 children = children->next;
420 gtk_widget_ref (child);
421 gtk_widget_unparent (child);
422 gtk_widget_destroy (child);
423 gtk_widget_unref (child);
426 g_list_free (tree->children);
427 tree->children = NULL;
429 if (tree->root_tree == tree)
432 for (node = tree->selection; node; node = node->next)
433 gtk_widget_unref ((GtkWidget *)node->data);
434 g_list_free (tree->selection);
435 tree->selection = NULL;
438 if (GTK_OBJECT_CLASS (parent_class)->destroy)
439 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
443 gtk_tree_forall (GtkContainer *container,
444 gboolean include_internals,
445 GtkCallback callback,
446 gpointer callback_data)
453 g_return_if_fail (container != NULL);
454 g_return_if_fail (GTK_IS_TREE (container));
455 g_return_if_fail (callback != NULL);
457 tree = GTK_TREE (container);
458 children = tree->children;
462 child = children->data;
463 children = children->next;
465 (* callback) (child, callback_data);
470 gtk_tree_unselect_all (GtkTree *tree)
472 GList *tmp_list, *selection;
475 selection = tree->selection;
476 tree->selection = NULL;
478 tmp_list = selection;
481 tmp_item = selection->data;
483 if (tmp_item->parent &&
484 GTK_IS_TREE (tmp_item->parent) &&
485 GTK_TREE (tmp_item->parent)->root_tree == tree)
486 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
488 gtk_widget_unref (tmp_item);
490 tmp_list = tmp_list->next;
493 g_list_free (selection);
497 gtk_tree_parent_set (GtkWidget *widget,
498 GtkWidget *previous_parent)
500 GtkTree *tree = GTK_TREE (widget);
504 if (widget->parent && GTK_IS_TREE (widget->parent))
506 gtk_tree_unselect_all (tree);
508 /* set root tree for this tree */
509 tree->root_tree = GTK_TREE(widget->parent)->root_tree;
511 tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
512 tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
513 tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
515 tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
516 tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
520 tree->root_tree = tree;
523 tree->current_indent = 0;
526 children = tree->children;
529 child = children->data;
530 children = children->next;
532 if (GTK_TREE_ITEM (child)->subtree)
533 gtk_tree_parent_set (GTK_TREE_ITEM (child)->subtree, child);
538 gtk_tree_map (GtkWidget *widget)
540 GtkTree *tree = GTK_TREE (widget);
544 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
546 children = tree->children;
549 child = children->data;
550 children = children->next;
552 if (GTK_WIDGET_VISIBLE (child) &&
553 !GTK_WIDGET_MAPPED (child))
554 gtk_widget_map (child);
556 if (GTK_TREE_ITEM (child)->subtree)
558 child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
560 if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
561 gtk_widget_map (child);
565 gdk_window_show (widget->window);
569 gtk_tree_motion_notify (GtkWidget *widget,
570 GdkEventMotion *event)
572 g_return_val_if_fail (widget != NULL, FALSE);
573 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
574 g_return_val_if_fail (event != NULL, FALSE);
577 g_message("gtk_tree_motion_notify\n");
578 #endif /* TREE_DEBUG */
584 gtk_tree_realize (GtkWidget *widget)
586 GdkWindowAttr attributes;
587 gint attributes_mask;
590 g_return_if_fail (widget != NULL);
591 g_return_if_fail (GTK_IS_TREE (widget));
593 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
595 attributes.window_type = GDK_WINDOW_CHILD;
596 attributes.x = widget->allocation.x;
597 attributes.y = widget->allocation.y;
598 attributes.width = widget->allocation.width;
599 attributes.height = widget->allocation.height;
600 attributes.wclass = GDK_INPUT_OUTPUT;
601 attributes.visual = gtk_widget_get_visual (widget);
602 attributes.colormap = gtk_widget_get_colormap (widget);
603 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
605 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
607 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
608 gdk_window_set_user_data (widget->window, widget);
610 widget->style = gtk_style_attach (widget->style, widget->window);
611 gdk_window_set_background (widget->window,
612 &widget->style->base[GTK_STATE_NORMAL]);
616 gtk_tree_remove_item (GtkTree *container,
621 g_return_if_fail (container != NULL);
622 g_return_if_fail (GTK_IS_TREE (container));
623 g_return_if_fail (widget != NULL);
624 g_return_if_fail (container == GTK_TREE (widget->parent));
626 item_list = g_list_append (NULL, widget);
628 gtk_tree_remove_items (GTK_TREE (container), item_list);
630 g_list_free (item_list);
633 /* used by gtk_tree_remove_items to make the function independant of
634 order in list of items to remove.
635 Sort item bu depth in tree */
637 gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
639 if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
641 if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
648 gtk_tree_remove_items (GtkTree *tree,
652 GList *selected_widgets;
658 g_return_if_fail (tree != NULL);
659 g_return_if_fail (GTK_IS_TREE (tree));
662 g_message("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
663 #endif /* TREE_DEBUG */
665 /* We may not yet be mapped, so we actively have to find our
669 root_tree = tree->root_tree;
672 GtkWidget *tmp = GTK_WIDGET (tree);
673 while (tmp->parent && GTK_IS_TREE (tmp->parent))
676 root_tree = GTK_TREE (tmp);
680 selected_widgets = NULL;
685 g_message("* sort list by depth\n");
686 #endif /* TREE_DEBUG */
692 g_message ("* item [%#x] depth [%d]\n",
694 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
695 #endif /* TREE_DEBUG */
697 sorted_list = g_list_insert_sorted(sorted_list,
699 (GCompareFunc)gtk_tree_sort_item_by_depth);
700 tmp_list = g_list_next(tmp_list);
704 /* print sorted list */
705 g_message("* sorted list result\n");
706 tmp_list = sorted_list;
709 g_message("* item [%#x] depth [%d]\n",
711 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
712 tmp_list = g_list_next(tmp_list);
714 #endif /* TREE_DEBUG */
717 g_message("* scan sorted list\n");
718 #endif /* TREE_DEBUG */
720 tmp_list = sorted_list;
723 widget = tmp_list->data;
724 tmp_list = tmp_list->next;
727 g_message("* item [%#x] subtree [%#x]\n",
728 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
729 #endif /* TREE_DEBUG */
731 /* get real owner of this widget */
732 real_tree = GTK_TREE(widget->parent);
734 g_message("* subtree having this widget [%#x]\n", (int)real_tree);
735 #endif /* TREE_DEBUG */
738 if (widget->state == GTK_STATE_SELECTED)
740 selected_widgets = g_list_prepend (selected_widgets, widget);
742 g_message("* selected widget - adding it in selected list [%#x]\n",
743 (int)selected_widgets);
744 #endif /* TREE_DEBUG */
747 /* remove this item from its real parent */
749 g_message("* remove widget from its owner tree\n");
750 #endif /* TREE_DEBUG */
751 real_tree->children = g_list_remove (real_tree->children, widget);
753 /* remove subtree associate at this item if it exist */
754 if(GTK_TREE_ITEM(widget)->subtree)
757 g_message("* remove subtree associate at this item [%#x]\n",
758 (int) GTK_TREE_ITEM(widget)->subtree);
759 #endif /* TREE_DEBUG */
760 if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
761 gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
763 gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
764 GTK_TREE_ITEM(widget)->subtree = NULL;
767 /* really remove widget for this item */
769 g_message("* unmap and unparent widget [%#x]\n", (int)widget);
770 #endif /* TREE_DEBUG */
771 if (GTK_WIDGET_MAPPED (widget))
772 gtk_widget_unmap (widget);
774 gtk_widget_unparent (widget);
776 /* delete subtree if there is no children in it */
777 if(real_tree->children == NULL &&
778 real_tree != root_tree)
781 g_message("* owner tree don't have children ... destroy it\n");
782 #endif /* TREE_DEBUG */
783 gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
787 g_message("* next item in list\n");
788 #endif /* TREE_DEBUG */
791 if (selected_widgets)
794 g_message("* scan selected item list\n");
795 #endif /* TREE_DEBUG */
796 tmp_list = selected_widgets;
799 widget = tmp_list->data;
800 tmp_list = tmp_list->next;
803 g_message("* widget [%#x] subtree [%#x]\n",
804 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
805 #endif /* TREE_DEBUG */
807 /* remove widget of selection */
808 root_tree->selection = g_list_remove (root_tree->selection, widget);
810 /* unref it to authorize is destruction */
811 gtk_widget_unref (widget);
814 /* emit only one selection_changed signal */
815 gtk_signal_emit (GTK_OBJECT (root_tree),
816 tree_signals[SELECTION_CHANGED]);
820 g_message("* free selected_widgets list\n");
821 #endif /* TREE_DEBUG */
822 g_list_free (selected_widgets);
823 g_list_free (sorted_list);
825 if (root_tree->children && !root_tree->selection &&
826 (root_tree->selection_mode == GTK_SELECTION_BROWSE))
829 g_message("* BROWSE mode, select another item\n");
830 #endif /* TREE_DEBUG */
831 widget = root_tree->children->data;
832 gtk_tree_select_child (root_tree, widget);
835 if (GTK_WIDGET_VISIBLE (root_tree))
838 g_message("* query queue resizing for root_tree\n");
839 #endif /* TREE_DEBUG */
840 gtk_widget_queue_resize (GTK_WIDGET (root_tree));
845 gtk_tree_select_child (GtkTree *tree,
846 GtkWidget *tree_item)
848 g_return_if_fail (tree != NULL);
849 g_return_if_fail (GTK_IS_TREE (tree));
850 g_return_if_fail (tree_item != NULL);
851 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
853 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], tree_item);
857 gtk_tree_select_item (GtkTree *tree,
862 g_return_if_fail (tree != NULL);
863 g_return_if_fail (GTK_IS_TREE (tree));
865 tmp_list = g_list_nth (tree->children, item);
867 gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
872 gtk_tree_size_allocate (GtkWidget *widget,
873 GtkAllocation *allocation)
876 GtkWidget *child, *subtree;
877 GtkAllocation child_allocation;
881 g_return_if_fail (widget != NULL);
882 g_return_if_fail (GTK_IS_TREE (widget));
883 g_return_if_fail (allocation != NULL);
885 tree = GTK_TREE (widget);
887 widget->allocation = *allocation;
888 if (GTK_WIDGET_REALIZED (widget))
889 gdk_window_move_resize (widget->window,
890 allocation->x, allocation->y,
891 allocation->width, allocation->height);
895 child_allocation.x = GTK_CONTAINER (tree)->border_width;
896 child_allocation.y = GTK_CONTAINER (tree)->border_width;
897 child_allocation.width = MAX (1, (gint)allocation->width - child_allocation.x * 2);
899 children = tree->children;
903 child = children->data;
904 children = children->next;
906 if (GTK_WIDGET_VISIBLE (child))
908 GtkRequisition child_requisition;
909 gtk_widget_get_child_requisition (child, &child_requisition);
911 child_allocation.height = child_requisition.height;
913 gtk_widget_size_allocate (child, &child_allocation);
915 child_allocation.y += child_allocation.height;
917 if((subtree = GTK_TREE_ITEM(child)->subtree))
918 if(GTK_WIDGET_VISIBLE (subtree))
920 child_allocation.height = subtree->requisition.height;
921 gtk_widget_size_allocate (subtree, &child_allocation);
922 child_allocation.y += child_allocation.height;
931 gtk_tree_size_request (GtkWidget *widget,
932 GtkRequisition *requisition)
935 GtkWidget *child, *subtree;
937 GtkRequisition child_requisition;
940 g_return_if_fail (widget != NULL);
941 g_return_if_fail (GTK_IS_TREE (widget));
942 g_return_if_fail (requisition != NULL);
944 tree = GTK_TREE (widget);
945 requisition->width = 0;
946 requisition->height = 0;
948 children = tree->children;
951 child = children->data;
952 children = children->next;
954 if (GTK_WIDGET_VISIBLE (child))
956 gtk_widget_size_request (child, &child_requisition);
958 requisition->width = MAX (requisition->width, child_requisition.width);
959 requisition->height += child_requisition.height;
961 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
962 GTK_WIDGET_VISIBLE (subtree))
964 gtk_widget_size_request (subtree, &child_requisition);
966 requisition->width = MAX (requisition->width,
967 child_requisition.width);
969 requisition->height += child_requisition.height;
974 requisition->width += GTK_CONTAINER (tree)->border_width * 2;
975 requisition->height += GTK_CONTAINER (tree)->border_width * 2;
977 requisition->width = MAX (requisition->width, 1);
978 requisition->height = MAX (requisition->height, 1);
983 gtk_tree_unmap (GtkWidget *widget)
986 g_return_if_fail (widget != NULL);
987 g_return_if_fail (GTK_IS_TREE (widget));
989 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
990 gdk_window_hide (widget->window);
995 gtk_tree_unselect_child (GtkTree *tree,
996 GtkWidget *tree_item)
998 g_return_if_fail (tree != NULL);
999 g_return_if_fail (GTK_IS_TREE (tree));
1000 g_return_if_fail (tree_item != NULL);
1001 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1003 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1007 gtk_tree_unselect_item (GtkTree *tree,
1012 g_return_if_fail (tree != NULL);
1013 g_return_if_fail (GTK_IS_TREE (tree));
1015 tmp_list = g_list_nth (tree->children, item);
1017 gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1022 gtk_real_tree_select_child (GtkTree *tree,
1025 GList *selection, *root_selection;
1027 GtkWidget *tmp_item;
1029 g_return_if_fail (tree != NULL);
1030 g_return_if_fail (GTK_IS_TREE (tree));
1031 g_return_if_fail (child != NULL);
1032 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1034 root_selection = tree->root_tree->selection;
1036 switch (tree->root_tree->selection_mode)
1038 case GTK_SELECTION_SINGLE:
1040 selection = root_selection;
1042 /* remove old selection list */
1045 tmp_item = selection->data;
1047 if (tmp_item != child)
1049 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1051 tmp_list = selection;
1052 selection = selection->next;
1054 root_selection = g_list_remove_link (root_selection, tmp_list);
1055 gtk_widget_unref (tmp_item);
1057 g_list_free (tmp_list);
1060 selection = selection->next;
1063 if (child->state == GTK_STATE_NORMAL)
1065 gtk_tree_item_select (GTK_TREE_ITEM (child));
1066 root_selection = g_list_prepend (root_selection, child);
1067 gtk_widget_ref (child);
1069 else if (child->state == GTK_STATE_SELECTED)
1071 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1072 root_selection = g_list_remove (root_selection, child);
1073 gtk_widget_unref (child);
1076 tree->root_tree->selection = root_selection;
1078 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1079 tree_signals[SELECTION_CHANGED]);
1083 case GTK_SELECTION_BROWSE:
1084 selection = root_selection;
1088 tmp_item = selection->data;
1090 if (tmp_item != child)
1092 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1094 tmp_list = selection;
1095 selection = selection->next;
1097 root_selection = g_list_remove_link (root_selection, tmp_list);
1098 gtk_widget_unref (tmp_item);
1100 g_list_free (tmp_list);
1103 selection = selection->next;
1106 tree->root_tree->selection = root_selection;
1108 if (child->state == GTK_STATE_NORMAL)
1110 gtk_tree_item_select (GTK_TREE_ITEM (child));
1111 root_selection = g_list_prepend (root_selection, child);
1112 gtk_widget_ref (child);
1113 tree->root_tree->selection = root_selection;
1114 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1115 tree_signals[SELECTION_CHANGED]);
1119 case GTK_SELECTION_MULTIPLE:
1120 if (child->state == GTK_STATE_NORMAL)
1122 gtk_tree_item_select (GTK_TREE_ITEM (child));
1123 root_selection = g_list_prepend (root_selection, child);
1124 gtk_widget_ref (child);
1125 tree->root_tree->selection = root_selection;
1126 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1127 tree_signals[SELECTION_CHANGED]);
1129 else if (child->state == GTK_STATE_SELECTED)
1131 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1132 root_selection = g_list_remove (root_selection, child);
1133 gtk_widget_unref (child);
1134 tree->root_tree->selection = root_selection;
1135 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1136 tree_signals[SELECTION_CHANGED]);
1140 case GTK_SELECTION_EXTENDED:
1146 gtk_real_tree_unselect_child (GtkTree *tree,
1149 g_return_if_fail (tree != NULL);
1150 g_return_if_fail (GTK_IS_TREE (tree));
1151 g_return_if_fail (child != NULL);
1152 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1154 switch (tree->selection_mode)
1156 case GTK_SELECTION_SINGLE:
1157 case GTK_SELECTION_MULTIPLE:
1158 case GTK_SELECTION_BROWSE:
1159 if (child->state == GTK_STATE_SELECTED)
1161 GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1162 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1163 root_tree->selection = g_list_remove (root_tree->selection, child);
1164 gtk_widget_unref (child);
1165 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1166 tree_signals[SELECTION_CHANGED]);
1170 case GTK_SELECTION_EXTENDED:
1176 gtk_tree_set_selection_mode (GtkTree *tree,
1177 GtkSelectionMode mode)
1179 g_return_if_fail (tree != NULL);
1180 g_return_if_fail (GTK_IS_TREE (tree));
1182 tree->selection_mode = mode;
1186 gtk_tree_set_view_mode (GtkTree *tree,
1187 GtkTreeViewMode mode)
1189 g_return_if_fail (tree != NULL);
1190 g_return_if_fail (GTK_IS_TREE (tree));
1192 tree->view_mode = mode;
1196 gtk_tree_set_view_lines (GtkTree *tree,
1199 g_return_if_fail (tree != NULL);
1200 g_return_if_fail (GTK_IS_TREE (tree));
1202 tree->view_line = flag;