2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
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 "gtktreeselection.h"
21 #include "gtktreeprivate.h"
22 #include "gtkrbtree.h"
23 #include "gtksignal.h"
25 static void gtk_tree_selection_init (GtkTreeSelection *selection);
26 static void gtk_tree_selection_class_init (GtkTreeSelectionClass *class);
27 static gint gtk_tree_selection_real_select_all (GtkTreeSelection *selection);
28 static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection);
29 static gint gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
40 static GtkObjectClass *parent_class = NULL;
41 static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
44 gtk_tree_selection_get_type (void)
46 static GtkType selection_type = 0;
50 static const GTypeInfo selection_info =
52 sizeof (GtkTreeSelectionClass),
54 NULL, /* base_finalize */
55 (GClassInitFunc) gtk_tree_selection_class_init,
56 NULL, /* class_finalize */
57 NULL, /* class_data */
58 sizeof (GtkTreeSelection),
60 (GInstanceInitFunc) gtk_tree_selection_init
63 selection_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeSelection", &selection_info, 0);
66 return selection_type;
70 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
72 GtkObjectClass *object_class;
74 object_class = (GtkObjectClass*) class;
75 parent_class = g_type_class_peek_parent (class);
77 class->selection_changed = NULL;
79 tree_selection_signals[SELECTION_CHANGED] =
80 gtk_signal_new ("selection_changed",
82 GTK_CLASS_TYPE (object_class),
83 GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, selection_changed),
84 gtk_marshal_VOID__VOID,
89 gtk_tree_selection_init (GtkTreeSelection *selection)
91 selection->type = GTK_TREE_SELECTION_SINGLE;
95 * _gtk_tree_selection_new:
97 * Creates a new #GtkTreeSelection object. This function should not be invoked,
98 * as each #GtkTreeView will create it's own #GtkTreeSelection.
100 * Return value: A newly created #GtkTreeSelection object.
103 _gtk_tree_selection_new (void)
105 GtkTreeSelection *selection;
107 selection = GTK_TREE_SELECTION (gtk_type_new (GTK_TYPE_TREE_SELECTION));
113 * _gtk_tree_selection_new_with_tree_view:
114 * @tree_view: The #GtkTreeView.
116 * Creates a new #GtkTreeSelection object. This function should not be invoked,
117 * as each #GtkTreeView will create it's own #GtkTreeSelection.
119 * Return value: A newly created #GtkTreeSelection object.
122 _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
124 GtkTreeSelection *selection;
126 g_return_val_if_fail (tree_view != NULL, NULL);
127 g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
129 selection = _gtk_tree_selection_new ();
130 _gtk_tree_selection_set_tree_view (selection, tree_view);
136 * _gtk_tree_selection_set_tree_view:
137 * @selection: A #GtkTreeSelection.
138 * @tree_view: The #GtkTreeView.
140 * Sets the #GtkTreeView of @selection. This function should not be invoked, as
141 * it is used internally by #GtkTreeView.
144 _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
145 GtkTreeView *tree_view)
147 g_return_if_fail (selection != NULL);
148 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
149 if (tree_view != NULL)
150 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
152 selection->tree_view = tree_view;
155 /* FIXME explain what the anchor is */
157 * gtk_tree_selection_set_mode:
158 * @selection: A #GtkTreeSelection.
159 * @type: The selection type.
161 * Sets the selection type of the @selection. If the previous type was
162 * #GTK_TREE_SELECTION_MULTI and @type is #GTK_TREE_SELECTION_SINGLE, then
163 * the anchor is kept selected, if it was previously selected.
166 gtk_tree_selection_set_mode (GtkTreeSelection *selection,
167 GtkTreeSelectionMode type)
169 g_return_if_fail (selection != NULL);
170 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
172 if (selection->type == type)
175 if (type == GTK_TREE_SELECTION_SINGLE)
177 GtkRBTree *tree = NULL;
178 GtkRBNode *node = NULL;
179 gint selected = FALSE;
181 if (selection->tree_view->priv->anchor)
183 GtkTreePath *anchor_path;
185 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
189 _gtk_tree_view_find_node (selection->tree_view,
194 if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
197 gtk_tree_path_free (anchor_path);
200 /* FIXME: if user_func is set, then it needs to unconditionally unselect
203 gtk_tree_selection_unselect_all (selection);
205 /* FIXME are we properly emitting the selection_changed signal here? */
206 if (node && selected)
207 GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
209 selection->type = type;
213 * gtk_tree_selection_set_select_function:
214 * @selection: A #GtkTreeSelection.
215 * @func: The selection function.
216 * @data: The selection function's data.
218 * Sets the selection function. If set, this function is called before any node
219 * is selected or unselected, giving some control over which nodes are selected.
222 gtk_tree_selection_set_select_function (GtkTreeSelection *selection,
223 GtkTreeSelectionFunc func,
226 g_return_if_fail (selection != NULL);
227 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
228 g_return_if_fail (func != NULL);
230 selection->user_func = func;
231 selection->user_data = data;
235 * gtk_tree_selection_get_user_data:
236 * @selection: A #GtkTreeSelection.
238 * Returns the user data for the selection function.
240 * Return value: The user data.
243 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
245 g_return_val_if_fail (selection != NULL, NULL);
246 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
248 return selection->user_data;
252 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
254 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
256 return selection->tree_view;
260 * gtk_tree_selection_get_selected:
261 * @selection: A #GtkTreeSelection.
262 * @model: A pointer set to the #GtkTreeModel, or NULL.
263 * @iter: The #GtkTreeIter, or NULL.
265 * Sets @iter to the currently selected node if @selection is set to
266 * #GTK_TREE_SELECTION_SINGLE. Otherwise, it uses the anchor. @iter may be
267 * NULL if you just want to test if @selection has any selected nodes. @model
268 * is filled with the current model as a convenience.
270 * Return value: TRUE, if there is a selected node.
273 gtk_tree_selection_get_selected (GtkTreeSelection *selection,
274 GtkTreeModel **model,
279 GtkTreePath *anchor_path;
282 g_return_val_if_fail (selection != NULL, FALSE);
283 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
286 *model = selection->tree_view->priv->model;
288 if (selection->tree_view->priv->anchor == NULL)
291 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
293 if (anchor_path == NULL)
298 gtk_tree_path_free (anchor_path);
302 g_return_val_if_fail (selection->tree_view != NULL, FALSE);
303 g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
307 if (!_gtk_tree_view_find_node (selection->tree_view,
311 ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
313 /* We don't want to return the anchor if it isn't actually selected.
319 retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
324 gtk_tree_path_free (anchor_path);
330 * gtk_tree_selection_selected_foreach:
331 * @selection: A #GtkTreeSelection.
332 * @func: The function to call for each selected node.
333 * @data: user data to pass to the function.
335 * Calls a function for each selected node.
338 gtk_tree_selection_selected_foreach (GtkTreeSelection *selection,
339 GtkTreeSelectionForeachFunc func,
347 g_return_if_fail (selection != NULL);
348 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
349 g_return_if_fail (selection->tree_view != NULL);
350 g_return_if_fail (selection->tree_view->priv->model != NULL);
353 selection->tree_view->priv->tree == NULL ||
354 selection->tree_view->priv->tree->root == NULL)
357 tree = selection->tree_view->priv->tree;
358 node = selection->tree_view->priv->tree->root;
360 while (node->left != tree->nil)
363 /* find the node internally */
364 path = gtk_tree_path_new_root ();
365 gtk_tree_model_get_iter (selection->tree_view->priv->model,
367 gtk_tree_path_free (path);
371 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
372 (* func) (selection->tree_view->priv->model, &iter, data);
378 tree = node->children;
380 while (node->left != tree->nil)
383 has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
386 TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
390 gboolean done = FALSE;
393 node = _gtk_rbtree_next (tree, node);
398 has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
402 TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
407 GtkTreeIter tmp_iter = iter;
409 node = tree->parent_node;
410 tree = tree->parent_tree;
412 /* we've run out of tree */
413 /* We're done with this function */
415 has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
418 TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
428 * gtk_tree_selection_select_path:
429 * @selection: A #GtkTreeSelection.
430 * @path: The #GtkTreePath to be selected.
432 * Select the row at @path.
435 gtk_tree_selection_select_path (GtkTreeSelection *selection,
440 GdkModifierType state = 0;
442 g_return_if_fail (selection != NULL);
443 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
444 g_return_if_fail (selection->tree_view != NULL);
445 g_return_if_fail (path != NULL);
447 _gtk_tree_view_find_node (selection->tree_view,
452 if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
455 if (selection->type == GTK_TREE_SELECTION_MULTI)
456 state = GDK_CONTROL_MASK;
458 _gtk_tree_selection_internal_select_node (selection,
466 * gtk_tree_selection_unselect_path:
467 * @selection: A #GtkTreeSelection.
468 * @path: The #GtkTreePath to be unselected.
470 * Unselects the row at @path.
473 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
479 g_return_if_fail (selection != NULL);
480 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
481 g_return_if_fail (selection->tree_view != NULL);
482 g_return_if_fail (path != NULL);
484 _gtk_tree_view_find_node (selection->tree_view,
489 if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
492 _gtk_tree_selection_internal_select_node (selection,
500 * gtk_tree_selection_select_iter:
501 * @selection: A #GtkTreeSelection.
502 * @iter: The #GtkTreeIter to be selected.
504 * Selects the specified iterator.
507 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
512 g_return_if_fail (selection != NULL);
513 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
514 g_return_if_fail (selection->tree_view != NULL);
515 g_return_if_fail (selection->tree_view->priv->model != NULL);
516 g_return_if_fail (iter != NULL);
518 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
524 gtk_tree_selection_select_path (selection, path);
525 gtk_tree_path_free (path);
530 * gtk_tree_selection_unselect_iter:
531 * @selection: A #GtkTreeSelection.
532 * @iter: The #GtkTreeIter to be unselected.
534 * Unselects the specified iterator.
537 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
542 g_return_if_fail (selection != NULL);
543 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
544 g_return_if_fail (selection->tree_view != NULL);
545 g_return_if_fail (selection->tree_view->priv->model != NULL);
546 g_return_if_fail (iter != NULL);
548 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
554 gtk_tree_selection_select_path (selection, path);
555 gtk_tree_path_free (path);
558 /* Wish I was in python, right now... */
560 GtkTreeSelection *selection;
565 select_all_helper (GtkRBTree *tree,
569 struct _TempTuple *tuple = data;
572 _gtk_rbtree_traverse (node->children,
573 node->children->root,
577 if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
579 tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
584 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
585 * can use it in other places without fear of the signal being emitted.
588 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
590 struct _TempTuple *tuple;
591 if (selection->tree_view->priv->tree == NULL)
594 if (selection->type == GTK_TREE_SELECTION_SINGLE)
600 /* Just select the last row */
602 dirty = gtk_tree_selection_real_unselect_all (selection);
604 tree = selection->tree_view->priv->tree;
608 while (node->right != selection->tree_view->priv->tree->nil)
613 tree = node->children;
620 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
626 /* Mark all nodes selected */
628 tuple = g_new (struct _TempTuple, 1);
629 tuple->selection = selection;
630 tuple->dirty = FALSE;
632 _gtk_rbtree_traverse (selection->tree_view->priv->tree,
633 selection->tree_view->priv->tree->root,
648 * gtk_tree_selection_select_all:
649 * @selection: A #GtkTreeSelection.
651 * Selects all the nodes. If the type of @selection is
652 * #GTK_TREE_SELECTION_SINGLE, then the last row is selected.
655 gtk_tree_selection_select_all (GtkTreeSelection *selection)
657 g_return_if_fail (selection != NULL);
658 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
659 g_return_if_fail (selection->tree_view != NULL);
660 g_return_if_fail (selection->tree_view->priv->tree != NULL);
662 if (gtk_tree_selection_real_select_all (selection))
663 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
667 unselect_all_helper (GtkRBTree *tree,
671 struct _TempTuple *tuple = data;
674 _gtk_rbtree_traverse (node->children,
675 node->children->root,
679 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
681 tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
686 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
688 struct _TempTuple *tuple;
690 if (selection->type == GTK_TREE_SELECTION_SINGLE)
692 GtkRBTree *tree = NULL;
693 GtkRBNode *node = NULL;
694 GtkTreePath *anchor_path;
696 if (selection->tree_view->priv->anchor == NULL)
699 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
701 if (anchor_path == NULL)
704 _gtk_tree_view_find_node (selection->tree_view,
709 gtk_tree_path_free (anchor_path);
711 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
713 gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
720 tuple = g_new (struct _TempTuple, 1);
721 tuple->selection = selection;
722 tuple->dirty = FALSE;
724 _gtk_rbtree_traverse (selection->tree_view->priv->tree,
725 selection->tree_view->priv->tree->root,
741 * gtk_tree_selection_unselect_all:
742 * @selection: A #GtkTreeSelection.
744 * Unselects all the nodes.
747 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
749 g_return_if_fail (selection != NULL);
750 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
751 g_return_if_fail (selection->tree_view != NULL);
752 g_return_if_fail (selection->tree_view->priv->tree != NULL);
753 if (selection->tree_view->priv->tree == NULL)
756 if (gtk_tree_selection_real_unselect_all (selection))
757 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
761 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
762 GtkTreePath *start_path,
763 GtkTreePath *end_path)
765 GtkRBNode *start_node, *end_node;
766 GtkRBTree *start_tree, *end_tree;
767 gboolean dirty = FALSE;
769 switch (gtk_tree_path_compare (start_path, end_path))
772 _gtk_tree_view_find_node (selection->tree_view,
776 _gtk_tree_view_find_node (selection->tree_view,
782 _gtk_tree_view_find_node (selection->tree_view,
786 end_tree = start_tree;
787 end_node = start_node;
790 _gtk_tree_view_find_node (selection->tree_view,
794 _gtk_tree_view_find_node (selection->tree_view,
801 g_return_val_if_fail (start_node != NULL, FALSE);
802 g_return_val_if_fail (end_node != NULL, FALSE);
806 if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
808 dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
811 if (start_node == end_node)
814 if (start_node->children)
816 start_tree = start_node->children;
817 start_node = start_tree->root;
818 while (start_node->left != start_tree->nil)
819 start_node = start_node->left;
823 gboolean done = FALSE;
826 start_node = _gtk_rbtree_next (start_tree, start_node);
827 if (start_node != NULL)
833 start_node = start_tree->parent_node;
834 start_tree = start_tree->parent_tree;
835 if (start_tree == NULL)
836 /* FIXME should this really be silent, or should it g_warning? */
837 /* we've run out of tree */
838 /* This means we never found end node!! */
851 * gtk_tree_selection_select_range:
852 * @selection: A #GtkTreeSelection.
853 * @start_path: The initial node of the range.
854 * @end_path: The final node of the range.
856 * Selects a range of nodes, determined by @start_path and @end_path inclusive.
859 gtk_tree_selection_select_range (GtkTreeSelection *selection,
860 GtkTreePath *start_path,
861 GtkTreePath *end_path)
863 g_return_if_fail (selection != NULL);
864 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
865 g_return_if_fail (selection->tree_view != NULL);
867 if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
868 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
870 /* Called internally by gtktreeview.c It handles actually selecting the tree.
871 * This should almost certainly ever be called by anywhere else.
874 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
878 GdkModifierType state)
882 GtkTreePath *anchor_path = NULL;
884 if (selection->tree_view->priv->anchor)
885 anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
887 if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
889 if (selection->tree_view->priv->anchor)
890 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
892 selection->tree_view->priv->anchor =
893 gtk_tree_row_reference_new (selection->tree_view->priv->model,
895 dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
897 else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
899 gtk_tree_selection_select_range (selection,
903 else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
906 if (selection->type == GTK_TREE_SELECTION_SINGLE)
907 dirty = gtk_tree_selection_real_unselect_all (selection);
909 if (selection->tree_view->priv->anchor)
910 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
912 selection->tree_view->priv->anchor =
913 gtk_tree_row_reference_new (selection->tree_view->priv->model,
916 if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
917 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
919 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
921 else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
923 dirty = gtk_tree_selection_real_unselect_all (selection);
924 dirty |= gtk_tree_selection_real_select_range (selection,
930 dirty = gtk_tree_selection_real_unselect_all (selection);
932 if (selection->tree_view->priv->anchor)
933 gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
935 selection->tree_view->priv->anchor =
936 gtk_tree_row_reference_new (selection->tree_view->priv->model,
939 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
943 gtk_tree_path_free (anchor_path);
946 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
949 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
952 /* FIXME: user_func can screw up GTK_TREE_SELECTION_SINGLE. If it prevents
953 * unselection of a node, it can keep more then one node selected.
955 /* Perhaps the correct solution is to prevent selecting the new node, if
956 * we fail to unselect the old node.
959 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
964 gboolean selected = FALSE;
965 GtkTreePath *path = NULL;
967 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
969 path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
970 if (selection->user_func)
972 if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
977 gtk_tree_path_free (path);
979 if (selected == TRUE)
981 node->flags ^= GTK_RBNODE_IS_SELECTED;
983 /* FIXME: just draw the one node*/
984 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));