]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
Minor documentation fixes
[~andy/gtk] / gtk / gtktreeselection.c
1 /* gtktreeselection.h
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "gtktreeselection.h"
21 #include "gtktreeprivate.h"
22 #include "gtkrbtree.h"
23 #include "gtkmarshalers.h"
24 #include "gtksignal.h"
25
26 static void gtk_tree_selection_init              (GtkTreeSelection      *selection);
27 static void gtk_tree_selection_class_init        (GtkTreeSelectionClass *class);
28
29 static void gtk_tree_selection_finalize          (GObject               *object);
30 static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
31 static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection      *selection);
32 static gint gtk_tree_selection_real_select_node  (GtkTreeSelection      *selection,
33                                                   GtkRBTree             *tree,
34                                                   GtkRBNode             *node,
35                                                   gboolean               select);
36
37 enum
38 {
39   CHANGED,
40   LAST_SIGNAL
41 };
42
43 static GObjectClass *parent_class = NULL;
44 static guint tree_selection_signals [LAST_SIGNAL] = { 0 };
45
46 GtkType
47 gtk_tree_selection_get_type (void)
48 {
49   static GtkType selection_type = 0;
50
51   if (!selection_type)
52     {
53       static const GTypeInfo selection_info =
54       {
55         sizeof (GtkTreeSelectionClass),
56         NULL,           /* base_init */
57         NULL,           /* base_finalize */
58         (GClassInitFunc) gtk_tree_selection_class_init,
59         NULL,           /* class_finalize */
60         NULL,           /* class_data */
61         sizeof (GtkTreeSelection),
62         0,              /* n_preallocs */
63         (GInstanceInitFunc) gtk_tree_selection_init
64       };
65
66       selection_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeSelection", &selection_info, 0);
67     }
68
69   return selection_type;
70 }
71
72 static void
73 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
74 {
75   GObjectClass *object_class;
76
77   object_class = (GObjectClass*) class;
78   parent_class = g_type_class_peek_parent (class);
79
80   object_class->finalize = gtk_tree_selection_finalize;
81   class->changed = NULL;
82
83   tree_selection_signals[CHANGED] =
84     gtk_signal_new ("changed",
85                     GTK_RUN_FIRST,
86                     GTK_CLASS_TYPE (object_class),
87                     GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, changed),
88                     _gtk_marshal_VOID__VOID,
89                     GTK_TYPE_NONE, 0);
90 }
91
92 static void
93 gtk_tree_selection_init (GtkTreeSelection *selection)
94 {
95   selection->type = GTK_SELECTION_SINGLE;
96 }
97
98 static void
99 gtk_tree_selection_finalize (GObject *object)
100 {
101   GtkTreeSelection *selection = GTK_TREE_SELECTION (object);
102
103   if (selection->destroy)
104     {
105       GtkDestroyNotify d = selection->destroy;
106
107       selection->destroy = NULL;
108       d (selection->user_data);
109     }
110
111   /* chain parent_class' handler */
112   G_OBJECT_CLASS (parent_class)->finalize (object);
113 }
114
115 /**
116  * _gtk_tree_selection_new:
117  *
118  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
119  * as each #GtkTreeView will create it's own #GtkTreeSelection.
120  *
121  * Return value: A newly created #GtkTreeSelection object.
122  **/
123 GtkTreeSelection*
124 _gtk_tree_selection_new (void)
125 {
126   GtkTreeSelection *selection;
127
128   selection = GTK_TREE_SELECTION (g_object_new (GTK_TYPE_TREE_SELECTION, NULL));
129
130   return selection;
131 }
132
133 /**
134  * _gtk_tree_selection_new_with_tree_view:
135  * @tree_view: The #GtkTreeView.
136  *
137  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
138  * as each #GtkTreeView will create it's own #GtkTreeSelection.
139  *
140  * Return value: A newly created #GtkTreeSelection object.
141  **/
142 GtkTreeSelection*
143 _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
144 {
145   GtkTreeSelection *selection;
146
147   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
148
149   selection = _gtk_tree_selection_new ();
150   _gtk_tree_selection_set_tree_view (selection, tree_view);
151
152   return selection;
153 }
154
155 /**
156  * _gtk_tree_selection_set_tree_view:
157  * @selection: A #GtkTreeSelection.
158  * @tree_view: The #GtkTreeView.
159  *
160  * Sets the #GtkTreeView of @selection.  This function should not be invoked, as
161  * it is used internally by #GtkTreeView.
162  **/
163 void
164 _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
165                                    GtkTreeView      *tree_view)
166 {
167   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
168   if (tree_view != NULL)
169     g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
170
171   selection->tree_view = tree_view;
172 }
173
174 /**
175  * gtk_tree_selection_set_mode:
176  * @selection: A #GtkTreeSelection.
177  * @type: The selection mode
178  *
179  * Sets the selection mode of the @selection.  If the previous type was
180  * #GTK_SELECTION_MULTIPLE, then the anchor is kept selected, if it was
181  * previously selected.
182  **/
183 void
184 gtk_tree_selection_set_mode (GtkTreeSelection *selection,
185                              GtkSelectionMode  type)
186 {
187   GtkTreeSelectionFunc tmp_func;
188   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
189
190   if (selection->type == type)
191     return;
192
193   
194   if (type == GTK_SELECTION_NONE)
195     {
196       /* We do this so that we unconditionally unset all rows
197        */
198       tmp_func = selection->user_func;
199       selection->user_func = NULL;
200       gtk_tree_selection_unselect_all (selection);
201       selection->user_func = tmp_func;
202
203       gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
204       selection->tree_view->priv->anchor = NULL;
205     }
206   else if (type == GTK_SELECTION_SINGLE ||
207            type == GTK_SELECTION_BROWSE)
208     {
209       GtkRBTree *tree = NULL;
210       GtkRBNode *node = NULL;
211       gint selected = FALSE;
212       GtkTreePath *anchor_path = NULL;
213
214       if (selection->tree_view->priv->anchor)
215         {
216           anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
217
218           if (anchor_path)
219             {
220               _gtk_tree_view_find_node (selection->tree_view,
221                                         anchor_path,
222                                         &tree,
223                                         &node);
224
225               if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
226                 selected = TRUE;
227             }
228         }
229
230       /* We do this so that we unconditionally unset all rows
231        */
232       tmp_func = selection->user_func;
233       selection->user_func = NULL;
234       gtk_tree_selection_unselect_all (selection);
235       selection->user_func = tmp_func;
236
237       if (node && selected)
238         _gtk_tree_selection_internal_select_node (selection,
239                                                   node,
240                                                   tree,
241                                                   anchor_path,
242                                                   0,
243                                                   FALSE);
244       if (anchor_path)
245         gtk_tree_path_free (anchor_path);
246     }
247
248   selection->type = type;
249 }
250
251 /**
252  * gtk_tree_selection_get_mode:
253  * @selection: a #GtkTreeSelection
254  *
255  * Gets the selection mode for @selection. See
256  * gtk_tree_selection_set_mode().
257  *
258  * Return value: the current selection mode
259  **/
260 GtkSelectionMode
261 gtk_tree_selection_get_mode (GtkTreeSelection *selection)
262 {
263   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_SELECTION_SINGLE);
264
265   return selection->type;
266 }
267
268 /**
269  * gtk_tree_selection_set_select_function:
270  * @selection: A #GtkTreeSelection.
271  * @func: The selection function.
272  * @data: The selection function's data.
273  * @destroy: The destroy function for user data.  May be NULL.
274  *
275  * Sets the selection function.  If set, this function is called before any node
276  * is selected or unselected, giving some control over which nodes are selected.
277  * The select function should return %TRUE if the state of the node may be toggled,
278  * and %FALSE if the state of the node should be left unchanged.
279  **/
280 void
281 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
282                                         GtkTreeSelectionFunc  func,
283                                         gpointer              data,
284                                         GtkDestroyNotify      destroy)
285 {
286   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
287   g_return_if_fail (func != NULL);
288
289   if (selection->destroy)
290     {
291       GtkDestroyNotify d = selection->destroy;
292
293       selection->destroy = NULL;
294       d (selection->user_data);
295     }
296
297   selection->user_func = func;
298   selection->user_data = data;
299   selection->destroy = destroy;
300 }
301
302 /**
303  * gtk_tree_selection_get_user_data:
304  * @selection: A #GtkTreeSelection.
305  *
306  * Returns the user data for the selection function.
307  *
308  * Return value: The user data.
309  **/
310 gpointer
311 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
312 {
313   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
314
315   return selection->user_data;
316 }
317
318 /**
319  * gtk_tree_selection_get_tree_view:
320  * @selection: A #GtkTreeSelection
321  * 
322  * Returns the tree view associated with @selection.
323  * 
324  * Return value: A #GtkTreeView
325  **/
326 GtkTreeView *
327 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
328 {
329   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
330
331   return selection->tree_view;
332 }
333
334 /**
335  * gtk_tree_selection_get_selected:
336  * @selection: A #GtkTreeSelection.
337  * @model: A pointer to set to the #GtkTreeModel, or NULL.
338  * @iter: The #GtkTreeIter, or NULL.
339  *
340  * Sets @iter to the currently selected node if @selection is set to
341  * #GTK_SELECTION_SINGLE or #GTK_SELECTION_BROWSE.  @iter may be NULL if you
342  * just want to test if @selection has any selected nodes.  @model is filled
343  * with the current model as a convenience.  This function will not work if you
344  * use @selection is #GTK_SELECTION_MULTIPLE.
345  *
346  * Return value: TRUE, if there is a selected node.
347  **/
348 gboolean
349 gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
350                                  GtkTreeModel     **model,
351                                  GtkTreeIter       *iter)
352 {
353   GtkRBTree *tree;
354   GtkRBNode *node;
355   GtkTreePath *anchor_path;
356   gboolean retval;
357   gboolean found_node;
358
359   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
360   g_return_val_if_fail (selection->type != GTK_SELECTION_MULTIPLE, FALSE);
361   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
362   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
363
364   if (model)
365     *model = selection->tree_view->priv->model;
366
367   if (selection->tree_view->priv->anchor == NULL)
368     return FALSE;
369
370   anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
371
372   if (anchor_path == NULL)
373     return FALSE;
374
375   retval = FALSE;
376
377   found_node = !_gtk_tree_view_find_node (selection->tree_view,
378                                           anchor_path,
379                                           &tree,
380                                           &node);
381
382   if (found_node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
383     {
384       /* we only want to return the anchor if it exists in the rbtree and
385        * is selected.
386        */
387       if (iter == NULL)
388         retval = TRUE;
389       else
390         retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
391                                           iter,
392                                           anchor_path);
393     }
394   else
395     {
396       /* We don't want to return the anchor if it isn't actually selected.
397        */
398       retval = FALSE;
399     }
400
401   gtk_tree_path_free (anchor_path);
402
403   return retval;
404 }
405
406 /**
407  * gtk_tree_selection_get_selected_rows:
408  * @selection: A #GtkTreeSelection.
409  * @model: A pointer to set to the #GtkTreeModel, or NULL.
410  *
411  * Creates a list of path of all selected rows. Additionally, if you are
412  * planning on modifying the model after calling this function, you may
413  * want to convert the returned list into a list of #GtkTreeRowReferences.
414  * To do this, you can use gtk_tree_row_reference_new_proxy().
415  *
416  * To free the return value, use:
417  * <informalexample><programlisting>
418  * g_list_foreach (list, gtk_tree_path_free, NULL);
419  * g_list_free (list);
420  * </programlisting></informalexample>
421  *
422  * Return value: A #GList containing a #GtkTreePath for each selected row.
423  **/
424 GList *
425 gtk_tree_selection_get_selected_rows (GtkTreeSelection   *selection,
426                                       GtkTreeModel      **model)
427 {
428   GList *list = NULL;
429   GtkRBTree *tree = NULL;
430   GtkRBNode *node = NULL;
431   GtkTreePath *path;
432
433   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
434   g_return_val_if_fail (selection->tree_view != NULL, NULL);
435   g_return_val_if_fail (selection->tree_view->priv->model != NULL, NULL);
436
437   if (selection->tree_view->priv->tree == NULL ||
438       selection->tree_view->priv->tree->root == NULL)
439     return NULL;
440
441   if (model)
442     *model = selection->tree_view->priv->model;
443
444   if (selection->type == GTK_SELECTION_NONE)
445     return NULL;
446   else if (selection->type != GTK_SELECTION_MULTIPLE)
447     {
448       GtkTreeIter iter;
449
450       if (gtk_tree_selection_get_selected (selection, NULL, &iter))
451         {
452           GtkTreePath *path;
453
454           path = gtk_tree_model_get_path (*model, &iter);
455           list = g_list_append (list, path);
456
457           return list;
458         }
459
460       return NULL;
461     }
462
463   tree = selection->tree_view->priv->tree;
464   node = selection->tree_view->priv->tree->root;
465
466   while (node->left != tree->nil)
467     node = node->left;
468   path = gtk_tree_path_new_first ();
469
470   do
471     {
472       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
473         list = g_list_append (list, gtk_tree_path_copy (path));
474
475       if (node->children)
476         {
477           tree = node->children;
478           node = tree->root;
479
480           while (node->left != tree->nil)
481             node = node->left;
482
483           gtk_tree_path_append_index (path, 0);
484         }
485       else
486         {
487           gboolean done = FALSE;
488
489           do
490             {
491               node = _gtk_rbtree_next (tree, node);
492               if (node != NULL)
493                 {
494                   done = TRUE;
495                   gtk_tree_path_next (path);
496                 }
497               else
498                 {
499                   node = tree->parent_node;
500                   tree = tree->parent_tree;
501
502                   if (!tree)
503                     {
504                       gtk_tree_path_free (path);
505                       return list;
506                     }
507
508                   gtk_tree_path_up (path);
509                 }
510             }
511           while (!done);
512         }
513     }
514   while (TRUE);
515
516   gtk_tree_path_free (path);
517
518   return list;
519 }
520
521 static void
522 gtk_tree_selection_count_selected_rows_helper (GtkRBTree *tree,
523                                                GtkRBNode *node,
524                                                gpointer   data)
525 {
526   gint *count = (gint *)data;
527
528   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
529     (*count)++;
530
531   if (node->children)
532     _gtk_rbtree_traverse (node->children, node->children->root,
533                           G_PRE_ORDER,
534                           gtk_tree_selection_count_selected_rows_helper, data);
535 }
536
537 /**
538  * gtk_tree_selection_count_selected_rows:
539  * @selection: A #GtkTreeSelection.
540  *
541  * Returns the number of rows that have been selected in @tree.
542  *
543  * Return value: The number of rows selected.
544  **/
545 gint
546 gtk_tree_selection_count_selected_rows (GtkTreeSelection *selection)
547 {
548   gint count = 0;
549   GtkRBTree *tree;
550   GtkRBNode *node;
551
552   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), 0);
553   g_return_val_if_fail (selection->tree_view != NULL, 0);
554   g_return_val_if_fail (selection->tree_view->priv->model != NULL, 0);
555
556   if (selection->tree_view->priv->tree == NULL ||
557       selection->tree_view->priv->tree->root == NULL)
558     return 0;
559
560   if (selection->type == GTK_SELECTION_SINGLE ||
561       selection->type == GTK_SELECTION_BROWSE)
562     {
563       if (gtk_tree_selection_get_selected (selection, NULL, NULL))
564         return 1;
565       else
566         return 0;
567     }
568
569   tree = selection->tree_view->priv->tree;
570   node = selection->tree_view->priv->tree->root;
571
572   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
573                         selection->tree_view->priv->tree->root,
574                         G_PRE_ORDER,
575                         gtk_tree_selection_count_selected_rows_helper,
576                         &count);
577
578   return count;
579 }
580
581 /**
582  * gtk_tree_selection_selected_foreach:
583  * @selection: A #GtkTreeSelection.
584  * @func: The function to call for each selected node.
585  * @data: user data to pass to the function.
586  *
587  * Calls a function for each selected node. Note that you cannot modify
588  * the tree or selection from within this function. As a result,
589  * gtk_tree_selection_get_selected_rows() might be more useful.
590  **/
591 void
592 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
593                                      GtkTreeSelectionForeachFunc  func,
594                                      gpointer                     data)
595 {
596   GtkTreePath *path;
597   GtkRBTree *tree;
598   GtkRBNode *node;
599   GtkTreeIter iter;
600
601   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
602   g_return_if_fail (selection->tree_view != NULL);
603   g_return_if_fail (selection->tree_view->priv->model != NULL);
604
605   if (func == NULL ||
606       selection->tree_view->priv->tree == NULL ||
607       selection->tree_view->priv->tree->root == NULL)
608     return;
609
610   if (selection->type == GTK_SELECTION_SINGLE ||
611       selection->type == GTK_SELECTION_BROWSE)
612     {
613       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
614         {
615           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
616           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
617           (* func) (selection->tree_view->priv->model, path, &iter, data);
618           gtk_tree_path_free (path);
619         }
620       return;
621     }
622
623   tree = selection->tree_view->priv->tree;
624   node = selection->tree_view->priv->tree->root;
625   
626   while (node->left != tree->nil)
627     node = node->left;
628
629   /* find the node internally */
630   path = gtk_tree_path_new_first ();
631   gtk_tree_model_get_iter (selection->tree_view->priv->model,
632                            &iter, path);
633
634   do
635     {
636       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
637         (* func) (selection->tree_view->priv->model, path, &iter, data);
638       if (node->children)
639         {
640           gboolean has_child;
641           GtkTreeIter tmp;
642
643           tree = node->children;
644           node = tree->root;
645           while (node->left != tree->nil)
646             node = node->left;
647           tmp = iter;
648           has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
649           gtk_tree_path_append_index (path, 0);
650           /* Sanity Check! */
651           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
652         }
653       else
654         {
655           gboolean done = FALSE;
656           do
657             {
658               node = _gtk_rbtree_next (tree, node);
659               if (node != NULL)
660                 {
661                   gboolean has_next;
662
663                   has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
664                   done = TRUE;
665                   gtk_tree_path_next (path);
666
667                   /* Sanity Check! */
668                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
669                 }
670               else
671                 {
672                   gboolean has_parent;
673                   GtkTreeIter tmp_iter = iter;
674
675                   node = tree->parent_node;
676                   tree = tree->parent_tree;
677                   if (tree == NULL)
678                     {
679                       gtk_tree_path_free (path);
680                       /* we've run out of tree */
681                       /* We're done with this function */
682                       return;
683                     }
684                   has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
685                   gtk_tree_path_up (path);
686                   /* Sanity check */
687                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
688                 }
689             }
690           while (!done);
691         }
692     }
693   while (TRUE);
694 }
695
696 /**
697  * gtk_tree_selection_select_path:
698  * @selection: A #GtkTreeSelection.
699  * @path: The #GtkTreePath to be selected.
700  *
701  * Select the row at @path.
702  **/
703 void
704 gtk_tree_selection_select_path (GtkTreeSelection *selection,
705                                 GtkTreePath      *path)
706 {
707   GtkRBNode *node;
708   GtkRBTree *tree;
709   GdkModifierType state = 0;
710   gboolean ret;
711
712   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
713   g_return_if_fail (selection->tree_view != NULL);
714   g_return_if_fail (path != NULL);
715
716   ret = _gtk_tree_view_find_node (selection->tree_view,
717                                   path,
718                                   &tree,
719                                   &node);
720
721   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
722       ret == TRUE)
723     return;
724
725   if (selection->type == GTK_SELECTION_MULTIPLE)
726     state = GDK_CONTROL_MASK;
727
728   _gtk_tree_selection_internal_select_node (selection,
729                                             node,
730                                             tree,
731                                             path,
732                                             state,
733                                             FALSE);
734 }
735
736 /**
737  * gtk_tree_selection_unselect_path:
738  * @selection: A #GtkTreeSelection.
739  * @path: The #GtkTreePath to be unselected.
740  *
741  * Unselects the row at @path.
742  **/
743 void
744 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
745                                   GtkTreePath      *path)
746 {
747   GtkRBNode *node;
748   GtkRBTree *tree;
749   gboolean ret;
750
751   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
752   g_return_if_fail (selection->tree_view != NULL);
753   g_return_if_fail (path != NULL);
754
755   ret = _gtk_tree_view_find_node (selection->tree_view,
756                                   path,
757                                   &tree,
758                                   &node);
759
760   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
761       ret == TRUE)
762     return;
763
764   _gtk_tree_selection_internal_select_node (selection,
765                                             node,
766                                             tree,
767                                             path,
768                                             GDK_CONTROL_MASK,
769                                             TRUE);
770 }
771
772 /**
773  * gtk_tree_selection_select_iter:
774  * @selection: A #GtkTreeSelection.
775  * @iter: The #GtkTreeIter to be selected.
776  *
777  * Selects the specified iterator.
778  **/
779 void
780 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
781                                 GtkTreeIter      *iter)
782 {
783   GtkTreePath *path;
784
785   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
786   g_return_if_fail (selection->tree_view != NULL);
787   g_return_if_fail (selection->tree_view->priv->model != NULL);
788   g_return_if_fail (iter != NULL);
789
790   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
791                                   iter);
792
793   if (path == NULL)
794     return;
795
796   gtk_tree_selection_select_path (selection, path);
797   gtk_tree_path_free (path);
798 }
799
800
801 /**
802  * gtk_tree_selection_unselect_iter:
803  * @selection: A #GtkTreeSelection.
804  * @iter: The #GtkTreeIter to be unselected.
805  *
806  * Unselects the specified iterator.
807  **/
808 void
809 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
810                                   GtkTreeIter      *iter)
811 {
812   GtkTreePath *path;
813
814   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
815   g_return_if_fail (selection->tree_view != NULL);
816   g_return_if_fail (selection->tree_view->priv->model != NULL);
817   g_return_if_fail (iter != NULL);
818
819   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
820                                   iter);
821
822   if (path == NULL)
823     return;
824
825   gtk_tree_selection_unselect_path (selection, path);
826   gtk_tree_path_free (path);
827 }
828
829 /**
830  * gtk_tree_selection_path_is_selected:
831  * @selection: A #GtkTreeSelection.
832  * @path: A #GtkTreePath to check selection on.
833  * 
834  * Returns %TRUE if the row pointed to by @path is currently selected.  If @path
835  * does not point to a valid location, %FALSE is returned
836  * 
837  * Return value: %TRUE if @path is selected.
838  **/
839 gboolean
840 gtk_tree_selection_path_is_selected (GtkTreeSelection *selection,
841                                      GtkTreePath      *path)
842 {
843   GtkRBNode *node;
844   GtkRBTree *tree;
845   gboolean ret;
846
847   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
848   g_return_val_if_fail (path != NULL, FALSE);
849   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
850   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
851
852   ret = _gtk_tree_view_find_node (selection->tree_view,
853                                   path,
854                                   &tree,
855                                   &node);
856
857   if ((node == NULL) || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) ||
858       ret == TRUE)
859     return FALSE;
860
861   return TRUE;
862 }
863
864 /**
865  * gtk_tree_selection_iter_is_selected:
866  * @selection: A #GtkTreeSelection
867  * @iter: A valid #GtkTreeIter
868  * 
869  * Returns %TRUE if the row at @iter is currently selected.
870  * 
871  * Return value: %TRUE, if @iter is selected
872  **/
873 gboolean
874 gtk_tree_selection_iter_is_selected (GtkTreeSelection *selection,
875                                      GtkTreeIter      *iter)
876 {
877   GtkTreePath *path;
878   gboolean retval;
879
880   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
881   g_return_val_if_fail (iter != NULL, FALSE);
882   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
883   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
884
885   path = gtk_tree_model_get_path (selection->tree_view->priv->model, iter);
886   if (path == NULL)
887     return FALSE;
888
889   retval = gtk_tree_selection_path_is_selected (selection, path);
890   gtk_tree_path_free (path);
891
892   return retval;
893 }
894
895
896 /* Wish I was in python, right now... */
897 struct _TempTuple {
898   GtkTreeSelection *selection;
899   gint dirty;
900 };
901
902 static void
903 select_all_helper (GtkRBTree  *tree,
904                    GtkRBNode  *node,
905                    gpointer    data)
906 {
907   struct _TempTuple *tuple = data;
908
909   if (node->children)
910     _gtk_rbtree_traverse (node->children,
911                           node->children->root,
912                           G_PRE_ORDER,
913                           select_all_helper,
914                           data);
915   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
916     {
917       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
918     }
919 }
920
921
922 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
923  * can use it in other places without fear of the signal being emitted.
924  */
925 static gint
926 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
927 {
928   struct _TempTuple *tuple;
929
930   if (selection->tree_view->priv->tree == NULL)
931     return FALSE;
932
933   /* Mark all nodes selected */
934   tuple = g_new (struct _TempTuple, 1);
935   tuple->selection = selection;
936   tuple->dirty = FALSE;
937
938   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
939                         selection->tree_view->priv->tree->root,
940                         G_PRE_ORDER,
941                         select_all_helper,
942                         tuple);
943   if (tuple->dirty)
944     {
945       g_free (tuple);
946       return TRUE;
947     }
948   g_free (tuple);
949   return FALSE;
950 }
951
952 /**
953  * gtk_tree_selection_select_all:
954  * @selection: A #GtkTreeSelection.
955  *
956  * Selects all the nodes.  @selection is must be set to #GTK_SELECTION_MULTIPLE
957  * mode.
958  **/
959 void
960 gtk_tree_selection_select_all (GtkTreeSelection *selection)
961 {
962   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
963   g_return_if_fail (selection->tree_view != NULL);
964   if (selection->tree_view->priv->tree == NULL)
965     return;
966   g_return_if_fail (selection->type == GTK_SELECTION_MULTIPLE);
967
968   if (gtk_tree_selection_real_select_all (selection))
969     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
970 }
971
972 static void
973 unselect_all_helper (GtkRBTree  *tree,
974                      GtkRBNode  *node,
975                      gpointer    data)
976 {
977   struct _TempTuple *tuple = data;
978
979   if (node->children)
980     _gtk_rbtree_traverse (node->children,
981                           node->children->root,
982                           G_PRE_ORDER,
983                           unselect_all_helper,
984                           data);
985   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
986     {
987       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
988     }
989 }
990
991 static gint
992 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
993 {
994   struct _TempTuple *tuple;
995
996   if (selection->type == GTK_SELECTION_SINGLE ||
997       selection->type == GTK_SELECTION_BROWSE)
998     {
999       GtkRBTree *tree = NULL;
1000       GtkRBNode *node = NULL;
1001       GtkTreePath *anchor_path;
1002
1003       if (selection->tree_view->priv->anchor == NULL)
1004         return FALSE;
1005
1006       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1007
1008       if (anchor_path == NULL)
1009         return FALSE;
1010
1011       _gtk_tree_view_find_node (selection->tree_view,
1012                                 anchor_path,
1013                                 &tree,
1014                                 &node);
1015
1016       gtk_tree_path_free (anchor_path);
1017
1018       if (tree == NULL)
1019         return FALSE;
1020
1021       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1022         {
1023           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
1024             {
1025               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1026               selection->tree_view->priv->anchor = NULL;
1027               return TRUE;
1028             }
1029         }
1030       return FALSE;
1031     }
1032   else
1033     {
1034       tuple = g_new (struct _TempTuple, 1);
1035       tuple->selection = selection;
1036       tuple->dirty = FALSE;
1037
1038       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
1039                             selection->tree_view->priv->tree->root,
1040                             G_PRE_ORDER,
1041                             unselect_all_helper,
1042                             tuple);
1043
1044       if (tuple->dirty)
1045         {
1046           g_free (tuple);
1047           return TRUE;
1048         }
1049       g_free (tuple);
1050       return FALSE;
1051     }
1052 }
1053
1054 /**
1055  * gtk_tree_selection_unselect_all:
1056  * @selection: A #GtkTreeSelection.
1057  *
1058  * Unselects all the nodes.
1059  **/
1060 void
1061 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
1062 {
1063   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1064   g_return_if_fail (selection->tree_view != NULL);
1065   if (selection->tree_view->priv->tree == NULL)
1066     return;
1067   
1068   if (selection->tree_view->priv->tree == NULL)
1069     return;
1070
1071   if (gtk_tree_selection_real_unselect_all (selection))
1072     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
1073 }
1074
1075 enum
1076 {
1077   RANGE_SELECT,
1078   RANGE_UNSELECT
1079 };
1080
1081 static gint
1082 gtk_tree_selection_real_modify_range (GtkTreeSelection *selection,
1083                                       gint              mode,
1084                                       GtkTreePath      *start_path,
1085                                       GtkTreePath      *end_path)
1086 {
1087   GtkRBNode *start_node, *end_node;
1088   GtkRBTree *start_tree, *end_tree;
1089   gboolean dirty = FALSE;
1090
1091   switch (gtk_tree_path_compare (start_path, end_path))
1092     {
1093     case 1:
1094       _gtk_tree_view_find_node (selection->tree_view,
1095                                 end_path,
1096                                 &start_tree,
1097                                 &start_node);
1098       _gtk_tree_view_find_node (selection->tree_view,
1099                                 start_path,
1100                                 &end_tree,
1101                                 &end_node);
1102       break;
1103     case 0:
1104       _gtk_tree_view_find_node (selection->tree_view,
1105                                 start_path,
1106                                 &start_tree,
1107                                 &start_node);
1108       end_tree = start_tree;
1109       end_node = start_node;
1110       break;
1111     case -1:
1112       _gtk_tree_view_find_node (selection->tree_view,
1113                                 start_path,
1114                                 &start_tree,
1115                                 &start_node);
1116       _gtk_tree_view_find_node (selection->tree_view,
1117                                 end_path,
1118                                 &end_tree,
1119                                 &end_node);
1120       break;
1121     }
1122
1123   g_return_val_if_fail (start_node != NULL, FALSE);
1124   g_return_val_if_fail (end_node != NULL, FALSE);
1125
1126   do
1127     {
1128       dirty |= gtk_tree_selection_real_select_node (selection, start_tree, start_node, (mode == RANGE_SELECT)?TRUE:FALSE);
1129
1130       if (start_node == end_node)
1131         break;
1132
1133       if (start_node->children)
1134         {
1135           start_tree = start_node->children;
1136           start_node = start_tree->root;
1137           while (start_node->left != start_tree->nil)
1138             start_node = start_node->left;
1139         }
1140       else
1141         {
1142           _gtk_rbtree_next_full (start_tree, start_node, &start_tree, &start_node);
1143           if (start_tree == NULL)
1144             {
1145               /* we just ran out of tree.  That means someone passed in bogus values.
1146                */
1147               return dirty;
1148             }
1149         }
1150     }
1151   while (TRUE);
1152
1153   return dirty;
1154 }
1155
1156 /**
1157  * gtk_tree_selection_select_range:
1158  * @selection: A #GtkTreeSelection.
1159  * @start_path: The initial node of the range.
1160  * @end_path: The final node of the range.
1161  *
1162  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
1163  **/
1164 void
1165 gtk_tree_selection_select_range (GtkTreeSelection *selection,
1166                                  GtkTreePath      *start_path,
1167                                  GtkTreePath      *end_path)
1168 {
1169   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1170   g_return_if_fail (selection->tree_view != NULL);
1171
1172   if (gtk_tree_selection_real_modify_range (selection, RANGE_SELECT, start_path, end_path))
1173     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
1174 }
1175
1176 /**
1177  * gtk_tree_selection_unselect_range:
1178  * @selection: A #GtkTreeSelection.
1179  * @start_path: The initial node of the range.
1180  * @end_path: The initial node of the range.
1181  *
1182  * Unselects a range of nodes, determined by @start_path and @end_path
1183  * inclusive.
1184  **/
1185 void
1186 gtk_tree_selection_unselect_range (GtkTreeSelection *selection,
1187                                    GtkTreePath      *start_path,
1188                                    GtkTreePath      *end_path)
1189 {
1190   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
1191   g_return_if_fail (selection->tree_view != NULL);
1192
1193   if (gtk_tree_selection_real_modify_range (selection, RANGE_UNSELECT, start_path, end_path))
1194     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
1195 }
1196
1197 /* Called internally by gtktreeview.c It handles actually selecting the tree.
1198  */
1199
1200 /*
1201  * docs about the 'override_browse_mode', we set this flag when we want to
1202  * unset select the node and override the select browse mode behaviour (that is
1203  * 'one node should *always* be selected').
1204  */
1205 void
1206 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
1207                                           GtkRBNode        *node,
1208                                           GtkRBTree        *tree,
1209                                           GtkTreePath      *path,
1210                                           GdkModifierType   state,
1211                                           gboolean          override_browse_mode)
1212 {
1213   gint flags;
1214   gint dirty = FALSE;
1215   GtkTreePath *anchor_path = NULL;
1216
1217   if (selection->type == GTK_SELECTION_NONE)
1218     return;
1219
1220   if (selection->tree_view->priv->anchor)
1221     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
1222
1223   if (selection->type == GTK_SELECTION_SINGLE ||
1224       selection->type == GTK_SELECTION_BROWSE)
1225     {
1226       /* just unselect */
1227       if (selection->type == GTK_SELECTION_BROWSE && override_browse_mode)
1228         {
1229           dirty = gtk_tree_selection_real_unselect_all (selection);
1230         }
1231       /* Did we try to select the same node again? */
1232       else if (selection->type == GTK_SELECTION_SINGLE &&
1233                anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
1234         {
1235           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
1236             {
1237               dirty = gtk_tree_selection_real_unselect_all (selection);
1238             }
1239         }
1240       else
1241         {
1242           if (anchor_path)
1243             {
1244               /* We only want to select the new node if we can unselect the old one,
1245                * and we can select the new one. */
1246               if (selection->user_func)
1247                 {
1248                   if ((*selection->user_func) (selection, selection->tree_view->priv->model, path,
1249                                                GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
1250                                                selection->user_data))
1251                     dirty = TRUE;
1252                 }
1253               else
1254                 {
1255                   dirty = TRUE;
1256                 }
1257
1258               /* if dirty is FALSE, we weren't able to select the new one, otherwise, we try to
1259                * unselect the new one
1260                */
1261               if (dirty)
1262                 dirty = gtk_tree_selection_real_unselect_all (selection);
1263
1264               /* if dirty is TRUE at this point, we successfully unselected the
1265                * old one, and can then select the new one */
1266               if (dirty)
1267                 {
1268                   if (selection->tree_view->priv->anchor)
1269                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1270                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1271                     {
1272                       selection->tree_view->priv->anchor =
1273                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1274                     }
1275                 }
1276             }
1277           else
1278             {
1279               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
1280                 {
1281                   dirty = TRUE;
1282                   selection->tree_view->priv->anchor =
1283                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1284                 }
1285             }
1286         }
1287     }
1288   else if (selection->type == GTK_SELECTION_MULTIPLE)
1289     {
1290       if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
1291         {
1292           if (selection->tree_view->priv->anchor)
1293             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1294
1295           selection->tree_view->priv->anchor =
1296             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1297           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1298         }
1299       else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
1300         {
1301           gtk_tree_selection_select_range (selection,
1302                                            anchor_path,
1303                                            path);
1304         }
1305       else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
1306         {
1307           flags = node->flags;
1308           if (selection->tree_view->priv->anchor)
1309             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1310
1311           selection->tree_view->priv->anchor =
1312             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1313
1314           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
1315             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
1316           else
1317             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1318         }
1319       else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
1320         {
1321           dirty = gtk_tree_selection_real_unselect_all (selection);
1322           dirty |= gtk_tree_selection_real_modify_range (selection,
1323                                                          RANGE_SELECT,
1324                                                          anchor_path,
1325                                                          path);
1326         }
1327       else
1328         {
1329           dirty = gtk_tree_selection_real_unselect_all (selection);
1330
1331           if (selection->tree_view->priv->anchor)
1332             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
1333
1334           selection->tree_view->priv->anchor =
1335             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
1336
1337           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
1338         }
1339     }
1340
1341   if (anchor_path)
1342     gtk_tree_path_free (anchor_path);
1343
1344   if (dirty)
1345     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
1346 }
1347
1348 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
1349  */
1350
1351 static gint
1352 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1353                                      GtkRBTree        *tree,
1354                                      GtkRBNode        *node,
1355                                      gboolean          select)
1356 {
1357   gboolean selected = FALSE;
1358   GtkTreePath *path = NULL;
1359
1360   select = !! select;
1361
1362   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1363     {
1364       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1365       if (selection->user_func)
1366         {
1367           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path,
1368                                        GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED),
1369                                        selection->user_data))
1370             selected = TRUE;
1371         }
1372       else
1373         selected = TRUE;
1374       gtk_tree_path_free (path);
1375     }
1376
1377   if (selected == TRUE)
1378     {
1379       node->flags ^= GTK_RBNODE_IS_SELECTED;
1380
1381       _gtk_tree_view_queue_draw_node (selection->tree_view, tree, node, NULL);
1382       
1383       return TRUE;
1384     }
1385
1386   return FALSE;
1387 }
1388