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 static void gtk_tree_class_init (GtkTreeClass *klass);
33 static void gtk_tree_init (GtkTree *tree);
34 static void gtk_tree_destroy (GtkObject *object);
35 static void gtk_tree_map (GtkWidget *widget);
36 static void gtk_tree_unmap (GtkWidget *widget);
37 static void gtk_tree_realize (GtkWidget *widget);
38 static void gtk_tree_draw (GtkWidget *widget,
40 static gint gtk_tree_expose (GtkWidget *widget,
41 GdkEventExpose *event);
42 static gint gtk_tree_motion_notify (GtkWidget *widget,
43 GdkEventMotion *event);
44 static gint gtk_tree_button_press (GtkWidget *widget,
45 GdkEventButton *event);
46 static gint gtk_tree_button_release (GtkWidget *widget,
47 GdkEventButton *event);
48 static void gtk_tree_size_request (GtkWidget *widget,
49 GtkRequisition *requisition);
50 static void gtk_tree_size_allocate (GtkWidget *widget,
51 GtkAllocation *allocation);
52 static void gtk_tree_add (GtkContainer *container,
54 static void gtk_tree_forall (GtkContainer *container,
55 gboolean include_internals,
57 gpointer callback_data);
59 static void gtk_real_tree_select_child (GtkTree *tree,
61 static void gtk_real_tree_unselect_child (GtkTree *tree,
64 static GtkType gtk_tree_child_type (GtkContainer *container);
66 static GtkContainerClass *parent_class = NULL;
67 static guint tree_signals[LAST_SIGNAL] = { 0 };
70 gtk_tree_get_type (void)
72 static GtkType tree_type = 0;
76 GtkTypeInfo tree_info =
80 sizeof (GtkTreeClass),
81 (GtkClassInitFunc) gtk_tree_class_init,
82 (GtkObjectInitFunc) gtk_tree_init,
83 /* reserved_1 */ NULL,
84 /* reserved_2 */ NULL,
85 (GtkClassInitFunc) NULL,
88 tree_type = gtk_type_unique (gtk_container_get_type (), &tree_info);
95 gtk_tree_class_init (GtkTreeClass *class)
97 GtkObjectClass *object_class;
98 GtkWidgetClass *widget_class;
99 GtkContainerClass *container_class;
101 object_class = (GtkObjectClass*) class;
102 widget_class = (GtkWidgetClass*) class;
103 container_class = (GtkContainerClass*) class;
105 parent_class = gtk_type_class (gtk_container_get_type ());
107 tree_signals[SELECTION_CHANGED] =
108 gtk_signal_new ("selection_changed",
111 GTK_SIGNAL_OFFSET (GtkTreeClass, selection_changed),
112 gtk_marshal_NONE__NONE,
114 tree_signals[SELECT_CHILD] =
115 gtk_signal_new ("select_child",
118 GTK_SIGNAL_OFFSET (GtkTreeClass, select_child),
119 gtk_marshal_NONE__POINTER,
122 tree_signals[UNSELECT_CHILD] =
123 gtk_signal_new ("unselect_child",
126 GTK_SIGNAL_OFFSET (GtkTreeClass, unselect_child),
127 gtk_marshal_NONE__POINTER,
131 gtk_object_class_add_signals (object_class, tree_signals, LAST_SIGNAL);
133 object_class->destroy = gtk_tree_destroy;
135 widget_class->map = gtk_tree_map;
136 widget_class->unmap = gtk_tree_unmap;
137 widget_class->realize = gtk_tree_realize;
138 widget_class->draw = gtk_tree_draw;
139 widget_class->expose_event = gtk_tree_expose;
140 widget_class->motion_notify_event = gtk_tree_motion_notify;
141 widget_class->button_press_event = gtk_tree_button_press;
142 widget_class->button_release_event = gtk_tree_button_release;
143 widget_class->size_request = gtk_tree_size_request;
144 widget_class->size_allocate = gtk_tree_size_allocate;
146 container_class->add = gtk_tree_add;
147 container_class->remove =
148 (void (*)(GtkContainer *, GtkWidget *)) gtk_tree_remove_item;
149 container_class->forall = gtk_tree_forall;
150 container_class->child_type = gtk_tree_child_type;
152 class->selection_changed = NULL;
153 class->select_child = gtk_real_tree_select_child;
154 class->unselect_child = gtk_real_tree_unselect_child;
158 gtk_tree_child_type (GtkContainer *container)
160 return GTK_TYPE_TREE_ITEM;
164 gtk_tree_init (GtkTree *tree)
166 tree->children = NULL;
167 tree->root_tree = NULL;
168 tree->selection = NULL;
169 tree->tree_owner = NULL;
170 tree->selection_mode = GTK_SELECTION_SINGLE;
171 tree->indent_value = 9;
172 tree->current_indent = 0;
174 tree->view_mode = GTK_TREE_VIEW_LINE;
181 return GTK_WIDGET (gtk_type_new (gtk_tree_get_type ()));
185 gtk_tree_append (GtkTree *tree,
186 GtkWidget *tree_item)
188 g_return_if_fail (tree != NULL);
189 g_return_if_fail (GTK_IS_TREE (tree));
190 g_return_if_fail (tree_item != NULL);
191 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
193 gtk_tree_insert(tree, tree_item, -1);
197 gtk_tree_prepend (GtkTree *tree,
198 GtkWidget *tree_item)
200 g_return_if_fail (tree != NULL);
201 g_return_if_fail (GTK_IS_TREE (tree));
202 g_return_if_fail (tree_item != NULL);
203 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
205 gtk_tree_insert(tree, tree_item, 0);
209 gtk_tree_insert (GtkTree *tree,
210 GtkWidget *tree_item,
215 g_return_if_fail (tree != NULL);
216 g_return_if_fail (GTK_IS_TREE (tree));
217 g_return_if_fail (tree_item != NULL);
218 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
220 /* set parent widget to item */
221 gtk_widget_set_parent (tree_item, GTK_WIDGET (tree));
223 if (GTK_WIDGET_VISIBLE (tree_item->parent))
225 if (GTK_WIDGET_REALIZED (tree_item->parent) &&
226 !GTK_WIDGET_REALIZED (tree_item))
227 gtk_widget_realize (tree_item);
229 if (GTK_WIDGET_MAPPED (tree_item->parent) &&
230 !GTK_WIDGET_MAPPED (tree_item))
231 gtk_widget_map (tree_item);
234 nchildren = g_list_length (tree->children);
236 if ((position < 0) || (position > nchildren))
237 position = nchildren;
239 if (position == nchildren)
241 tree->children = g_list_append(tree->children, tree_item);
245 tree->children = g_list_insert(tree->children, tree_item, position);
248 if (GTK_WIDGET_VISIBLE (tree))
249 gtk_widget_queue_resize (GTK_WIDGET (tree));
254 gtk_tree_add (GtkContainer *container,
259 g_return_if_fail (container != NULL);
260 g_return_if_fail (GTK_IS_TREE (container));
261 g_return_if_fail (widget != NULL);
262 g_return_if_fail (GTK_IS_TREE_ITEM (widget));
264 tree = GTK_TREE (container);
266 gtk_widget_set_parent (widget, GTK_WIDGET (container));
267 if (GTK_WIDGET_VISIBLE (widget->parent))
269 if (GTK_WIDGET_REALIZED (widget->parent) &&
270 !GTK_WIDGET_REALIZED (widget))
271 gtk_widget_realize (widget);
273 if (GTK_WIDGET_MAPPED (widget->parent) &&
274 !GTK_WIDGET_MAPPED (widget))
275 gtk_widget_map (widget);
278 tree->children = g_list_append (tree->children, widget);
280 if (!tree->selection && (tree->selection_mode == GTK_SELECTION_BROWSE))
282 gtk_tree_select_child (tree, widget);
285 if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
286 gtk_widget_queue_resize (widget);
291 gtk_tree_button_press (GtkWidget *widget,
292 GdkEventButton *event)
297 g_return_val_if_fail (widget != NULL, FALSE);
298 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
299 g_return_val_if_fail (event != NULL, FALSE);
301 tree = GTK_TREE (widget);
302 item = gtk_get_event_widget ((GdkEvent*) event);
304 while (item && !GTK_IS_TREE_ITEM (item))
307 if (!item || (item->parent != widget))
310 switch(event->button)
313 gtk_tree_select_child (tree, item);
316 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_expand(GTK_TREE_ITEM(item));
319 if(GTK_TREE_ITEM(item)->subtree) gtk_tree_item_collapse(GTK_TREE_ITEM(item));
327 gtk_tree_button_release (GtkWidget *widget,
328 GdkEventButton *event)
333 g_return_val_if_fail (widget != NULL, FALSE);
334 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
335 g_return_val_if_fail (event != NULL, FALSE);
337 tree = GTK_TREE (widget);
338 item = gtk_get_event_widget ((GdkEvent*) event);
344 gtk_tree_child_position (GtkTree *tree,
351 g_return_val_if_fail (tree != NULL, -1);
352 g_return_val_if_fail (GTK_IS_TREE (tree), -1);
353 g_return_val_if_fail (child != NULL, -1);
356 children = tree->children;
360 if (child == GTK_WIDGET (children->data))
364 children = children->next;
372 gtk_tree_clear_items (GtkTree *tree,
382 g_return_if_fail (tree != NULL);
383 g_return_if_fail (GTK_IS_TREE (tree));
385 nchildren = g_list_length (tree->children);
389 if ((end < 0) || (end > nchildren))
395 tmp_list = g_list_nth (tree->children, start);
398 while (tmp_list && index <= end)
400 widget = tmp_list->data;
401 tmp_list = tmp_list->next;
404 clear_list = g_list_prepend (clear_list, widget);
407 gtk_tree_remove_items (tree, clear_list);
412 gtk_tree_destroy (GtkObject *object)
418 g_return_if_fail (object != NULL);
419 g_return_if_fail (GTK_IS_TREE (object));
421 tree = GTK_TREE (object);
423 children = tree->children;
426 child = children->data;
427 children = children->next;
429 gtk_widget_ref (child);
430 gtk_widget_unparent (child);
431 gtk_widget_destroy (child);
432 gtk_widget_unref (child);
435 g_list_free (tree->children);
436 tree->children = NULL;
438 if (tree->root_tree == tree)
441 for (node = tree->selection; node; node = node->next)
442 gtk_widget_unref ((GtkWidget *)node->data);
443 g_list_free (tree->selection);
444 tree->selection = NULL;
447 if (GTK_OBJECT_CLASS (parent_class)->destroy)
448 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
452 gtk_tree_draw (GtkWidget *widget,
458 GdkRectangle child_area;
462 g_return_if_fail (widget != NULL);
463 g_return_if_fail (GTK_IS_TREE (widget));
464 g_return_if_fail (area != NULL);
466 if (GTK_WIDGET_DRAWABLE (widget))
468 tree = GTK_TREE (widget);
470 children = tree->children;
473 child = children->data;
474 children = children->next;
476 if (gtk_widget_intersect (child, area, &child_area))
477 gtk_widget_draw (child, &child_area);
479 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
480 GTK_WIDGET_VISIBLE(subtree) &&
481 gtk_widget_intersect (subtree, area, &child_area))
482 gtk_widget_draw (subtree, &child_area);
489 gtk_tree_expose (GtkWidget *widget,
490 GdkEventExpose *event)
494 GdkEventExpose child_event;
498 g_return_val_if_fail (widget != NULL, FALSE);
499 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
500 g_return_val_if_fail (event != NULL, FALSE);
502 if (GTK_WIDGET_DRAWABLE (widget))
504 tree = GTK_TREE (widget);
506 child_event = *event;
508 children = tree->children;
511 child = children->data;
512 children = children->next;
514 if (GTK_WIDGET_NO_WINDOW (child) &&
515 gtk_widget_intersect (child, &event->area, &child_event.area))
516 gtk_widget_event (child, (GdkEvent*) &child_event);
525 gtk_tree_forall (GtkContainer *container,
526 gboolean include_internals,
527 GtkCallback callback,
528 gpointer callback_data)
535 g_return_if_fail (container != NULL);
536 g_return_if_fail (GTK_IS_TREE (container));
537 g_return_if_fail (callback != NULL);
539 tree = GTK_TREE (container);
540 children = tree->children;
544 child = children->data;
545 children = children->next;
547 (* callback) (child, callback_data);
552 gtk_tree_map (GtkWidget *widget)
559 g_return_if_fail (widget != NULL);
560 g_return_if_fail (GTK_IS_TREE (widget));
562 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
563 tree = GTK_TREE (widget);
565 gdk_window_show (widget->window);
567 if(GTK_IS_TREE(widget->parent))
569 /* set root tree for this tree */
570 tree->root_tree = GTK_TREE(widget->parent)->root_tree;
572 tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
573 tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
574 tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
576 tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
577 tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
580 tree->root_tree = tree;
582 children = tree->children;
585 child = children->data;
586 children = children->next;
588 if (GTK_WIDGET_VISIBLE (child) &&
589 !GTK_WIDGET_MAPPED (child))
590 gtk_widget_map (child);
592 if (GTK_TREE_ITEM (child)->subtree)
594 child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
596 if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
597 gtk_widget_map (child);
603 gtk_tree_motion_notify (GtkWidget *widget,
604 GdkEventMotion *event)
606 g_return_val_if_fail (widget != NULL, FALSE);
607 g_return_val_if_fail (GTK_IS_TREE (widget), FALSE);
608 g_return_val_if_fail (event != NULL, FALSE);
611 g_message("gtk_tree_motion_notify\n");
612 #endif /* TREE_DEBUG */
618 gtk_tree_realize (GtkWidget *widget)
620 GdkWindowAttr attributes;
621 gint attributes_mask;
624 g_return_if_fail (widget != NULL);
625 g_return_if_fail (GTK_IS_TREE (widget));
627 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
629 attributes.window_type = GDK_WINDOW_CHILD;
630 attributes.x = widget->allocation.x;
631 attributes.y = widget->allocation.y;
632 attributes.width = widget->allocation.width;
633 attributes.height = widget->allocation.height;
634 attributes.wclass = GDK_INPUT_OUTPUT;
635 attributes.visual = gtk_widget_get_visual (widget);
636 attributes.colormap = gtk_widget_get_colormap (widget);
637 attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
639 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
641 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
642 gdk_window_set_user_data (widget->window, widget);
644 widget->style = gtk_style_attach (widget->style, widget->window);
645 gdk_window_set_background (widget->window,
646 &widget->style->base[GTK_STATE_NORMAL]);
650 gtk_tree_remove_item (GtkTree *container,
655 g_return_if_fail (container != NULL);
656 g_return_if_fail (GTK_IS_TREE (container));
657 g_return_if_fail (widget != NULL);
658 g_return_if_fail (container == GTK_TREE (widget->parent));
660 item_list = g_list_append (NULL, widget);
662 gtk_tree_remove_items (GTK_TREE (container), item_list);
664 g_list_free (item_list);
667 /* used by gtk_tree_remove_items to make the function independant of
668 order in list of items to remove.
669 Sort item bu depth in tree */
671 gtk_tree_sort_item_by_depth(GtkWidget* a, GtkWidget* b)
673 if((GTK_TREE(a->parent)->level) < (GTK_TREE(b->parent)->level))
675 if((GTK_TREE(a->parent)->level) > (GTK_TREE(b->parent)->level))
682 gtk_tree_remove_items (GtkTree *tree,
686 GList *selected_widgets;
692 g_return_if_fail (tree != NULL);
693 g_return_if_fail (GTK_IS_TREE (tree));
696 g_message("+ gtk_tree_remove_items [ tree %#x items list %#x ]\n", (int)tree, (int)items);
697 #endif /* TREE_DEBUG */
699 /* We may not yet be mapped, so we actively have to find our
703 root_tree = tree->root_tree;
706 GtkWidget *tmp = GTK_WIDGET (tree);
707 while (tmp->parent && GTK_IS_TREE (tmp->parent))
710 root_tree = GTK_TREE (tmp);
714 selected_widgets = NULL;
719 g_message("* sort list by depth\n");
720 #endif /* TREE_DEBUG */
726 g_message ("* item [%#x] depth [%d]\n",
728 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
729 #endif /* TREE_DEBUG */
731 sorted_list = g_list_insert_sorted(sorted_list,
733 (GCompareFunc)gtk_tree_sort_item_by_depth);
734 tmp_list = g_list_next(tmp_list);
738 /* print sorted list */
739 g_message("* sorted list result\n");
740 tmp_list = sorted_list;
743 g_message("* item [%#x] depth [%d]\n",
745 (int)GTK_TREE(GTK_WIDGET(tmp_list->data)->parent)->level);
746 tmp_list = g_list_next(tmp_list);
748 #endif /* TREE_DEBUG */
751 g_message("* scan sorted list\n");
752 #endif /* TREE_DEBUG */
754 tmp_list = sorted_list;
757 widget = tmp_list->data;
758 tmp_list = tmp_list->next;
761 g_message("* item [%#x] subtree [%#x]\n",
762 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
763 #endif /* TREE_DEBUG */
765 /* get real owner of this widget */
766 real_tree = GTK_TREE(widget->parent);
768 g_message("* subtree having this widget [%#x]\n", (int)real_tree);
769 #endif /* TREE_DEBUG */
772 if (widget->state == GTK_STATE_SELECTED)
774 selected_widgets = g_list_prepend (selected_widgets, widget);
776 g_message("* selected widget - adding it in selected list [%#x]\n",
777 (int)selected_widgets);
778 #endif /* TREE_DEBUG */
781 /* remove this item from its real parent */
783 g_message("* remove widget from its owner tree\n");
784 #endif /* TREE_DEBUG */
785 real_tree->children = g_list_remove (real_tree->children, widget);
787 /* remove subtree associate at this item if it exist */
788 if(GTK_TREE_ITEM(widget)->subtree)
791 g_message("* remove subtree associate at this item [%#x]\n",
792 (int) GTK_TREE_ITEM(widget)->subtree);
793 #endif /* TREE_DEBUG */
794 if (GTK_WIDGET_MAPPED (GTK_TREE_ITEM(widget)->subtree))
795 gtk_widget_unmap (GTK_TREE_ITEM(widget)->subtree);
797 gtk_widget_unparent (GTK_TREE_ITEM(widget)->subtree);
798 GTK_TREE_ITEM(widget)->subtree = NULL;
801 /* really remove widget for this item */
803 g_message("* unmap and unparent widget [%#x]\n", (int)widget);
804 #endif /* TREE_DEBUG */
805 if (GTK_WIDGET_MAPPED (widget))
806 gtk_widget_unmap (widget);
808 gtk_widget_unparent (widget);
810 /* delete subtree if there is no children in it */
811 if(real_tree->children == NULL &&
812 real_tree != root_tree)
815 g_message("* owner tree don't have children ... destroy it\n");
816 #endif /* TREE_DEBUG */
817 gtk_tree_item_remove_subtree(GTK_TREE_ITEM(real_tree->tree_owner));
821 g_message("* next item in list\n");
822 #endif /* TREE_DEBUG */
825 if (selected_widgets)
828 g_message("* scan selected item list\n");
829 #endif /* TREE_DEBUG */
830 tmp_list = selected_widgets;
833 widget = tmp_list->data;
834 tmp_list = tmp_list->next;
837 g_message("* widget [%#x] subtree [%#x]\n",
838 (int)widget, (int)GTK_TREE_ITEM_SUBTREE(widget));
839 #endif /* TREE_DEBUG */
841 /* remove widget of selection */
842 root_tree->selection = g_list_remove (root_tree->selection, widget);
844 /* unref it to authorize is destruction */
845 gtk_widget_unref (widget);
848 /* emit only one selection_changed signal */
849 gtk_signal_emit (GTK_OBJECT (root_tree),
850 tree_signals[SELECTION_CHANGED]);
854 g_message("* free selected_widgets list\n");
855 #endif /* TREE_DEBUG */
856 g_list_free (selected_widgets);
857 g_list_free (sorted_list);
859 if (root_tree->children && !root_tree->selection &&
860 (root_tree->selection_mode == GTK_SELECTION_BROWSE))
863 g_message("* BROWSE mode, select another item\n");
864 #endif /* TREE_DEBUG */
865 widget = root_tree->children->data;
866 gtk_tree_select_child (root_tree, widget);
869 if (GTK_WIDGET_VISIBLE (root_tree))
872 g_message("* query queue resizing for root_tree\n");
873 #endif /* TREE_DEBUG */
874 gtk_widget_queue_resize (GTK_WIDGET (root_tree));
879 gtk_tree_select_child (GtkTree *tree,
880 GtkWidget *tree_item)
882 g_return_if_fail (tree != NULL);
883 g_return_if_fail (GTK_IS_TREE (tree));
884 g_return_if_fail (tree_item != NULL);
885 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
887 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[SELECT_CHILD], tree_item);
891 gtk_tree_select_item (GtkTree *tree,
896 g_return_if_fail (tree != NULL);
897 g_return_if_fail (GTK_IS_TREE (tree));
899 tmp_list = g_list_nth (tree->children, item);
901 gtk_tree_select_child (tree, GTK_WIDGET (tmp_list->data));
906 gtk_tree_size_allocate (GtkWidget *widget,
907 GtkAllocation *allocation)
910 GtkWidget *child, *subtree;
911 GtkAllocation child_allocation;
915 g_return_if_fail (widget != NULL);
916 g_return_if_fail (GTK_IS_TREE (widget));
917 g_return_if_fail (allocation != NULL);
919 tree = GTK_TREE (widget);
921 widget->allocation = *allocation;
922 if (GTK_WIDGET_REALIZED (widget))
923 gdk_window_move_resize (widget->window,
924 allocation->x, allocation->y,
925 allocation->width, allocation->height);
929 child_allocation.x = GTK_CONTAINER (tree)->border_width;
930 child_allocation.y = GTK_CONTAINER (tree)->border_width;
931 child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
933 children = tree->children;
937 child = children->data;
938 children = children->next;
940 if (GTK_WIDGET_VISIBLE (child))
942 child_allocation.height = child->requisition.height;
944 gtk_widget_size_allocate (child, &child_allocation);
946 child_allocation.y += child_allocation.height;
948 if((subtree = GTK_TREE_ITEM(child)->subtree))
949 if(GTK_WIDGET_VISIBLE (subtree))
951 child_allocation.height = subtree->requisition.height;
952 gtk_widget_size_allocate (subtree, &child_allocation);
953 child_allocation.y += child_allocation.height;
962 gtk_tree_size_request (GtkWidget *widget,
963 GtkRequisition *requisition)
966 GtkWidget *child, *subtree;
970 g_return_if_fail (widget != NULL);
971 g_return_if_fail (GTK_IS_TREE (widget));
972 g_return_if_fail (requisition != NULL);
974 tree = GTK_TREE (widget);
975 requisition->width = 0;
976 requisition->height = 0;
978 children = tree->children;
981 child = children->data;
982 children = children->next;
984 if (GTK_WIDGET_VISIBLE (child))
986 gtk_widget_size_request (child, &child->requisition);
988 requisition->width = MAX (requisition->width, child->requisition.width);
989 requisition->height += child->requisition.height;
991 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
992 GTK_WIDGET_VISIBLE (subtree))
994 gtk_widget_size_request (subtree, &subtree->requisition);
996 requisition->width = MAX (requisition->width,
997 subtree->requisition.width);
999 requisition->height += subtree->requisition.height;
1004 requisition->width += GTK_CONTAINER (tree)->border_width * 2;
1005 requisition->height += GTK_CONTAINER (tree)->border_width * 2;
1007 requisition->width = MAX (requisition->width, 1);
1008 requisition->height = MAX (requisition->height, 1);
1013 gtk_tree_unmap (GtkWidget *widget)
1016 g_return_if_fail (widget != NULL);
1017 g_return_if_fail (GTK_IS_TREE (widget));
1019 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1020 gdk_window_hide (widget->window);
1025 gtk_tree_unselect_child (GtkTree *tree,
1026 GtkWidget *tree_item)
1028 g_return_if_fail (tree != NULL);
1029 g_return_if_fail (GTK_IS_TREE (tree));
1030 g_return_if_fail (tree_item != NULL);
1031 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1033 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1037 gtk_tree_unselect_item (GtkTree *tree,
1042 g_return_if_fail (tree != NULL);
1043 g_return_if_fail (GTK_IS_TREE (tree));
1045 tmp_list = g_list_nth (tree->children, item);
1047 gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1052 gtk_real_tree_select_child (GtkTree *tree,
1055 GList *selection, *root_selection;
1057 GtkWidget *tmp_item;
1059 g_return_if_fail (tree != NULL);
1060 g_return_if_fail (GTK_IS_TREE (tree));
1061 g_return_if_fail (child != NULL);
1062 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1064 root_selection = tree->root_tree->selection;
1066 switch (tree->root_tree->selection_mode)
1068 case GTK_SELECTION_SINGLE:
1070 selection = root_selection;
1072 /* remove old selection list */
1075 tmp_item = selection->data;
1077 if (tmp_item != child)
1079 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1081 tmp_list = selection;
1082 selection = selection->next;
1084 root_selection = g_list_remove_link (root_selection, tmp_list);
1085 gtk_widget_unref (tmp_item);
1087 g_list_free (tmp_list);
1090 selection = selection->next;
1093 if (child->state == GTK_STATE_NORMAL)
1095 gtk_tree_item_select (GTK_TREE_ITEM (child));
1096 root_selection = g_list_prepend (root_selection, child);
1097 gtk_widget_ref (child);
1099 else if (child->state == GTK_STATE_SELECTED)
1101 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1102 root_selection = g_list_remove (root_selection, child);
1103 gtk_widget_unref (child);
1106 tree->root_tree->selection = root_selection;
1108 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1109 tree_signals[SELECTION_CHANGED]);
1113 case GTK_SELECTION_BROWSE:
1114 selection = root_selection;
1118 tmp_item = selection->data;
1120 if (tmp_item != child)
1122 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1124 tmp_list = selection;
1125 selection = selection->next;
1127 root_selection = g_list_remove_link (root_selection, tmp_list);
1128 gtk_widget_unref (tmp_item);
1130 g_list_free (tmp_list);
1133 selection = selection->next;
1136 tree->root_tree->selection = root_selection;
1138 if (child->state == GTK_STATE_NORMAL)
1140 gtk_tree_item_select (GTK_TREE_ITEM (child));
1141 root_selection = g_list_prepend (root_selection, child);
1142 gtk_widget_ref (child);
1143 tree->root_tree->selection = root_selection;
1144 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1145 tree_signals[SELECTION_CHANGED]);
1149 case GTK_SELECTION_MULTIPLE:
1150 if (child->state == GTK_STATE_NORMAL)
1152 gtk_tree_item_select (GTK_TREE_ITEM (child));
1153 root_selection = g_list_prepend (root_selection, child);
1154 gtk_widget_ref (child);
1155 tree->root_tree->selection = root_selection;
1156 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1157 tree_signals[SELECTION_CHANGED]);
1159 else if (child->state == GTK_STATE_SELECTED)
1161 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1162 root_selection = g_list_remove (root_selection, child);
1163 gtk_widget_unref (child);
1164 tree->root_tree->selection = root_selection;
1165 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1166 tree_signals[SELECTION_CHANGED]);
1170 case GTK_SELECTION_EXTENDED:
1176 gtk_real_tree_unselect_child (GtkTree *tree,
1179 g_return_if_fail (tree != NULL);
1180 g_return_if_fail (GTK_IS_TREE (tree));
1181 g_return_if_fail (child != NULL);
1182 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1184 switch (tree->selection_mode)
1186 case GTK_SELECTION_SINGLE:
1187 case GTK_SELECTION_MULTIPLE:
1188 case GTK_SELECTION_BROWSE:
1189 if (child->state == GTK_STATE_SELECTED)
1191 GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1192 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1193 root_tree->selection = g_list_remove (root_tree->selection, child);
1194 gtk_widget_unref (child);
1195 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1196 tree_signals[SELECTION_CHANGED]);
1200 case GTK_SELECTION_EXTENDED:
1206 gtk_tree_set_selection_mode (GtkTree *tree,
1207 GtkSelectionMode mode)
1209 g_return_if_fail (tree != NULL);
1210 g_return_if_fail (GTK_IS_TREE (tree));
1212 tree->selection_mode = mode;
1216 gtk_tree_set_view_mode (GtkTree *tree,
1217 GtkTreeViewMode mode)
1219 g_return_if_fail (tree != NULL);
1220 g_return_if_fail (GTK_IS_TREE (tree));
1222 tree->view_mode = mode;
1226 gtk_tree_set_view_lines (GtkTree *tree,
1229 g_return_if_fail (tree != NULL);
1230 g_return_if_fail (GTK_IS_TREE (tree));
1232 tree->view_line = flag;