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 static const 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 if(GTK_IS_TREE(widget->parent))
567 /* set root tree for this tree */
568 tree->root_tree = GTK_TREE(widget->parent)->root_tree;
570 tree->level = GTK_TREE(GTK_WIDGET(tree)->parent)->level+1;
571 tree->indent_value = GTK_TREE(GTK_WIDGET(tree)->parent)->indent_value;
572 tree->current_indent = GTK_TREE(GTK_WIDGET(tree)->parent)->current_indent +
574 tree->view_mode = GTK_TREE(GTK_WIDGET(tree)->parent)->view_mode;
575 tree->view_line = GTK_TREE(GTK_WIDGET(tree)->parent)->view_line;
578 tree->root_tree = tree;
580 children = tree->children;
583 child = children->data;
584 children = children->next;
586 if (GTK_WIDGET_VISIBLE (child) &&
587 !GTK_WIDGET_MAPPED (child))
588 gtk_widget_map (child);
590 if (GTK_TREE_ITEM (child)->subtree)
592 child = GTK_WIDGET (GTK_TREE_ITEM (child)->subtree);
594 if (GTK_WIDGET_VISIBLE (child) && !GTK_WIDGET_MAPPED (child))
595 gtk_widget_map (child);
599 gdk_window_show (widget->window);
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, (gint)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 GtkRequisition child_requisition;
943 gtk_widget_get_child_requisition (child, &child_requisition);
945 child_allocation.height = child_requisition.height;
947 gtk_widget_size_allocate (child, &child_allocation);
949 child_allocation.y += child_allocation.height;
951 if((subtree = GTK_TREE_ITEM(child)->subtree))
952 if(GTK_WIDGET_VISIBLE (subtree))
954 child_allocation.height = subtree->requisition.height;
955 gtk_widget_size_allocate (subtree, &child_allocation);
956 child_allocation.y += child_allocation.height;
965 gtk_tree_size_request (GtkWidget *widget,
966 GtkRequisition *requisition)
969 GtkWidget *child, *subtree;
971 GtkRequisition child_requisition;
974 g_return_if_fail (widget != NULL);
975 g_return_if_fail (GTK_IS_TREE (widget));
976 g_return_if_fail (requisition != NULL);
978 tree = GTK_TREE (widget);
979 requisition->width = 0;
980 requisition->height = 0;
982 children = tree->children;
985 child = children->data;
986 children = children->next;
988 if (GTK_WIDGET_VISIBLE (child))
990 gtk_widget_size_request (child, &child_requisition);
992 requisition->width = MAX (requisition->width, child_requisition.width);
993 requisition->height += child_requisition.height;
995 if((subtree = GTK_TREE_ITEM(child)->subtree) &&
996 GTK_WIDGET_VISIBLE (subtree))
998 gtk_widget_size_request (subtree, &child_requisition);
1000 requisition->width = MAX (requisition->width,
1001 child_requisition.width);
1003 requisition->height += child_requisition.height;
1008 requisition->width += GTK_CONTAINER (tree)->border_width * 2;
1009 requisition->height += GTK_CONTAINER (tree)->border_width * 2;
1011 requisition->width = MAX (requisition->width, 1);
1012 requisition->height = MAX (requisition->height, 1);
1017 gtk_tree_unmap (GtkWidget *widget)
1020 g_return_if_fail (widget != NULL);
1021 g_return_if_fail (GTK_IS_TREE (widget));
1023 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1024 gdk_window_hide (widget->window);
1029 gtk_tree_unselect_child (GtkTree *tree,
1030 GtkWidget *tree_item)
1032 g_return_if_fail (tree != NULL);
1033 g_return_if_fail (GTK_IS_TREE (tree));
1034 g_return_if_fail (tree_item != NULL);
1035 g_return_if_fail (GTK_IS_TREE_ITEM (tree_item));
1037 gtk_signal_emit (GTK_OBJECT (tree), tree_signals[UNSELECT_CHILD], tree_item);
1041 gtk_tree_unselect_item (GtkTree *tree,
1046 g_return_if_fail (tree != NULL);
1047 g_return_if_fail (GTK_IS_TREE (tree));
1049 tmp_list = g_list_nth (tree->children, item);
1051 gtk_tree_unselect_child (tree, GTK_WIDGET (tmp_list->data));
1056 gtk_real_tree_select_child (GtkTree *tree,
1059 GList *selection, *root_selection;
1061 GtkWidget *tmp_item;
1063 g_return_if_fail (tree != NULL);
1064 g_return_if_fail (GTK_IS_TREE (tree));
1065 g_return_if_fail (child != NULL);
1066 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1068 root_selection = tree->root_tree->selection;
1070 switch (tree->root_tree->selection_mode)
1072 case GTK_SELECTION_SINGLE:
1074 selection = root_selection;
1076 /* remove old selection list */
1079 tmp_item = selection->data;
1081 if (tmp_item != child)
1083 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1085 tmp_list = selection;
1086 selection = selection->next;
1088 root_selection = g_list_remove_link (root_selection, tmp_list);
1089 gtk_widget_unref (tmp_item);
1091 g_list_free (tmp_list);
1094 selection = selection->next;
1097 if (child->state == GTK_STATE_NORMAL)
1099 gtk_tree_item_select (GTK_TREE_ITEM (child));
1100 root_selection = g_list_prepend (root_selection, child);
1101 gtk_widget_ref (child);
1103 else if (child->state == GTK_STATE_SELECTED)
1105 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1106 root_selection = g_list_remove (root_selection, child);
1107 gtk_widget_unref (child);
1110 tree->root_tree->selection = root_selection;
1112 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1113 tree_signals[SELECTION_CHANGED]);
1117 case GTK_SELECTION_BROWSE:
1118 selection = root_selection;
1122 tmp_item = selection->data;
1124 if (tmp_item != child)
1126 gtk_tree_item_deselect (GTK_TREE_ITEM (tmp_item));
1128 tmp_list = selection;
1129 selection = selection->next;
1131 root_selection = g_list_remove_link (root_selection, tmp_list);
1132 gtk_widget_unref (tmp_item);
1134 g_list_free (tmp_list);
1137 selection = selection->next;
1140 tree->root_tree->selection = root_selection;
1142 if (child->state == GTK_STATE_NORMAL)
1144 gtk_tree_item_select (GTK_TREE_ITEM (child));
1145 root_selection = g_list_prepend (root_selection, child);
1146 gtk_widget_ref (child);
1147 tree->root_tree->selection = root_selection;
1148 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1149 tree_signals[SELECTION_CHANGED]);
1153 case GTK_SELECTION_MULTIPLE:
1154 if (child->state == GTK_STATE_NORMAL)
1156 gtk_tree_item_select (GTK_TREE_ITEM (child));
1157 root_selection = g_list_prepend (root_selection, child);
1158 gtk_widget_ref (child);
1159 tree->root_tree->selection = root_selection;
1160 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1161 tree_signals[SELECTION_CHANGED]);
1163 else if (child->state == GTK_STATE_SELECTED)
1165 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1166 root_selection = g_list_remove (root_selection, child);
1167 gtk_widget_unref (child);
1168 tree->root_tree->selection = root_selection;
1169 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1170 tree_signals[SELECTION_CHANGED]);
1174 case GTK_SELECTION_EXTENDED:
1180 gtk_real_tree_unselect_child (GtkTree *tree,
1183 g_return_if_fail (tree != NULL);
1184 g_return_if_fail (GTK_IS_TREE (tree));
1185 g_return_if_fail (child != NULL);
1186 g_return_if_fail (GTK_IS_TREE_ITEM (child));
1188 switch (tree->selection_mode)
1190 case GTK_SELECTION_SINGLE:
1191 case GTK_SELECTION_MULTIPLE:
1192 case GTK_SELECTION_BROWSE:
1193 if (child->state == GTK_STATE_SELECTED)
1195 GtkTree* root_tree = GTK_TREE_ROOT_TREE(tree);
1196 gtk_tree_item_deselect (GTK_TREE_ITEM (child));
1197 root_tree->selection = g_list_remove (root_tree->selection, child);
1198 gtk_widget_unref (child);
1199 gtk_signal_emit (GTK_OBJECT (tree->root_tree),
1200 tree_signals[SELECTION_CHANGED]);
1204 case GTK_SELECTION_EXTENDED:
1210 gtk_tree_set_selection_mode (GtkTree *tree,
1211 GtkSelectionMode mode)
1213 g_return_if_fail (tree != NULL);
1214 g_return_if_fail (GTK_IS_TREE (tree));
1216 tree->selection_mode = mode;
1220 gtk_tree_set_view_mode (GtkTree *tree,
1221 GtkTreeViewMode mode)
1223 g_return_if_fail (tree != NULL);
1224 g_return_if_fail (GTK_IS_TREE (tree));
1226 tree->view_mode = mode;
1230 gtk_tree_set_view_lines (GtkTree *tree,
1233 g_return_if_fail (tree != NULL);
1234 g_return_if_fail (GTK_IS_TREE (tree));
1236 tree->view_line = flag;