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,
39 static GtkObjectClass *parent_class = NULL;
40 static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
43 gtk_tree_selection_get_type (void)
45 static GtkType selection_type = 0;
49 static const GTypeInfo selection_info =
51 sizeof (GtkTreeSelectionClass),
53 NULL, /* base_finalize */
54 (GClassInitFunc) gtk_tree_selection_class_init,
55 NULL, /* class_finalize */
56 NULL, /* class_data */
57 sizeof (GtkTreeSelection),
59 (GInstanceInitFunc) gtk_tree_selection_init
62 selection_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeSelection", &selection_info, 0);
65 return selection_type;
69 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
71 GtkObjectClass *object_class;
73 object_class = (GtkObjectClass*) class;
74 parent_class = g_type_class_peek_parent (class);
76 tree_selection_signals[SELECTION_CHANGED] =
77 gtk_signal_new ("selection_changed",
79 GTK_CLASS_TYPE (object_class),
80 GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, selection_changed),
81 gtk_marshal_VOID__VOID,
84 gtk_object_class_add_signals (object_class, tree_selection_signals, LAST_SIGNAL);
86 class->selection_changed = NULL;
90 gtk_tree_selection_init (GtkTreeSelection *selection)
92 selection->type = GTK_TREE_SELECTION_SINGLE;
96 * gtk_tree_selection_new:
99 * Creates a new #GtkTreeSelection object. This function should not be invoked,
100 * as each #GtkTreeView will create it's own #GtkTreeSelection.
102 * Return value: A newly created #GtkTreeSelection object.
105 gtk_tree_selection_new (void)
107 GtkObject *selection;
109 selection = GTK_OBJECT (gtk_type_new (GTK_TYPE_TREE_SELECTION));
115 * gtk_tree_selection_new_with_tree_view:
116 * @tree_view: The #GtkTreeView.
118 * Creates a new #GtkTreeSelection object. This function should not be invoked,
119 * as each #GtkTreeView will create it's own #GtkTreeSelection.
121 * Return value: A newly created #GtkTreeSelection object.
124 gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
126 GtkObject *selection;
128 g_return_val_if_fail (tree_view != NULL, NULL);
129 g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
131 selection = gtk_tree_selection_new ();
132 gtk_tree_selection_set_tree_view (GTK_TREE_SELECTION (selection), tree_view);
138 * gtk_tree_selection_set_tree_view:
139 * @selection: A #GtkTreeSelection.
140 * @tree_view: The #GtkTreeView.
142 * Sets the #GtkTreeView of @selection. This function should not be invoked, as
143 * it is used internally by #GtkTreeView.
146 gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
147 GtkTreeView *tree_view)
149 g_return_if_fail (selection != NULL);
150 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
151 if (tree_view != NULL)
152 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
154 selection->tree_view = tree_view;
155 tree_view->priv->selection = selection;
159 * gtk_tree_selection_set_type:
160 * @selection: A #GtkTreeSelection.
161 * @type: The selection type.
163 * Sets the selection type of the @selection. If the previous type was
164 * #GTK_TREE_SELECTION_MULTI and @type is #GTK_TREE_SELECTION_SINGLE, then
165 * the anchor is kept selected, if it was previously selected.
168 gtk_tree_selection_set_type (GtkTreeSelection *selection,
169 GtkTreeSelectionType type)
171 g_return_if_fail (selection != NULL);
172 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
174 if (selection->type == type)
177 if (type == GTK_TREE_SELECTION_SINGLE)
179 GtkRBTree *tree = NULL;
180 GtkRBNode *node = NULL;
181 gint selected = FALSE;
183 if (selection->tree_view->priv->anchor)
185 _gtk_tree_view_find_node (selection->tree_view,
186 selection->tree_view->priv->anchor,
190 if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
193 /* FIXME: if user_func is set, then it needs to unconditionally unselect
196 gtk_tree_selection_unselect_all (selection);
197 if (node && selected)
198 GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
200 selection->type = type;
204 * gtk_tree_selection_set_select_function:
205 * @selection: A #GtkTreeSelection.
206 * @func: The selection function.
207 * @data: The selection function's data.
209 * Sets the selection function. If set, this function is called before any node
210 * is selected or unselected, giving some control over which nodes are selected.
213 gtk_tree_selection_set_select_function (GtkTreeSelection *selection,
214 GtkTreeSelectionFunc func,
217 g_return_if_fail (selection != NULL);
218 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
219 g_return_if_fail (func != NULL);
221 selection->user_func = func;
222 selection->user_data = data;
226 * gtk_tree_selection_get_user_data:
227 * @selection: A #GtkTreeSelection.
229 * Returns the user data for the selection function.
231 * Return value: The user data.
234 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
236 g_return_val_if_fail (selection != NULL, NULL);
237 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
239 return selection->user_data;
243 * gtk_tree_selection_get_selected:
244 * @selection: A #GtkTreeSelection.
246 * Returns the currently selected node if @selection is set to
247 * #GTK_TREE_SELECTION_SINGLE. Otherwise, it returns the anchor.
249 * Return value: The selected #GtkTreeNode.
252 gtk_tree_selection_get_selected (GtkTreeSelection *selection)
258 g_return_val_if_fail (selection != NULL, NULL);
259 g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
261 if (selection->tree_view->priv->anchor == NULL)
264 g_return_val_if_fail (selection->tree_view != NULL, NULL);
265 g_return_val_if_fail (selection->tree_view->priv->model != NULL, NULL);
267 if (!_gtk_tree_view_find_node (selection->tree_view,
268 selection->tree_view->priv->anchor,
271 ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
272 /* We don't want to return the anchor if it isn't actually selected.
277 retval = gtk_tree_model_get_node (selection->tree_view->priv->model,
278 selection->tree_view->priv->anchor);
283 * gtk_tree_selection_selected_foreach:
284 * @selection: A #GtkTreeSelection.
285 * @func: The function to call for each selected node.
286 * @data: user data to pass to the function.
288 * Calls a function for each selected node.
291 gtk_tree_selection_selected_foreach (GtkTreeSelection *selection,
292 GtkTreeSelectionForeachFunc func,
298 GtkTreeNode tree_node;
300 g_return_if_fail (selection != NULL);
301 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
302 g_return_if_fail (selection->tree_view != NULL);
303 g_return_if_fail (selection->tree_view->priv->model != NULL);
306 selection->tree_view->priv->tree == NULL ||
307 selection->tree_view->priv->tree->root == NULL)
310 tree = selection->tree_view->priv->tree;
311 node = selection->tree_view->priv->tree->root;
313 while (node->left != tree->nil)
316 /* find the node internally */
317 path = gtk_tree_path_new_root ();
318 tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
319 gtk_tree_path_free (path);
323 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
324 (* func) (selection->tree_view->priv->model, tree_node, data);
327 tree = node->children;
329 while (node->left != tree->nil)
331 tree_node = gtk_tree_model_node_children (selection->tree_view->priv->model, tree_node);
334 TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
338 gboolean done = FALSE;
341 node = _gtk_rbtree_next (tree, node);
344 gtk_tree_model_node_next (selection->tree_view->priv->model, &tree_node);
348 TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
352 node = tree->parent_node;
353 tree = tree->parent_tree;
355 /* we've run out of tree */
356 /* We're done with this function */
358 tree_node = gtk_tree_model_node_parent (selection->tree_view->priv->model, tree_node);
361 TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
371 * gtk_tree_selection_select_path:
372 * @selection: A #GtkTreeSelection.
373 * @path: The #GtkTreePath to be selected.
375 * Select the row at @path.
378 gtk_tree_selection_select_path (GtkTreeSelection *selection,
383 GdkModifierType state = 0;
385 g_return_if_fail (selection != NULL);
386 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
387 g_return_if_fail (selection->tree_view != NULL);
388 g_return_if_fail (path != NULL);
390 _gtk_tree_view_find_node (selection->tree_view,
395 if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
398 if (selection->type == GTK_TREE_SELECTION_MULTI)
399 state = GDK_CONTROL_MASK;
401 _gtk_tree_selection_internal_select_node (selection,
409 * gtk_tree_selection_unselect_path:
410 * @selection: A #GtkTreeSelection.
411 * @path: The #GtkTreePath to be unselected.
413 * Unselects the row at @path.
416 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
422 g_return_if_fail (selection != NULL);
423 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
424 g_return_if_fail (selection->tree_view != NULL);
425 g_return_if_fail (path != NULL);
427 _gtk_tree_view_find_node (selection->tree_view,
432 if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
435 _gtk_tree_selection_internal_select_node (selection,
443 * gtk_tree_selection_select_node:
444 * @selection: A #GtkTreeSelection.
445 * @tree_node: The #GtkTreeNode to be selected.
447 * Selects the specified node.
450 gtk_tree_selection_select_node (GtkTreeSelection *selection,
451 GtkTreeNode tree_node)
455 g_return_if_fail (selection != NULL);
456 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
457 g_return_if_fail (selection->tree_view != NULL);
458 g_return_if_fail (selection->tree_view->priv->model != NULL);
460 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
466 gtk_tree_selection_select_path (selection, path);
467 gtk_tree_path_free (path);
472 * gtk_tree_selection_unselect_node:
473 * @selection: A #GtkTreeSelection.
474 * @tree_node: The #GtkTreeNode to be unselected.
476 * Unselects the specified node.
479 gtk_tree_selection_unselect_node (GtkTreeSelection *selection,
480 GtkTreeNode tree_node)
484 g_return_if_fail (selection != NULL);
485 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
486 g_return_if_fail (selection->tree_view != NULL);
488 path = gtk_tree_model_get_path (selection->tree_view->priv->model,
494 gtk_tree_selection_select_path (selection, path);
495 gtk_tree_path_free (path);
498 /* Wish I was in python, right now... */
500 GtkTreeSelection *selection;
505 select_all_helper (GtkRBTree *tree,
509 struct _TempTuple *tuple = data;
512 _gtk_rbtree_traverse (node->children,
513 node->children->root,
517 if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
519 tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
524 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
525 * can use it in other places without fear of the signal being emitted.
528 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
530 struct _TempTuple *tuple;
531 if (selection->tree_view->priv->tree == NULL)
534 if (selection->type == GTK_TREE_SELECTION_SINGLE)
540 dirty = gtk_tree_selection_real_unselect_all (selection);
542 tree = selection->tree_view->priv->tree;
546 while (node->right != selection->tree_view->priv->tree->nil)
551 tree = node->children;
558 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
563 tuple = g_new (struct _TempTuple, 1);
564 tuple->selection = selection;
565 tuple->dirty = FALSE;
567 _gtk_rbtree_traverse (selection->tree_view->priv->tree,
568 selection->tree_view->priv->tree->root,
582 * gtk_tree_selection_select_all:
583 * @selection: A #GtkTreeSelection.
585 * Selects all the nodes. If the type of @selection is
586 * #GTK_TREE_SELECTION_SINGLE, then the last row is selected.
589 gtk_tree_selection_select_all (GtkTreeSelection *selection)
591 g_return_if_fail (selection != NULL);
592 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
593 g_return_if_fail (selection->tree_view != NULL);
594 g_return_if_fail (selection->tree_view->priv->tree != NULL);
596 if (gtk_tree_selection_real_select_all (selection))
597 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
601 unselect_all_helper (GtkRBTree *tree,
605 struct _TempTuple *tuple = data;
608 _gtk_rbtree_traverse (node->children,
609 node->children->root,
613 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
615 tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
620 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
622 struct _TempTuple *tuple;
624 if (selection->type == GTK_TREE_SELECTION_SINGLE)
626 GtkRBTree *tree = NULL;
627 GtkRBNode *node = NULL;
628 if (selection->tree_view->priv->anchor == NULL)
631 _gtk_tree_view_find_node (selection->tree_view,
632 selection->tree_view->priv->anchor,
635 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
637 gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
643 tuple = g_new (struct _TempTuple, 1);
644 tuple->selection = selection;
645 tuple->dirty = FALSE;
647 _gtk_rbtree_traverse (selection->tree_view->priv->tree,
648 selection->tree_view->priv->tree->root,
663 * gtk_tree_selection_unselect_all:
664 * @selection: A #GtkTreeSelection.
666 * Unselects all the nodes.
669 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
671 g_return_if_fail (selection != NULL);
672 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
673 g_return_if_fail (selection->tree_view != NULL);
674 g_return_if_fail (selection->tree_view->priv->tree != NULL);
675 if (selection->tree_view->priv->tree == NULL)
678 if (gtk_tree_selection_real_unselect_all (selection))
679 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
683 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
684 GtkTreePath *start_path,
685 GtkTreePath *end_path)
687 GtkRBNode *start_node, *end_node;
688 GtkRBTree *start_tree, *end_tree;
689 gboolean dirty = FALSE;
691 switch (gtk_tree_path_compare (start_path, end_path))
694 _gtk_tree_view_find_node (selection->tree_view,
698 _gtk_tree_view_find_node (selection->tree_view,
704 _gtk_tree_view_find_node (selection->tree_view,
708 end_tree = start_tree;
709 end_node = start_node;
712 _gtk_tree_view_find_node (selection->tree_view,
716 _gtk_tree_view_find_node (selection->tree_view,
723 g_return_val_if_fail (start_node != NULL, FALSE);
724 g_return_val_if_fail (end_node != NULL, FALSE);
728 if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
730 dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
733 if (start_node == end_node)
736 if (start_node->children)
738 start_tree = start_node->children;
739 start_node = start_tree->root;
740 while (start_node->left != start_tree->nil)
741 start_node = start_node->left;
745 gboolean done = FALSE;
748 start_node = _gtk_rbtree_next (start_tree, start_node);
749 if (start_node != NULL)
755 start_node = start_tree->parent_node;
756 start_tree = start_tree->parent_tree;
757 if (start_tree == NULL)
758 /* we've run out of tree */
759 /* This means we never found end node!! */
772 * gtk_tree_selection_select_range:
773 * @selection: A #GtkTreeSelection.
774 * @start_path: The initial node of the range.
775 * @end_path: The final node of the range.
777 * Selects a range of nodes, determined by @start_path and @end_path inclusive.
780 gtk_tree_selection_select_range (GtkTreeSelection *selection,
781 GtkTreePath *start_path,
782 GtkTreePath *end_path)
784 g_return_if_fail (selection != NULL);
785 g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
786 g_return_if_fail (selection->tree_view != NULL);
788 if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
789 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
791 /* Called internally by gtktreeview.c It handles actually selecting the tree.
792 * This should almost certainly ever be called by anywhere else.
795 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
799 GdkModifierType state)
804 if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (selection->tree_view->priv->anchor == NULL))
806 selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
807 dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
809 else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
811 gtk_tree_selection_select_range (selection,
812 selection->tree_view->priv->anchor,
815 else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
818 if (selection->type == GTK_TREE_SELECTION_SINGLE)
819 dirty = gtk_tree_selection_real_unselect_all (selection);
821 if (selection->tree_view->priv->anchor)
822 gtk_tree_path_free (selection->tree_view->priv->anchor);
823 selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
825 if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
826 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
828 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
830 else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
832 dirty = gtk_tree_selection_real_unselect_all (selection);
833 dirty |= gtk_tree_selection_real_select_range (selection,
834 selection->tree_view->priv->anchor,
839 dirty = gtk_tree_selection_real_unselect_all (selection);
840 if (selection->tree_view->priv->anchor)
841 gtk_tree_path_free (selection->tree_view->priv->anchor);
842 selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
843 dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
847 gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
850 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
853 /* FIXME: user_func can screw up GTK_TREE_SELECTION_SINGLE. If it prevents
854 * unselection of a node, it can keep more then one node selected.
857 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
862 gboolean selected = FALSE;
863 GtkTreePath *path = NULL;
865 if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
867 path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
868 if (selection->user_func)
870 if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
876 if (selected == TRUE)
878 GtkTreeNode tree_node;
879 tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
881 node->flags ^= GTK_RBNODE_IS_SELECTED;
883 /* FIXME: just draw the one node*/
884 gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));