]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
add path argument to selection callbacks.
[~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 "gtksignal.h"
24
25 static void gtk_tree_selection_init              (GtkTreeSelection      *selection);
26 static void gtk_tree_selection_class_init        (GtkTreeSelectionClass *class);
27
28 static void gtk_tree_selection_finalize          (GObject               *object);
29 static gint gtk_tree_selection_real_select_all   (GtkTreeSelection      *selection);
30 static gint gtk_tree_selection_real_unselect_all (GtkTreeSelection      *selection);
31 static gint gtk_tree_selection_real_select_node  (GtkTreeSelection      *selection,
32                                                   GtkRBTree             *tree,
33                                                   GtkRBNode             *node,
34                                                   gboolean               select);
35
36 enum
37 {
38   CHANGED,
39   LAST_SIGNAL
40 };
41
42 static GObjectClass *parent_class = NULL;
43 static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
44
45 GtkType
46 gtk_tree_selection_get_type (void)
47 {
48   static GtkType selection_type = 0;
49
50   if (!selection_type)
51     {
52       static const GTypeInfo selection_info =
53       {
54         sizeof (GtkTreeSelectionClass),
55         NULL,           /* base_init */
56         NULL,           /* base_finalize */
57         (GClassInitFunc) gtk_tree_selection_class_init,
58         NULL,           /* class_finalize */
59         NULL,           /* class_data */
60         sizeof (GtkTreeSelection),
61         0,              /* n_preallocs */
62         (GInstanceInitFunc) gtk_tree_selection_init
63       };
64
65       selection_type = g_type_register_static (G_TYPE_OBJECT, "GtkTreeSelection", &selection_info, 0);
66     }
67
68   return selection_type;
69 }
70
71 static void
72 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
73 {
74   GObjectClass *object_class;
75
76   object_class = (GObjectClass*) class;
77   parent_class = g_type_class_peek_parent (class);
78
79   object_class->finalize = gtk_tree_selection_finalize;
80   class->changed = NULL;
81
82   tree_selection_signals[CHANGED] =
83     gtk_signal_new ("changed",
84                     GTK_RUN_FIRST,
85                     GTK_CLASS_TYPE (object_class),
86                     GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, changed),
87                     gtk_marshal_VOID__VOID,
88                     GTK_TYPE_NONE, 0);
89 }
90
91 static void
92 gtk_tree_selection_init (GtkTreeSelection *selection)
93 {
94   selection->type = GTK_TREE_SELECTION_SINGLE;
95 }
96
97 static void
98 gtk_tree_selection_finalize (GObject *object)
99 {
100   if (GTK_TREE_SELECTION (object)->destroy)
101     (* GTK_TREE_SELECTION (object)->destroy) (GTK_TREE_SELECTION (object)->user_data);
102 }
103
104 /**
105  * _gtk_tree_selection_new:
106  *
107  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
108  * as each #GtkTreeView will create it's own #GtkTreeSelection.
109  *
110  * Return value: A newly created #GtkTreeSelection object.
111  **/
112 GtkTreeSelection*
113 _gtk_tree_selection_new (void)
114 {
115   GtkTreeSelection *selection;
116
117   selection = GTK_TREE_SELECTION (g_object_new (GTK_TYPE_TREE_SELECTION, NULL));
118
119   return selection;
120 }
121
122 /**
123  * _gtk_tree_selection_new_with_tree_view:
124  * @tree_view: The #GtkTreeView.
125  *
126  * Creates a new #GtkTreeSelection object.  This function should not be invoked,
127  * as each #GtkTreeView will create it's own #GtkTreeSelection.
128  *
129  * Return value: A newly created #GtkTreeSelection object.
130  **/
131 GtkTreeSelection*
132 _gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
133 {
134   GtkTreeSelection *selection;
135
136   g_return_val_if_fail (tree_view != NULL, NULL);
137   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
138
139   selection = _gtk_tree_selection_new ();
140   _gtk_tree_selection_set_tree_view (selection, tree_view);
141
142   return selection;
143 }
144
145 /**
146  * _gtk_tree_selection_set_tree_view:
147  * @selection: A #GtkTreeSelection.
148  * @tree_view: The #GtkTreeView.
149  *
150  * Sets the #GtkTreeView of @selection.  This function should not be invoked, as
151  * it is used internally by #GtkTreeView.
152  **/
153 void
154 _gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
155                                    GtkTreeView      *tree_view)
156 {
157   g_return_if_fail (selection != NULL);
158   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
159   if (tree_view != NULL)
160     g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
161
162   selection->tree_view = tree_view;
163 }
164
165 /**
166  * gtk_tree_selection_set_mode:
167  * @selection: A #GtkTreeSelection.
168  * @type: The selection mode
169  *
170  * Sets the selection mode of the @selection.  If the previous type was
171  * #GTK_TREE_SELECTION_MULTI and @type is #GTK_TREE_SELECTION_SINGLE, then
172  * the anchor is kept selected, if it was previously selected.
173  **/
174 void
175 gtk_tree_selection_set_mode (GtkTreeSelection     *selection,
176                              GtkTreeSelectionMode  type)
177 {
178   g_return_if_fail (selection != NULL);
179   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
180
181   if (selection->type == type)
182     return;
183
184   if (type == GTK_TREE_SELECTION_SINGLE)
185     {
186       GtkRBTree *tree = NULL;
187       GtkRBNode *node = NULL;
188       gint selected = FALSE;
189
190       if (selection->tree_view->priv->anchor)
191         {
192           GtkTreePath *anchor_path;
193
194           anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
195
196           if (anchor_path)
197             {
198               _gtk_tree_view_find_node (selection->tree_view,
199                                         anchor_path,
200                                         &tree,
201                                         &node);
202
203               if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
204                 selected = TRUE;
205
206               gtk_tree_path_free (anchor_path);
207             }
208         }
209       /* FIXME: if user_func is set, then it needs to unconditionally unselect
210        * all.
211        */
212       gtk_tree_selection_unselect_all (selection);
213
214       /* FIXME are we properly emitting the selection_changed signal here? */
215       if (node && selected)
216         GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
217     }
218   selection->type = type;
219 }
220
221 /**
222  * gtk_tree_selection_get_mode:
223  * @selection: a #GtkTreeSelection
224  *
225  * Gets the selection mode for @selection. See
226  * gtk_tree_selection_set_mode().
227  *
228  * Return value: the current selection mode
229  **/
230 GtkTreeSelectionMode
231 gtk_tree_selection_get_mode (GtkTreeSelection *selection)
232 {
233   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), GTK_TREE_SELECTION_SINGLE);
234
235   return selection->type;
236 }
237
238 /**
239  * gtk_tree_selection_set_select_function:
240  * @selection: A #GtkTreeSelection.
241  * @func: The selection function.
242  * @data: The selection function's data.
243  * @destroy: The destroy function for user data.  May be NULL.
244  *
245  * Sets the selection function.  If set, this function is called before any node
246  * is selected or unselected, giving some control over which nodes are selected.
247  **/
248 void
249 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
250                                         GtkTreeSelectionFunc  func,
251                                         gpointer              data,
252                                         GtkDestroyNotify      destroy)
253 {
254   g_return_if_fail (selection != NULL);
255   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
256   g_return_if_fail (func != NULL);
257
258   selection->user_func = func;
259   selection->user_data = data;
260   selection->destroy = destroy;
261 }
262
263 /**
264  * gtk_tree_selection_get_user_data:
265  * @selection: A #GtkTreeSelection.
266  *
267  * Returns the user data for the selection function.
268  *
269  * Return value: The user data.
270  **/
271 gpointer
272 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
273 {
274   g_return_val_if_fail (selection != NULL, NULL);
275   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
276
277   return selection->user_data;
278 }
279
280 GtkTreeView*
281 gtk_tree_selection_get_tree_view (GtkTreeSelection *selection)
282 {
283   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
284
285   return selection->tree_view;
286 }
287
288 /**
289  * gtk_tree_selection_get_selected:
290  * @selection: A #GtkTreeSelection.
291  * @model: A pointer set to the #GtkTreeModel, or NULL.
292  * @iter: The #GtkTreeIter, or NULL.
293  *
294  * Sets @iter to the currently selected node if @selection is set to
295  * #GTK_TREE_SELECTION_SINGLE.  @iter may be NULL if you just want to test if
296  * @selection has any selected nodes.  @model is filled with the current model
297  * as a convenience.  This function will not work if you use @selection is
298  * #GTK_TREE_SELECTION_MULTI.
299  *
300  * Return value: TRUE, if there is a selected node.
301  **/
302 gboolean
303 gtk_tree_selection_get_selected (GtkTreeSelection  *selection,
304                                  GtkTreeModel     **model,
305                                  GtkTreeIter       *iter)
306 {
307   GtkRBTree *tree;
308   GtkRBNode *node;
309   GtkTreePath *anchor_path;
310   gboolean retval;
311
312   g_return_val_if_fail (selection != NULL, FALSE);
313   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), FALSE);
314   g_return_val_if_fail (selection->type == GTK_TREE_SELECTION_SINGLE, FALSE);
315   g_return_val_if_fail (selection->tree_view != NULL, FALSE);
316   g_return_val_if_fail (selection->tree_view->priv->model != NULL, FALSE);
317
318   if (model)
319     *model = selection->tree_view->priv->model;
320
321   if (selection->tree_view->priv->anchor == NULL)
322     return FALSE;
323
324   anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
325
326   if (anchor_path == NULL)
327     return FALSE;
328
329   if (iter == NULL)
330     {
331       gtk_tree_path_free (anchor_path);
332       return TRUE;
333     }
334
335   retval = FALSE;
336
337   if (!_gtk_tree_view_find_node (selection->tree_view,
338                                  anchor_path,
339                                  &tree,
340                                  &node) &&
341       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
342     {
343       /* We don't want to return the anchor if it isn't actually selected.
344        */
345       retval = FALSE;
346     }
347   else
348     {
349       retval = gtk_tree_model_get_iter (selection->tree_view->priv->model,
350                                         iter,
351                                         anchor_path);
352     }
353
354   gtk_tree_path_free (anchor_path);
355
356   return retval;
357 }
358
359 /**
360  * gtk_tree_selection_selected_foreach:
361  * @selection: A #GtkTreeSelection.
362  * @func: The function to call for each selected node.
363  * @data: user data to pass to the function.
364  *
365  * Calls a function for each selected node.
366  **/
367 void
368 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
369                                      GtkTreeSelectionForeachFunc  func,
370                                      gpointer                     data)
371 {
372   GtkTreePath *path;
373   GtkRBTree *tree;
374   GtkRBNode *node;
375   GtkTreeIter iter;
376
377   g_return_if_fail (selection != NULL);
378   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
379   g_return_if_fail (selection->tree_view != NULL);
380   g_return_if_fail (selection->tree_view->priv->model != NULL);
381
382   if (func == NULL ||
383       selection->tree_view->priv->tree == NULL ||
384       selection->tree_view->priv->tree->root == NULL)
385     return;
386
387   if (selection->type == GTK_TREE_SELECTION_SINGLE)
388     {
389       if (gtk_tree_row_reference_valid (selection->tree_view->priv->anchor))
390         {
391           path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
392           gtk_tree_model_get_iter (selection->tree_view->priv->model, &iter, path);
393           (* func) (selection->tree_view->priv->model, path, &iter, data);
394           gtk_tree_path_free (path);
395         }
396       return;
397     }
398
399   tree = selection->tree_view->priv->tree;
400   node = selection->tree_view->priv->tree->root;
401   
402   while (node->left != tree->nil)
403     node = node->left;
404
405   /* find the node internally */
406   path = gtk_tree_path_new_root ();
407   gtk_tree_model_get_iter (selection->tree_view->priv->model,
408                            &iter, path);
409
410   do
411     {
412       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
413         (* func) (selection->tree_view->priv->model, path, &iter, data);
414       if (node->children)
415         {
416           gboolean has_child;
417           GtkTreeIter tmp;
418
419           tree = node->children;
420           node = tree->root;
421           while (node->left != tree->nil)
422             node = node->left;
423           tmp = iter;
424           has_child = gtk_tree_model_iter_children (selection->tree_view->priv->model, &iter, &tmp);
425           gtk_tree_path_append_index (path, 0);
426           /* Sanity Check! */
427           TREE_VIEW_INTERNAL_ASSERT_VOID (has_child);
428         }
429       else
430         {
431           gboolean done = FALSE;
432           do
433             {
434               node = _gtk_rbtree_next (tree, node);
435               if (node != NULL)
436                 {
437                   gboolean has_next;
438
439                   has_next = gtk_tree_model_iter_next (selection->tree_view->priv->model, &iter);
440                   done = TRUE;
441                   gtk_tree_path_next (path);
442
443                   /* Sanity Check! */
444                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_next);
445                 }
446               else
447                 {
448                   gboolean has_parent;
449                   GtkTreeIter tmp_iter = iter;
450
451                   node = tree->parent_node;
452                   tree = tree->parent_tree;
453                   if (tree == NULL)
454                     {
455                       gtk_tree_path_free (path);
456                       /* we've run out of tree */
457                       /* We're done with this function */
458                       return;
459                     }
460                   has_parent = gtk_tree_model_iter_parent (selection->tree_view->priv->model, &iter, &tmp_iter);
461                   gtk_tree_path_up (path);
462                   /* Sanity check */
463                   TREE_VIEW_INTERNAL_ASSERT_VOID (has_parent);
464                 }
465             }
466           while (!done);
467         }
468     }
469   while (TRUE);
470 }
471
472 /**
473  * gtk_tree_selection_select_path:
474  * @selection: A #GtkTreeSelection.
475  * @path: The #GtkTreePath to be selected.
476  *
477  * Select the row at @path.
478  **/
479 void
480 gtk_tree_selection_select_path (GtkTreeSelection *selection,
481                                 GtkTreePath      *path)
482 {
483   GtkRBNode *node;
484   GtkRBTree *tree;
485   GdkModifierType state = 0;
486
487   g_return_if_fail (selection != NULL);
488   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
489   g_return_if_fail (selection->tree_view != NULL);
490   g_return_if_fail (path != NULL);
491
492   _gtk_tree_view_find_node (selection->tree_view,
493                             path,
494                             &tree,
495                             &node);
496
497   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
498     return;
499
500   if (selection->type == GTK_TREE_SELECTION_MULTI)
501     state = GDK_CONTROL_MASK;
502
503   _gtk_tree_selection_internal_select_node (selection,
504                                             node,
505                                             tree,
506                                             path,
507                                             state);
508 }
509
510 /**
511  * gtk_tree_selection_unselect_path:
512  * @selection: A #GtkTreeSelection.
513  * @path: The #GtkTreePath to be unselected.
514  *
515  * Unselects the row at @path.
516  **/
517 void
518 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
519                                   GtkTreePath      *path)
520 {
521   GtkRBNode *node;
522   GtkRBTree *tree;
523
524   g_return_if_fail (selection != NULL);
525   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
526   g_return_if_fail (selection->tree_view != NULL);
527   g_return_if_fail (path != NULL);
528
529   _gtk_tree_view_find_node (selection->tree_view,
530                             path,
531                             &tree,
532                             &node);
533
534   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
535     return;
536
537   _gtk_tree_selection_internal_select_node (selection,
538                                             node,
539                                             tree,
540                                             path,
541                                             GDK_CONTROL_MASK);
542 }
543
544 /**
545  * gtk_tree_selection_select_iter:
546  * @selection: A #GtkTreeSelection.
547  * @iter: The #GtkTreeIter to be selected.
548  *
549  * Selects the specified iterator.
550  **/
551 void
552 gtk_tree_selection_select_iter (GtkTreeSelection *selection,
553                                 GtkTreeIter      *iter)
554 {
555   GtkTreePath *path;
556
557   g_return_if_fail (selection != NULL);
558   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
559   g_return_if_fail (selection->tree_view != NULL);
560   g_return_if_fail (selection->tree_view->priv->model != NULL);
561   g_return_if_fail (iter != NULL);
562
563   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
564                                   iter);
565
566   if (path == NULL)
567     return;
568
569   gtk_tree_selection_select_path (selection, path);
570   gtk_tree_path_free (path);
571 }
572
573
574 /**
575  * gtk_tree_selection_unselect_iter:
576  * @selection: A #GtkTreeSelection.
577  * @iter: The #GtkTreeIter to be unselected.
578  *
579  * Unselects the specified iterator.
580  **/
581 void
582 gtk_tree_selection_unselect_iter (GtkTreeSelection *selection,
583                                   GtkTreeIter      *iter)
584 {
585   GtkTreePath *path;
586
587   g_return_if_fail (selection != NULL);
588   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
589   g_return_if_fail (selection->tree_view != NULL);
590   g_return_if_fail (selection->tree_view->priv->model != NULL);
591   g_return_if_fail (iter != NULL);
592
593   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
594                                   iter);
595
596   if (path == NULL)
597     return;
598
599   gtk_tree_selection_select_path (selection, path);
600   gtk_tree_path_free (path);
601 }
602
603 /* Wish I was in python, right now... */
604 struct _TempTuple {
605   GtkTreeSelection *selection;
606   gint dirty;
607 };
608
609 static void
610 select_all_helper (GtkRBTree  *tree,
611                    GtkRBNode  *node,
612                    gpointer    data)
613 {
614   struct _TempTuple *tuple = data;
615
616   if (node->children)
617     _gtk_rbtree_traverse (node->children,
618                           node->children->root,
619                           G_PRE_ORDER,
620                           select_all_helper,
621                           data);
622   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
623     {
624       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
625     }
626 }
627
628
629 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
630  * can use it in other places without fear of the signal being emitted.
631  */
632 static gint
633 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
634 {
635   struct _TempTuple *tuple;
636
637   if (selection->tree_view->priv->tree == NULL)
638     return FALSE;
639
640   /* Mark all nodes selected */
641   tuple = g_new (struct _TempTuple, 1);
642   tuple->selection = selection;
643   tuple->dirty = FALSE;
644
645   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
646                         selection->tree_view->priv->tree->root,
647                         G_PRE_ORDER,
648                         select_all_helper,
649                         tuple);
650   if (tuple->dirty)
651     {
652       g_free (tuple);
653       return TRUE;
654     }
655   g_free (tuple);
656   return FALSE;
657 }
658
659 /**
660  * gtk_tree_selection_select_all:
661  * @selection: A #GtkTreeSelection.
662  *
663  * Selects all the nodes.  @selection is must be set to
664  * #GTK_TREE_SELECTION_MULTI mode.
665  **/
666 void
667 gtk_tree_selection_select_all (GtkTreeSelection *selection)
668 {
669   g_return_if_fail (selection != NULL);
670   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
671   g_return_if_fail (selection->tree_view != NULL);
672   g_return_if_fail (selection->tree_view->priv->tree != NULL);
673   g_return_if_fail (selection->type != GTK_TREE_SELECTION_MULTI);
674
675   if (gtk_tree_selection_real_select_all (selection))
676     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
677 }
678
679 static void
680 unselect_all_helper (GtkRBTree  *tree,
681                      GtkRBNode  *node,
682                      gpointer    data)
683 {
684   struct _TempTuple *tuple = data;
685
686   if (node->children)
687     _gtk_rbtree_traverse (node->children,
688                           node->children->root,
689                           G_PRE_ORDER,
690                           unselect_all_helper,
691                           data);
692   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
693     {
694       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
695     }
696 }
697
698 static gint
699 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
700 {
701   struct _TempTuple *tuple;
702
703   if (selection->type == GTK_TREE_SELECTION_SINGLE)
704     {
705       GtkRBTree *tree = NULL;
706       GtkRBNode *node = NULL;
707       GtkTreePath *anchor_path;
708
709       if (selection->tree_view->priv->anchor == NULL)
710         return FALSE;
711
712       anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
713
714       if (anchor_path == NULL)
715         return FALSE;
716
717       _gtk_tree_view_find_node (selection->tree_view,
718                                 anchor_path,
719                                 &tree,
720                                 &node);
721
722       gtk_tree_path_free (anchor_path);
723
724       if (tree == NULL)
725         return FALSE;
726
727       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
728         {
729           if (gtk_tree_selection_real_select_node (selection, tree, node, FALSE))
730             {
731               gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
732               selection->tree_view->priv->anchor = NULL;
733               return TRUE;
734             }
735         }
736       return FALSE;
737     }
738   else
739     {
740       tuple = g_new (struct _TempTuple, 1);
741       tuple->selection = selection;
742       tuple->dirty = FALSE;
743
744       _gtk_rbtree_traverse (selection->tree_view->priv->tree,
745                             selection->tree_view->priv->tree->root,
746                             G_PRE_ORDER,
747                             unselect_all_helper,
748                             tuple);
749
750       if (tuple->dirty)
751         {
752           g_free (tuple);
753           return TRUE;
754         }
755       g_free (tuple);
756       return FALSE;
757     }
758 }
759
760 /**
761  * gtk_tree_selection_unselect_all:
762  * @selection: A #GtkTreeSelection.
763  *
764  * Unselects all the nodes.
765  **/
766 void
767 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
768 {
769   g_return_if_fail (selection != NULL);
770   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
771   g_return_if_fail (selection->tree_view != NULL);
772   g_return_if_fail (selection->tree_view->priv->tree != NULL);
773   if (selection->tree_view->priv->tree == NULL)
774     return;
775
776   if (gtk_tree_selection_real_unselect_all (selection))
777     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
778 }
779
780 static gint
781 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
782                                       GtkTreePath      *start_path,
783                                       GtkTreePath      *end_path)
784 {
785   GtkRBNode *start_node, *end_node;
786   GtkRBTree *start_tree, *end_tree;
787   gboolean dirty = FALSE;
788
789   switch (gtk_tree_path_compare (start_path, end_path))
790     {
791     case 1:
792       _gtk_tree_view_find_node (selection->tree_view,
793                                 end_path,
794                                 &start_tree,
795                                 &start_node);
796       _gtk_tree_view_find_node (selection->tree_view,
797                                 start_path,
798                                 &end_tree,
799                                 &end_node);
800       break;
801     case 0:
802       _gtk_tree_view_find_node (selection->tree_view,
803                                 start_path,
804                                 &start_tree,
805                                 &start_node);
806       end_tree = start_tree;
807       end_node = start_node;
808       break;
809     case -1:
810       _gtk_tree_view_find_node (selection->tree_view,
811                                 start_path,
812                                 &start_tree,
813                                 &start_node);
814       _gtk_tree_view_find_node (selection->tree_view,
815                                 end_path,
816                                 &end_tree,
817                                 &end_node);
818       break;
819     }
820
821   g_return_val_if_fail (start_node != NULL, FALSE);
822   g_return_val_if_fail (end_node != NULL, FALSE);
823
824   do
825     {
826       if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
827         {
828           dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
829         }
830
831       if (start_node == end_node)
832         break;
833
834       if (start_node->children)
835         {
836           start_tree = start_node->children;
837           start_node = start_tree->root;
838           while (start_node->left != start_tree->nil)
839             start_node = start_node->left;
840         }
841       else
842         {
843           gboolean done = FALSE;
844           do
845             {
846               start_node = _gtk_rbtree_next (start_tree, start_node);
847               if (start_node != NULL)
848                 {
849                   done = TRUE;
850                 }
851               else
852                 {
853                   start_node = start_tree->parent_node;
854                   start_tree = start_tree->parent_tree;
855                   if (start_tree == NULL)
856                     /* FIXME should this really be silent, or should it g_warning? */
857                     /* we've run out of tree */
858                     /* This means we never found end node!! */
859                     break;
860                 }
861             }
862           while (!done);
863         }
864     }
865   while (TRUE);
866
867   return dirty;
868 }
869
870 /**
871  * gtk_tree_selection_select_range:
872  * @selection: A #GtkTreeSelection.
873  * @start_path: The initial node of the range.
874  * @end_path: The final node of the range.
875  *
876  * Selects a range of nodes, determined by @start_path and @end_path inclusive.
877  **/
878 void
879 gtk_tree_selection_select_range (GtkTreeSelection *selection,
880                                  GtkTreePath      *start_path,
881                                  GtkTreePath      *end_path)
882 {
883   g_return_if_fail (selection != NULL);
884   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
885   g_return_if_fail (selection->tree_view != NULL);
886
887   if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
888     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
889 }
890
891 /* Called internally by gtktreeview.c It handles actually selecting the tree.
892  */
893 void
894 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
895                                           GtkRBNode        *node,
896                                           GtkRBTree        *tree,
897                                           GtkTreePath      *path,
898                                           GdkModifierType   state)
899 {
900   gint flags;
901   gint dirty = FALSE;
902   GtkTreePath *anchor_path = NULL;
903
904
905   if (selection->tree_view->priv->anchor)
906     anchor_path = gtk_tree_row_reference_get_path (selection->tree_view->priv->anchor);
907
908   if (selection->type == GTK_TREE_SELECTION_SINGLE)
909     {
910       /* Did we try to select the same node again? */
911       if (anchor_path && gtk_tree_path_compare (path, anchor_path) == 0)
912         {
913           if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
914             {
915               dirty = gtk_tree_selection_real_unselect_all (selection);
916             }
917         }
918       else
919         {
920           /* FIXME: We only want to select the new node if we can unselect the
921            * old one, and we can select the new one.  We are currently
922            * unselecting the old one first, then trying the new one. */
923           if (anchor_path)
924             {
925               dirty = gtk_tree_selection_real_unselect_all (selection);
926               if (dirty)
927                 {
928                   if (selection->tree_view->priv->anchor)
929                     gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
930                   if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
931                     {
932                       selection->tree_view->priv->anchor =
933                         gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
934                     }
935                 }
936             }
937           else
938             {
939               if (gtk_tree_selection_real_select_node (selection, tree, node, TRUE))
940                 {
941                   dirty = TRUE;
942                   selection->tree_view->priv->anchor =
943                     gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
944                 }
945             }
946         }
947     }
948   else if (selection->type == GTK_TREE_SELECTION_MULTI)
949     {
950       if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (anchor_path == NULL))
951         {
952           if (selection->tree_view->priv->anchor)
953             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
954
955           selection->tree_view->priv->anchor =
956             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
957           dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
958         }
959       else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
960         {
961           gtk_tree_selection_select_range (selection,
962                                            anchor_path,
963                                            path);
964         }
965       else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
966         {
967           flags = node->flags;
968           if (selection->tree_view->priv->anchor)
969             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
970
971           selection->tree_view->priv->anchor =
972             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
973
974           if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
975             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
976           else
977             dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
978         }
979       else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
980         {
981           dirty = gtk_tree_selection_real_unselect_all (selection);
982           dirty |= gtk_tree_selection_real_select_range (selection,
983                                                          anchor_path,
984                                                          path);
985         }
986       else
987         {
988           dirty = gtk_tree_selection_real_unselect_all (selection);
989
990           if (selection->tree_view->priv->anchor)
991             gtk_tree_row_reference_free (selection->tree_view->priv->anchor);
992
993           selection->tree_view->priv->anchor =
994             gtk_tree_row_reference_new_proxy (G_OBJECT (selection->tree_view), selection->tree_view->priv->model, path);
995
996           dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
997         }
998     }
999
1000   if (anchor_path)
1001     gtk_tree_path_free (anchor_path);
1002
1003   if (dirty)
1004     g_signal_emit (G_OBJECT (selection), tree_selection_signals[CHANGED], 0);
1005 }
1006
1007 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
1008  */
1009
1010 /* FIXME: user_func can screw up GTK_TREE_SELECTION_SINGLE.  If it prevents
1011  * unselection of a node, it can keep more then one node selected.
1012  */
1013 /* Perhaps the correct solution is to prevent selecting the new node, if
1014  * we fail to unselect the old node.
1015  */
1016 static gint
1017 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
1018                                      GtkRBTree        *tree,
1019                                      GtkRBNode        *node,
1020                                      gboolean          select)
1021 {
1022   gboolean selected = FALSE;
1023   GtkTreePath *path = NULL;
1024
1025   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
1026     {
1027       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
1028       if (selection->user_func)
1029         {
1030           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
1031             selected = TRUE;
1032         }
1033       else
1034         selected = TRUE;
1035       gtk_tree_path_free (path);
1036     }
1037
1038   if (selected == TRUE)
1039     {
1040       node->flags ^= GTK_RBNODE_IS_SELECTED;
1041
1042       /* FIXME: just draw the one node*/
1043       gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
1044       return TRUE;
1045     }
1046
1047   return FALSE;
1048 }
1049