]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeselection.c
Added values other then G_TYPE_STRING. Minor commenting updates. Format
[~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 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,
30                                                   GtkRBTree             *tree,
31                                                   GtkRBNode             *node,
32                                                   gboolean               select);
33
34 enum {
35   SELECTION_CHANGED,
36   LAST_SIGNAL
37 };
38
39 static GtkObjectClass *parent_class = NULL;
40 static guint tree_selection_signals[LAST_SIGNAL] = { 0 };
41
42 GtkType
43 gtk_tree_selection_get_type (void)
44 {
45   static GtkType selection_type = 0;
46
47   if (!selection_type)
48     {
49       static const GTypeInfo selection_info =
50       {
51         sizeof (GtkTreeSelectionClass),
52         NULL,           /* base_init */
53         NULL,           /* base_finalize */
54         (GClassInitFunc) gtk_tree_selection_class_init,
55         NULL,           /* class_finalize */
56         NULL,           /* class_data */
57         sizeof (GtkTreeSelection),
58         0,              /* n_preallocs */
59         (GInstanceInitFunc) gtk_tree_selection_init
60       };
61
62       selection_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeSelection", &selection_info);
63     }
64
65   return selection_type;
66 }
67
68 static void
69 gtk_tree_selection_class_init (GtkTreeSelectionClass *class)
70 {
71   GtkObjectClass *object_class;
72
73   object_class = (GtkObjectClass*) class;
74   parent_class = g_type_class_peek_parent (class);
75
76   tree_selection_signals[SELECTION_CHANGED] =
77     gtk_signal_new ("selection_changed",
78                     GTK_RUN_FIRST,
79                     GTK_CLASS_TYPE (object_class),
80                     GTK_SIGNAL_OFFSET (GtkTreeSelectionClass, selection_changed),
81                     gtk_marshal_NONE__NONE,
82                     GTK_TYPE_NONE, 0);
83
84   gtk_object_class_add_signals (object_class, tree_selection_signals, LAST_SIGNAL);
85
86   class->selection_changed = NULL;
87 }
88
89 static void
90 gtk_tree_selection_init (GtkTreeSelection *selection)
91 {
92   selection->type = GTK_TREE_SELECTION_SINGLE;
93 }
94
95 GtkObject *
96 gtk_tree_selection_new (void)
97 {
98   GtkObject *selection;
99
100   selection = GTK_OBJECT (gtk_type_new (GTK_TYPE_TREE_SELECTION));
101
102   return selection;
103 }
104
105 GtkObject *
106 gtk_tree_selection_new_with_tree_view (GtkTreeView *tree_view)
107 {
108   GtkObject *selection;
109
110   g_return_val_if_fail (tree_view != NULL, NULL);
111   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
112
113   selection = gtk_tree_selection_new ();
114   gtk_tree_selection_set_tree_view (GTK_TREE_SELECTION (selection), tree_view);
115
116   return selection;
117 }
118
119 void
120 gtk_tree_selection_set_tree_view (GtkTreeSelection *selection,
121                                   GtkTreeView      *tree_view)
122 {
123   g_return_if_fail (selection != NULL);
124   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
125   if (tree_view != NULL)
126     g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
127
128   selection->tree_view = tree_view;
129   tree_view->priv->selection = selection;
130 }
131
132 void
133 gtk_tree_selection_set_type (GtkTreeSelection     *selection,
134                              GtkTreeSelectionType  type)
135 {
136   g_return_if_fail (selection != NULL);
137   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
138
139   if (selection->type == type)
140     return;
141
142   if (type == GTK_TREE_SELECTION_SINGLE)
143     {
144       GtkRBTree *tree = NULL;
145       GtkRBNode *node = NULL;
146       gint selected = FALSE;
147
148       if (selection->tree_view->priv->anchor)
149         {
150           _gtk_tree_view_find_node (selection->tree_view,
151                                     selection->tree_view->priv->anchor,
152                                     &tree,
153                                     &node);
154
155           if (node && GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
156             selected = TRUE;
157         }
158       gtk_tree_selection_unselect_all (selection);
159       if (node && selected)
160         GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_SELECTED);
161     }
162   selection->type = type;
163 }
164
165 void
166 gtk_tree_selection_set_select_function (GtkTreeSelection     *selection,
167                                         GtkTreeSelectionFunc  func,
168                                         gpointer            data)
169 {
170   g_return_if_fail (selection != NULL);
171   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
172   g_return_if_fail (func != NULL);
173
174   selection->user_func = func;
175   selection->user_data = data;
176 }
177
178 gpointer
179 gtk_tree_selection_get_user_data (GtkTreeSelection *selection)
180 {
181   g_return_val_if_fail (selection != NULL, NULL);
182   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
183
184   return selection->user_data;
185 }
186
187 GtkTreeNode *
188 gtk_tree_selection_get_selected (GtkTreeSelection *selection)
189 {
190   GtkTreeNode *retval;
191   GtkRBTree *tree;
192   GtkRBNode *node;
193
194   g_return_val_if_fail (selection != NULL, NULL);
195   g_return_val_if_fail (GTK_IS_TREE_SELECTION (selection), NULL);
196
197   if (selection->tree_view->priv->anchor == NULL)
198     return NULL;
199
200   g_return_val_if_fail (selection->tree_view != NULL, NULL);
201   g_return_val_if_fail (selection->tree_view->priv->model != NULL, NULL);
202
203   if (!_gtk_tree_view_find_node (selection->tree_view,
204                                 selection->tree_view->priv->anchor,
205                                 &tree,
206                                 &node) &&
207       ! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
208     /* We don't want to return the anchor if it isn't actually selected.
209      */
210
211       return NULL;
212
213   retval = gtk_tree_model_get_node (selection->tree_view->priv->model,
214                                     selection->tree_view->priv->anchor);
215   return retval;
216 }
217
218 void
219 gtk_tree_selection_selected_foreach (GtkTreeSelection            *selection,
220                                      GtkTreeSelectionForeachFunc  func,
221                                      gpointer                     data)
222 {
223   GtkTreePath *path;
224   GtkRBTree *tree;
225   GtkRBNode *node;
226   GtkTreeNode tree_node;
227
228   g_return_if_fail (selection != NULL);
229   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
230   g_return_if_fail (selection->tree_view != NULL);
231   g_return_if_fail (selection->tree_view->priv->model != NULL);
232
233   if (func == NULL ||
234       selection->tree_view->priv->tree == NULL ||
235       selection->tree_view->priv->tree->root == NULL)
236     return;
237
238   tree = selection->tree_view->priv->tree;
239   node = selection->tree_view->priv->tree->root;
240
241   while (node->left != tree->nil)
242     node = node->left;
243
244   /* find the node internally */
245   path = gtk_tree_path_new_root ();
246   tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
247   gtk_tree_path_free (path);
248
249   do
250     {
251       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
252         (* func) (selection->tree_view->priv->model, tree_node, data);
253       if (node->children)
254         {
255           tree = node->children;
256           node = tree->root;
257           while (node->left != tree->nil)
258             node = node->left;
259           tree_node = gtk_tree_model_node_children (selection->tree_view->priv->model, tree_node);
260
261           /* Sanity Check! */
262           TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
263         }
264       else
265         {
266           gboolean done = FALSE;
267           do
268             {
269               node = _gtk_rbtree_next (tree, node);
270               if (node != NULL)
271                 {
272                   gtk_tree_model_node_next (selection->tree_view->priv->model, &tree_node);
273                   done = TRUE;
274
275                   /* Sanity Check! */
276                   TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
277                 }
278               else
279                 {
280                   node = tree->parent_node;
281                   tree = tree->parent_tree;
282                   if (tree == NULL)
283                     /* we've run out of tree */
284                     /* We're done with this function */
285                     return;
286                   tree_node = gtk_tree_model_node_parent (selection->tree_view->priv->model, tree_node);
287
288                   /* Sanity check */
289                   TREE_VIEW_INTERNAL_ASSERT_VOID (tree_node != NULL);
290                 }
291             }
292           while (!done);
293         }
294     }
295   while (TRUE);
296 }
297
298 void
299 gtk_tree_selection_select_path (GtkTreeSelection *selection,
300                                 GtkTreePath      *path)
301 {
302   GtkRBNode *node;
303   GtkRBTree *tree;
304   GdkModifierType state = 0;
305
306   g_return_if_fail (selection != NULL);
307   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
308   g_return_if_fail (selection->tree_view != NULL);
309   g_return_if_fail (path != NULL);
310
311   _gtk_tree_view_find_node (selection->tree_view,
312                             path,
313                             &tree,
314                             &node);
315
316   if (node == NULL || GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
317     return;
318
319   if (selection->type == GTK_TREE_SELECTION_MULTI)
320     state = GDK_CONTROL_MASK;
321
322   _gtk_tree_selection_internal_select_node (selection,
323                                             node,
324                                             tree,
325                                             path,
326                                             state);
327 }
328
329 void
330 gtk_tree_selection_unselect_path (GtkTreeSelection *selection,
331                                   GtkTreePath      *path)
332 {
333   GtkRBNode *node;
334   GtkRBTree *tree;
335
336   g_return_if_fail (selection != NULL);
337   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
338   g_return_if_fail (selection->tree_view != NULL);
339   g_return_if_fail (path != NULL);
340
341   _gtk_tree_view_find_node (selection->tree_view,
342                             path,
343                             &tree,
344                             &node);
345
346   if (node == NULL || !GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
347     return;
348
349   _gtk_tree_selection_internal_select_node (selection,
350                                             node,
351                                             tree,
352                                             path,
353                                             GDK_CONTROL_MASK);
354 }
355
356 void
357 gtk_tree_selection_select_node (GtkTreeSelection *selection,
358                                 GtkTreeNode      *tree_node)
359 {
360   GtkTreePath *path;
361
362   g_return_if_fail (selection != NULL);
363   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
364   g_return_if_fail (selection->tree_view != NULL);
365   g_return_if_fail (selection->tree_view->priv->model != NULL);
366
367   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
368                                   tree_node);
369
370   if (path == NULL)
371     return;
372
373   gtk_tree_selection_select_path (selection, path);
374   gtk_tree_path_free (path);
375 }
376
377
378 void
379 gtk_tree_selection_unselect_node (GtkTreeSelection *selection,
380                                   GtkTreeNode      *tree_node)
381 {
382   GtkTreePath *path;
383
384   g_return_if_fail (selection != NULL);
385   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
386   g_return_if_fail (selection->tree_view != NULL);
387
388   path = gtk_tree_model_get_path (selection->tree_view->priv->model,
389                                   tree_node);
390
391   if (path == NULL)
392     return;
393
394   gtk_tree_selection_select_path (selection, path);
395   gtk_tree_path_free (path);
396 }
397
398 /* Wish I was in python, right now... */
399 struct _TempTuple {
400   GtkTreeSelection *selection;
401   gint dirty;
402 };
403
404 static void
405 select_all_helper (GtkRBTree  *tree,
406                    GtkRBNode  *node,
407                    gpointer  data)
408 {
409   struct _TempTuple *tuple = data;
410
411   if (node->children)
412     _gtk_rbtree_traverse (node->children,
413                           node->children->root,
414                           G_PRE_ORDER,
415                           select_all_helper,
416                           data);
417   if (!GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
418     {
419       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, TRUE) || tuple->dirty;
420     }
421 }
422
423
424 /* We have a real_{un,}select_all function that doesn't emit the signal, so we
425  * can use it in other places without fear of the signal being emitted.
426  */
427 static gint
428 gtk_tree_selection_real_select_all (GtkTreeSelection *selection)
429 {
430   struct _TempTuple *tuple;
431   if (selection->tree_view->priv->tree == NULL)
432     return FALSE;
433
434   if (selection->type == GTK_TREE_SELECTION_SINGLE)
435     {
436       GtkRBTree *tree;
437       GtkRBNode *node;
438       gint dirty;
439       
440       dirty = gtk_tree_selection_real_unselect_all (selection);
441
442       tree = selection->tree_view->priv->tree;
443       node = tree->root;
444       do
445         {
446           while (node->right != selection->tree_view->priv->tree->nil)
447             node = node->right;
448
449           if (node->children)
450             {
451               tree = node->children;
452               node = tree->root;
453             }
454           else
455             break;
456         } while (TRUE);
457
458       dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
459
460       return dirty;
461     }
462
463   tuple = g_new (struct _TempTuple, 1);
464   tuple->selection = selection;
465   tuple->dirty = FALSE;
466
467   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
468                         selection->tree_view->priv->tree->root,
469                         G_PRE_ORDER,
470                         select_all_helper,
471                         tuple);
472   if (tuple->dirty)
473     {
474       g_free (tuple);
475       return TRUE;
476     }
477   g_free (tuple);
478   return FALSE;
479 }
480
481 void
482 gtk_tree_selection_select_all (GtkTreeSelection *selection)
483 {
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);
487   g_return_if_fail (selection->tree_view->priv->tree != NULL);
488
489   if (gtk_tree_selection_real_select_all (selection))
490     gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
491 }
492
493 static void
494 unselect_all_helper (GtkRBTree  *tree,
495                      GtkRBNode  *node,
496                      gpointer  data)
497 {
498   struct _TempTuple *tuple = data;
499
500   if (node->children)
501     _gtk_rbtree_traverse (node->children,
502                           node->children->root,
503                           G_PRE_ORDER,
504                           unselect_all_helper,
505                           data);
506   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
507     {
508       tuple->dirty = gtk_tree_selection_real_select_node (tuple->selection, tree, node, FALSE) || tuple->dirty;
509     }
510 }
511
512 static gint
513 gtk_tree_selection_real_unselect_all (GtkTreeSelection *selection)
514 {
515   struct _TempTuple *tuple;
516
517   if (selection->type == GTK_TREE_SELECTION_SINGLE)
518     {
519       GtkRBTree *tree = NULL;
520       GtkRBNode *node = NULL;
521       if (selection->tree_view->priv->anchor == NULL)
522         return FALSE;
523
524       _gtk_tree_view_find_node (selection->tree_view,
525                                 selection->tree_view->priv->anchor,
526                                 &tree,
527                                 &node);
528       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
529         {
530           gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
531           return TRUE;
532         }
533       return FALSE;
534     }
535
536   tuple = g_new (struct _TempTuple, 1);
537   tuple->selection = selection;
538   tuple->dirty = FALSE;
539
540   _gtk_rbtree_traverse (selection->tree_view->priv->tree,
541                         selection->tree_view->priv->tree->root,
542                         G_PRE_ORDER,
543                         unselect_all_helper,
544                         tuple);
545
546   if (tuple->dirty)
547     {
548       g_free (tuple);
549       return TRUE;
550     }
551   g_free (tuple);
552   return FALSE;
553 }
554
555 void
556 gtk_tree_selection_unselect_all (GtkTreeSelection *selection)
557 {
558   g_return_if_fail (selection != NULL);
559   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
560   g_return_if_fail (selection->tree_view != NULL);
561   g_return_if_fail (selection->tree_view->priv->tree != NULL);
562   if (selection->tree_view->priv->tree == NULL)
563     return;
564
565   if (gtk_tree_selection_real_unselect_all (selection))
566     gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
567 }
568
569 static gint
570 gtk_tree_selection_real_select_range (GtkTreeSelection *selection,
571                                       GtkTreePath      *start_path,
572                                       GtkTreePath      *end_path)
573 {
574   GtkRBNode *start_node, *end_node;
575   GtkRBTree *start_tree, *end_tree;
576   gboolean dirty = FALSE;
577
578   switch (gtk_tree_path_compare (start_path, end_path))
579     {
580     case -1:
581       _gtk_tree_view_find_node (selection->tree_view,
582                                 end_path,
583                                 &start_tree,
584                                 &start_node);
585       _gtk_tree_view_find_node (selection->tree_view,
586                                 start_path,
587                                 &end_tree,
588                                 &end_node);
589       break;
590     case 0:
591       _gtk_tree_view_find_node (selection->tree_view,
592                                 start_path,
593                                 &start_tree,
594                                 &start_node);
595       end_tree = start_tree;
596       end_node = start_node;
597       break;
598     case 1:
599       _gtk_tree_view_find_node (selection->tree_view,
600                                 start_path,
601                                 &start_tree,
602                                 &start_node);
603       _gtk_tree_view_find_node (selection->tree_view,
604                                 end_path,
605                                 &end_tree,
606                                 &end_node);
607       break;
608     }
609
610   g_return_val_if_fail (start_node != NULL, FALSE);
611   g_return_val_if_fail (end_node != NULL, FALSE);
612
613   do
614     {
615       if (GTK_RBNODE_FLAG_SET (start_node, GTK_RBNODE_IS_SELECTED))
616         {
617           dirty = gtk_tree_selection_real_select_node (selection, start_tree, start_node, FALSE);
618         }
619
620       if (start_node == end_node)
621         break;
622
623       if (start_node->children)
624         {
625           start_tree = start_node->children;
626           start_node = start_tree->root;
627           while (start_node->left != start_tree->nil)
628             start_node = start_node->left;
629         }
630       else
631         {
632           gboolean done = FALSE;
633           do
634             {
635               start_node = _gtk_rbtree_next (start_tree, start_node);
636               if (start_node != NULL)
637                 {
638                   done = TRUE;
639                 }
640               else
641                 {
642                   start_node = start_tree->parent_node;
643                   start_tree = start_tree->parent_tree;
644                   if (start_tree == NULL)
645                     /* we've run out of tree */
646                     /* This means we never found end node!! */
647                     break;
648                 }
649             }
650           while (!done);
651         }
652     }
653   while (TRUE);
654
655   return dirty;
656 }
657
658 void
659 gtk_tree_selection_select_range (GtkTreeSelection *selection,
660                                  GtkTreePath      *start_path,
661                                  GtkTreePath      *end_path)
662 {
663   g_return_if_fail (selection != NULL);
664   g_return_if_fail (GTK_IS_TREE_SELECTION (selection));
665   g_return_if_fail (selection->tree_view != NULL);
666
667   if (gtk_tree_selection_real_select_range (selection, start_path, end_path))
668     gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
669 }
670 /* Called internally by gtktreeview.c It handles actually selecting the tree.
671  * This should almost certainly ever be called by anywhere else.
672  */
673 void
674 _gtk_tree_selection_internal_select_node (GtkTreeSelection *selection,
675                                           GtkRBNode        *node,
676                                           GtkRBTree        *tree,
677                                           GtkTreePath      *path,
678                                           GdkModifierType   state)
679 {
680   gint flags;
681   gint dirty = FALSE;
682
683   if (((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK) && (selection->tree_view->priv->anchor == NULL))
684     {
685       selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
686       dirty = gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
687     }
688   else if ((state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) == (GDK_SHIFT_MASK|GDK_CONTROL_MASK))
689     {
690       gtk_tree_selection_select_range (selection,
691                                        selection->tree_view->priv->anchor,
692                                        path);
693     }
694   else if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
695     {
696       flags = node->flags;
697       if (selection->type == GTK_TREE_SELECTION_SINGLE)
698         dirty = gtk_tree_selection_real_unselect_all (selection);
699
700       if (selection->tree_view->priv->anchor)
701         gtk_tree_path_free (selection->tree_view->priv->anchor);
702       selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
703
704       if ((flags & GTK_RBNODE_IS_SELECTED) == GTK_RBNODE_IS_SELECTED)
705         dirty |= gtk_tree_selection_real_select_node (selection, tree, node, FALSE);
706       else
707         dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
708     }
709   else if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
710     {
711       dirty = gtk_tree_selection_real_unselect_all (selection);
712       dirty |= gtk_tree_selection_real_select_range (selection,
713                                                      selection->tree_view->priv->anchor,
714                                                      path);
715     }
716   else
717     {
718       dirty = gtk_tree_selection_real_unselect_all (selection);
719       if (selection->tree_view->priv->anchor)
720         gtk_tree_path_free (selection->tree_view->priv->anchor);
721       selection->tree_view->priv->anchor = gtk_tree_path_copy (path);
722       dirty |= gtk_tree_selection_real_select_node (selection, tree, node, TRUE);
723     }
724
725   if (dirty)
726     gtk_signal_emit (GTK_OBJECT (selection), tree_selection_signals[SELECTION_CHANGED]);
727 }
728
729 /* NOTE: Any {un,}selection ever done _MUST_ be done through this function!
730  */
731 static gint
732 gtk_tree_selection_real_select_node (GtkTreeSelection *selection,
733                                      GtkRBTree        *tree,
734                                      GtkRBNode        *node,
735                                      gboolean          select)
736 {
737   gboolean selected = FALSE;
738   GtkTreePath *path = NULL;
739
740   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) != select)
741     {
742       path = _gtk_tree_view_find_path (selection->tree_view, tree, node);
743       if (selection->user_func)
744         {
745           if ((*selection->user_func) (selection, selection->tree_view->priv->model, path, selection->user_data))
746             selected = TRUE;
747         }
748       else
749         selected = TRUE;
750     }
751   if (selected == TRUE)
752     {
753       GtkTreeNode tree_node;
754       tree_node = gtk_tree_model_get_node (selection->tree_view->priv->model, path);
755
756       node->flags ^= GTK_RBNODE_IS_SELECTED;
757
758       /* FIXME: just draw the one node*/
759       gtk_widget_queue_draw (GTK_WIDGET (selection->tree_view));
760       return TRUE;
761     }
762
763   return FALSE;
764 }
765