]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
Patch from Matthias Clasen to remove remove all instances of
[~andy/gtk] / gtk / gtktreeview.c
1 /* gtktreeview.c
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
21 #include "gtktreeview.h"
22 #include "gtkrbtree.h"
23 #include "gtktreednd.h"
24 #include "gtktreeprivate.h"
25 #include "gtkcellrenderer.h"
26 #include "gtksignal.h"
27 #include "gtkmain.h"
28 #include "gtkbutton.h"
29 #include "gtkalignment.h"
30 #include "gtklabel.h"
31 #include "gtkhbox.h"
32 #include "gtkarrow.h"
33 #include "gtkintl.h"
34 #include "gtkbindings.h"
35
36 #include <gdk/gdkkeysyms.h>
37
38 #if defined (GDK_WINDOWING_X11)
39 #include "x11/gdkx.h"
40 #elif defined (GDK_WINDOWING_WIN32)
41 #include "win32/gdkwin32.h"
42 #elif defined(GDK_WINDOWING_FB)
43 #include "linux-fb/gdkfb.h"
44 #elif defined (GDK_WINDOWING_NANOX)
45 #include "nanox/gdkprivate-nanox.h"
46 #endif
47
48
49 #define SCROLL_EDGE_SIZE 15
50
51
52 /* The "background" areas of all rows/cells add up to cover the entire tree.
53  * The background includes all inter-row and inter-cell spacing.
54  * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
55  * i.e. just the cells, no spacing.
56  */
57 #define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (_gtk_rbtree_node_find_offset ((tree), (node)) + TREE_VIEW_HEADER_HEIGHT ((tree_view)))
58 #define CELL_FIRST_PIXEL(tree_view,tree,node,separator) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + separator/2)
59
60 #define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node))
61 #define CELL_HEIGHT(node, separator) (BACKGROUND_HEIGHT (node) - separator);
62
63 #define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) - TREE_VIEW_HEADER_HEIGHT (tree_view))
64 #define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) + TREE_VIEW_HEADER_HEIGHT (tree_view))
65
66
67 typedef struct _GtkTreeViewChild GtkTreeViewChild;
68 struct _GtkTreeViewChild
69 {
70   GtkWidget *widget;
71   gint x;
72   gint y;
73 };
74
75
76 typedef struct _TreeViewDragInfo TreeViewDragInfo;
77 struct _TreeViewDragInfo
78 {
79   GdkModifierType start_button_mask;
80   GtkTargetList *source_target_list;
81   GdkDragAction source_actions;
82   GClosure *row_draggable_closure;
83
84   GtkTargetList *dest_target_list;
85   GClosure *location_droppable_closure;
86
87   guint source_set : 1;
88   guint dest_set : 1;
89 };
90
91
92 /* Signals */
93 enum
94 {
95   ROW_ACTIVATED,
96   TEST_EXPAND_ROW,
97   TEST_COLLAPSE_ROW,
98   ROW_EXPANDED,
99   ROW_COLLAPSED,
100   COLUMNS_CHANGED,
101   BEGIN_EXTENDED_SELECTION,
102   END_EXTENDED_SELECTION,
103   BEGIN_FREE_MOTION,
104   END_FREE_MOTION,
105   MOVE_CURSOR,
106   SELECT_CURSOR_ROW,
107   TOGGLE_CURSOR_ROW,
108   EXPAND_COLLAPSE_CURSOR_ROW,
109   SELECT_CURSOR_PARENT,
110   LAST_SIGNAL
111 };
112
113 /* Properties */
114 enum {
115   PROP_0,
116   PROP_MODEL,
117   PROP_HADJUSTMENT,
118   PROP_VADJUSTMENT,
119   PROP_HEADERS_VISIBLE,
120   PROP_HEADERS_CLICKABLE,
121   PROP_EXPANDER_COLUMN,
122   PROP_REORDERABLE,
123   PROP_RULES_HINT
124 };
125
126 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
127 static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);
128
129 /* object signals */
130 static void     gtk_tree_view_finalize             (GObject          *object);
131 static void     gtk_tree_view_set_property         (GObject         *object,
132                                                     guint            prop_id,
133                                                     const GValue    *value,
134                                                     GParamSpec      *pspec);
135 static void     gtk_tree_view_get_property         (GObject         *object,
136                                                     guint            prop_id,
137                                                     GValue          *value,
138                                                     GParamSpec      *pspec);
139
140 /* gtkobject signals */
141 static void     gtk_tree_view_destroy              (GtkObject        *object);
142
143 /* gtkwidget signals */
144 static void     gtk_tree_view_setup_model          (GtkTreeView      *tree_view);
145 static void     gtk_tree_view_realize              (GtkWidget        *widget);
146 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
147 static void     gtk_tree_view_map                  (GtkWidget        *widget);
148 static void     gtk_tree_view_size_request         (GtkWidget        *widget,
149                                                     GtkRequisition   *requisition);
150 static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
151                                                     GtkAllocation    *allocation);
152 static gboolean gtk_tree_view_expose               (GtkWidget        *widget,
153                                                     GdkEventExpose   *event);
154 static gboolean gtk_tree_view_key_press            (GtkWidget        *widget,
155                                                     GdkEventKey      *event);
156 static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
157                                                     GdkEventMotion   *event);
158 static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
159                                                     GdkEventCrossing *event);
160 static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
161                                                     GdkEventCrossing *event);
162 static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
163                                                     GdkEventButton   *event);
164 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
165                                                     GdkEventButton   *event);
166 static void     gtk_tree_view_set_focus_child      (GtkContainer     *container,
167                                                     GtkWidget        *child);
168 static void     gtk_tree_view_draw_focus           (GtkWidget        *widget);
169 static gint     gtk_tree_view_focus_in             (GtkWidget        *widget,
170                                                     GdkEventFocus    *event);
171 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
172                                                     GdkEventFocus    *event);
173 static gint     gtk_tree_view_focus                (GtkWidget        *widget,
174                                                     GtkDirectionType  direction);
175
176 /* container signals */
177 static void     gtk_tree_view_remove               (GtkContainer     *container,
178                                                     GtkWidget        *widget);
179 static void     gtk_tree_view_forall               (GtkContainer     *container,
180                                                     gboolean          include_internals,
181                                                     GtkCallback       callback,
182                                                     gpointer          callback_data);
183
184 /* Source side drag signals */
185 static void gtk_tree_view_drag_begin       (GtkWidget        *widget,
186                                             GdkDragContext   *context);
187 static void gtk_tree_view_drag_end         (GtkWidget        *widget,
188                                             GdkDragContext   *context);
189 static void gtk_tree_view_drag_data_get    (GtkWidget        *widget,
190                                             GdkDragContext   *context,
191                                             GtkSelectionData *selection_data,
192                                             guint             info,
193                                             guint             time);
194 static void gtk_tree_view_drag_data_delete (GtkWidget        *widget,
195                                             GdkDragContext   *context);
196
197 /* Target side drag signals */
198 static void     gtk_tree_view_drag_leave         (GtkWidget        *widget,
199                                                   GdkDragContext   *context,
200                                                   guint             time);
201 static gboolean gtk_tree_view_drag_motion        (GtkWidget        *widget,
202                                                   GdkDragContext   *context,
203                                                   gint              x,
204                                                   gint              y,
205                                                   guint             time);
206 static gboolean gtk_tree_view_drag_drop          (GtkWidget        *widget,
207                                                   GdkDragContext   *context,
208                                                   gint              x,
209                                                   gint              y,
210                                                   guint             time);
211 static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
212                                                   GdkDragContext   *context,
213                                                   gint              x,
214                                                   gint              y,
215                                                   GtkSelectionData *selection_data,
216                                                   guint             info,
217                                                   guint             time);
218
219 /* tree_model signals */
220 static void gtk_tree_view_set_adjustments                 (GtkTreeView     *tree_view,
221                                                            GtkAdjustment   *hadj,
222                                                            GtkAdjustment   *vadj);
223 static void gtk_tree_view_real_begin_extended_selection   (GtkTreeView     *tree_view);
224 static void gtk_tree_view_real_end_extended_selection     (GtkTreeView     *tree_view);
225 static void gtk_tree_view_real_begin_free_motion          (GtkTreeView     *tree_view);
226 static void gtk_tree_view_real_end_free_motion            (GtkTreeView     *tree_view);
227 static void gtk_tree_view_real_move_cursor                (GtkTreeView     *tree_view,
228                                                            GtkMovementStep  step,
229                                                            gint             count);
230 static void gtk_tree_view_real_select_cursor_row          (GtkTreeView     *tree_view);
231 static void gtk_tree_view_real_toggle_cursor_row          (GtkTreeView     *tree_view);
232 static void gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView     *tree_view,
233                                                            gboolean         logical,
234                                                            gboolean         expand,
235                                                            gboolean         open_all);
236 static void gtk_tree_view_real_select_cursor_parent       (GtkTreeView     *tree_view);
237 static void gtk_tree_view_range_changed                   (GtkTreeModel    *model,
238                                                            GtkTreePath     *path,
239                                                            GtkTreeIter     *iter,
240                                                            GtkTreePath     *end_path,
241                                                            GtkTreeIter     *end_iter,
242                                                            gpointer         data);
243 static void gtk_tree_view_inserted                        (GtkTreeModel    *model,
244                                                            GtkTreePath     *path,
245                                                            GtkTreeIter     *iter,
246                                                            gpointer         data);
247 static void gtk_tree_view_has_child_toggled               (GtkTreeModel    *model,
248                                                            GtkTreePath     *path,
249                                                            GtkTreeIter     *iter,
250                                                            gpointer         data);
251 static void gtk_tree_view_deleted                         (GtkTreeModel    *model,
252                                                            GtkTreePath     *path,
253                                                            gpointer         data);
254 static void gtk_tree_view_reordered                       (GtkTreeModel    *model,
255                                                            GtkTreePath     *parent,
256                                                            GtkTreeIter     *iter,
257                                                            gint            *new_order,
258                                                            gpointer         data);
259
260
261
262 /* Internal functions */
263 static gboolean gtk_tree_view_is_expander_column   (GtkTreeView      *tree_view,
264                                                     GtkTreeViewColumn*column);
265 static void     gtk_tree_view_add_move_binding     (GtkBindingSet    *binding_set,
266                                                     guint             keyval,
267                                                     guint             modmask,
268                                                     GtkMovementStep   step,
269                                                     gint              count);
270 static gint     gtk_tree_view_unref_and_check_selection_tree (GtkTreeView      *tree_view,
271                                                               GtkRBTree        *tree);
272 static void     gtk_tree_view_queue_draw_node      (GtkTreeView      *tree_view,
273                                                     GtkRBTree        *tree,
274                                                     GtkRBNode        *node,
275                                                     GdkRectangle     *clip_rect);
276 static void     gtk_tree_view_queue_draw_path      (GtkTreeView      *tree_view,
277                                                     GtkTreePath      *path,
278                                                     GdkRectangle     *clip_rect);
279 static void     gtk_tree_view_draw_arrow           (GtkTreeView      *tree_view,
280                                                     GtkRBTree        *tree,
281                                                     GtkRBNode        *node,
282                                                     gint              x,
283                                                     gint              y);
284 static void     gtk_tree_view_get_arrow_xrange     (GtkTreeView      *tree_view,
285                                                     gint              *x1,
286                                                     gint              *x2);
287 static gint     gtk_tree_view_new_column_width     (GtkTreeView      *tree_view,
288                                                     gint              i,
289                                                     gint             *x);
290 static void     gtk_tree_view_ensure_scroll_timeout(GtkTreeView      *tree_view,
291                                                     GFunc             func);
292 static void     gtk_tree_view_adjustment_changed   (GtkAdjustment    *adjustment,
293                                                     GtkTreeView      *tree_view);
294 static gint     gtk_tree_view_insert_iter_height   (GtkTreeView      *tree_view,
295                                                     GtkRBTree        *tree,
296                                                     GtkTreeIter      *iter,
297                                                     gint              depth);
298 static void     gtk_tree_view_build_tree           (GtkTreeView      *tree_view,
299                                                     GtkRBTree        *tree,
300                                                     GtkTreeIter      *iter,
301                                                     gint              depth,
302                                                     gboolean          recurse,
303                                                     gboolean          calc_bounds);
304 static void     gtk_tree_view_calc_size            (GtkTreeView      *priv,
305                                                     GtkRBTree        *tree,
306                                                     GtkTreeIter      *iter,
307                                                     gint              depth);
308 static gboolean gtk_tree_view_discover_dirty_iter  (GtkTreeView      *tree_view,
309                                                     GtkTreeIter      *iter,
310                                                     gint              depth,
311                                                     gint             *height);
312 static void     gtk_tree_view_discover_dirty       (GtkTreeView      *tree_view,
313                                                     GtkRBTree        *tree,
314                                                     GtkTreeIter      *iter,
315                                                     gint              depth);
316 static void     gtk_tree_view_check_dirty          (GtkTreeView      *tree_view);
317 static void     gtk_tree_view_clamp_node_visible   (GtkTreeView      *tree_view,
318                                                     GtkRBTree        *tree,
319                                                     GtkRBNode        *node);
320 static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
321                                                         GdkEventMotion   *event);
322 static void     _gtk_tree_view_update_col_width    (GtkTreeView      *tree_view);
323
324
325 static void gtk_tree_view_focus_to_cursor          (GtkTreeView *tree_view);
326 static void gtk_tree_view_move_cursor_up_down      (GtkTreeView *tree_view,
327                                                     gint         count);
328 static void gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
329                                                     gint         count);
330 static void gtk_tree_view_move_cursor_left_right   (GtkTreeView *tree_view,
331                                                     gint         count);
332 static void gtk_tree_view_move_cursor_start_end    (GtkTreeView *tree_view,
333                                                     gint         count);
334 static gboolean gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
335                                                  GtkTreePath *path,
336                                                  GtkRBTree   *tree,
337                                                  GtkRBNode   *node);
338 static gboolean gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
339                                                GtkTreePath *path,
340                                                GtkRBTree   *tree,
341                                                GtkRBNode   *node,
342                                                gboolean     open_all);
343 static void gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
344                                            GtkTreePath     *path,
345                                            gboolean         clear_and_select);
346
347
348 static GtkContainerClass *parent_class = NULL;
349 static guint tree_view_signals[LAST_SIGNAL] = { 0 };
350
351 \f
352
353 /* GType Methods
354  */
355
356 GtkType
357 gtk_tree_view_get_type (void)
358 {
359   static GtkType tree_view_type = 0;
360
361   if (!tree_view_type)
362     {
363       static const GTypeInfo tree_view_info =
364       {
365         sizeof (GtkTreeViewClass),
366         NULL,           /* base_init */
367         NULL,           /* base_finalize */
368         (GClassInitFunc) gtk_tree_view_class_init,
369         NULL,           /* class_finalize */
370         NULL,           /* class_data */
371         sizeof (GtkTreeView),
372         0,              /* n_preallocs */
373         (GInstanceInitFunc) gtk_tree_view_init
374       };
375
376       tree_view_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView", &tree_view_info, 0);
377     }
378
379   return tree_view_type;
380 }
381
382 static void
383 gtk_tree_view_class_init (GtkTreeViewClass *class)
384 {
385   GObjectClass *o_class;
386   GtkObjectClass *object_class;
387   GtkWidgetClass *widget_class;
388   GtkContainerClass *container_class;
389   GtkBindingSet *binding_set;
390
391   parent_class = g_type_class_peek_parent (class);
392   binding_set = gtk_binding_set_by_class (class);
393
394   o_class = (GObjectClass *) class;
395   object_class = (GtkObjectClass *) class;
396   widget_class = (GtkWidgetClass *) class;
397   container_class = (GtkContainerClass *) class;
398
399   /* GObject signals */
400   o_class->set_property = gtk_tree_view_set_property;
401   o_class->get_property = gtk_tree_view_get_property;
402   o_class->finalize = gtk_tree_view_finalize;
403
404   /* GtkObject signals */
405   object_class->destroy = gtk_tree_view_destroy;
406
407   /* GtkWidget signals */
408   widget_class->map = gtk_tree_view_map;
409   widget_class->realize = gtk_tree_view_realize;
410   widget_class->unrealize = gtk_tree_view_unrealize;
411   widget_class->size_request = gtk_tree_view_size_request;
412   widget_class->size_allocate = gtk_tree_view_size_allocate;
413   widget_class->button_press_event = gtk_tree_view_button_press;
414   widget_class->button_release_event = gtk_tree_view_button_release;
415   widget_class->motion_notify_event = gtk_tree_view_motion;
416   widget_class->expose_event = gtk_tree_view_expose;
417   widget_class->key_press_event = gtk_tree_view_key_press;
418   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
419   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
420   widget_class->focus_in_event = gtk_tree_view_focus_in;
421   widget_class->focus_out_event = gtk_tree_view_focus_out;
422   widget_class->drag_begin = gtk_tree_view_drag_begin;
423   widget_class->drag_end = gtk_tree_view_drag_end;
424   widget_class->drag_data_get = gtk_tree_view_drag_data_get;
425   widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
426   widget_class->drag_leave = gtk_tree_view_drag_leave;
427   widget_class->drag_motion = gtk_tree_view_drag_motion;
428   widget_class->drag_drop = gtk_tree_view_drag_drop;
429   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
430   widget_class->focus = gtk_tree_view_focus;
431
432   /* GtkContainer signals */
433   container_class->remove = gtk_tree_view_remove;
434   container_class->forall = gtk_tree_view_forall;
435   container_class->set_focus_child = gtk_tree_view_set_focus_child;
436
437   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
438   class->begin_extended_selection = gtk_tree_view_real_begin_extended_selection;
439   class->end_extended_selection = gtk_tree_view_real_end_extended_selection;
440   class->begin_free_motion = gtk_tree_view_real_begin_free_motion;
441   class->end_free_motion = gtk_tree_view_real_end_free_motion;
442   class->move_cursor = gtk_tree_view_real_move_cursor;
443   class->select_cursor_row = gtk_tree_view_real_select_cursor_row;
444   class->toggle_cursor_row = gtk_tree_view_real_toggle_cursor_row;
445   class->expand_collapse_cursor_row = gtk_tree_view_real_expand_collapse_cursor_row;
446   class->select_cursor_parent = gtk_tree_view_real_select_cursor_parent;
447
448   /* Properties */
449
450   g_object_class_install_property (o_class,
451                                    PROP_MODEL,
452                                    g_param_spec_object ("model",
453                                                         _("TreeView Model"),
454                                                         _("The model for the tree view"),
455                                                         GTK_TYPE_TREE_MODEL,
456                                                         G_PARAM_READWRITE));
457
458   g_object_class_install_property (o_class,
459                                    PROP_HADJUSTMENT,
460                                    g_param_spec_object ("hadjustment",
461                                                         _("Horizontal Adjustment"),
462                                                         _("Horizontal Adjustment for the widget"),
463                                                         GTK_TYPE_ADJUSTMENT,
464                                                         G_PARAM_READWRITE));
465
466   g_object_class_install_property (o_class,
467                                    PROP_VADJUSTMENT,
468                                    g_param_spec_object ("vadjustment",
469                                                         _("Vertical Adjustment"),
470                                                         _("Vertical Adjustment for the widget"),
471                                                         GTK_TYPE_ADJUSTMENT,
472                                                         G_PARAM_READWRITE));
473
474   g_object_class_install_property (o_class,
475                                    PROP_HEADERS_VISIBLE,
476                                    g_param_spec_boolean ("headers_visible",
477                                                          _("Visible"),
478                                                          _("Show the column header buttons"),
479                                                          FALSE,
480                                                          G_PARAM_READWRITE));
481
482   g_object_class_install_property (o_class,
483                                    PROP_HEADERS_CLICKABLE,
484                                    g_param_spec_boolean ("headers_clickable",
485                                                          _("Headers Clickable"),
486                                                          _("Column headers respond to click events"),
487                                                          FALSE,
488                                                          G_PARAM_WRITABLE));
489
490   g_object_class_install_property (o_class,
491                                    PROP_EXPANDER_COLUMN,
492                                    g_param_spec_object ("expander_column",
493                                                         _("Expander Column"),
494                                                         _("Set the column for the expander column"),
495                                                         GTK_TYPE_TREE_VIEW_COLUMN,
496                                                         G_PARAM_READWRITE));
497
498   g_object_class_install_property (o_class,
499                                    PROP_REORDERABLE,
500                                    g_param_spec_boolean ("reorderable",
501                                                          _("Reorderable"),
502                                                          _("View is reorderable"),
503                                                          FALSE,
504                                                          G_PARAM_READWRITE));
505
506   g_object_class_install_property (o_class,
507                                    PROP_RULES_HINT,
508                                    g_param_spec_boolean ("rules_hint",
509                                                          _("Rules Hint"),
510                                                          _("Set a hint to the theme engine to draw rows in alternating colors"),
511                                                          FALSE,
512                                                          G_PARAM_READWRITE));
513
514   /* Style properties */
515   /* the width of the column resize windows */
516 #define _TREE_VIEW_EXPANDER_WIDTH 14
517 #define _TREE_VIEW_EXPANDER_HEIGHT 14
518 #define _TREE_VIEW_VERTICAL_SEPARATOR 2
519 #define _TREE_VIEW_HORIZONTAL_SEPARATOR 0
520
521   gtk_widget_class_install_style_property (widget_class,
522                                            g_param_spec_int ("expander_width",
523                                                              _("Expander Width"),
524                                                              _("Width of the expander arrow"),
525                                                              0,
526                                                              G_MAXINT,
527                                                              _TREE_VIEW_EXPANDER_WIDTH,
528                                                              G_PARAM_READABLE));
529
530   gtk_widget_class_install_style_property (widget_class,
531                                            g_param_spec_int ("expander_height",
532                                                              _("Expander Height"),
533                                                              _("Height of the expander arrow"),
534                                                              4,
535                                                              G_MAXINT,
536                                                              _TREE_VIEW_EXPANDER_HEIGHT,
537                                                              G_PARAM_READABLE));
538
539     gtk_widget_class_install_style_property (widget_class,
540                                            g_param_spec_int ("vertical_separator",
541                                                              _("Vertical Separator Width"),
542                                                              _("Vertical space between cells"),
543                                                              0,
544                                                              G_MAXINT,
545                                                              _TREE_VIEW_VERTICAL_SEPARATOR,
546                                                              G_PARAM_READABLE));
547
548     gtk_widget_class_install_style_property (widget_class,
549                                            g_param_spec_int ("horizontal_separator",
550                                                              _("Horizontal Separator Width"),
551                                                              _("Horizontal space between cells"),
552                                                              0,
553                                                              G_MAXINT,
554                                                              _TREE_VIEW_HORIZONTAL_SEPARATOR,
555                                                              G_PARAM_READABLE));
556
557   /* Signals */
558   widget_class->set_scroll_adjustments_signal =
559     gtk_signal_new ("set_scroll_adjustments",
560                     GTK_RUN_LAST,
561                     GTK_CLASS_TYPE (object_class),
562                     GTK_SIGNAL_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
563                     gtk_marshal_VOID__OBJECT_OBJECT,
564                     GTK_TYPE_NONE, 2,
565                     GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
566
567   tree_view_signals[ROW_ACTIVATED] =
568     gtk_signal_new ("row_activated",
569                     GTK_RUN_LAST | GTK_RUN_ACTION,
570                     GTK_CLASS_TYPE (object_class),
571                     GTK_SIGNAL_OFFSET (GtkTreeViewClass, row_activated),
572                     gtk_marshal_VOID__BOXED_OBJECT,
573                     GTK_TYPE_NONE, 2,
574                     GTK_TYPE_TREE_PATH,
575                     GTK_TYPE_TREE_VIEW_COLUMN);
576
577   tree_view_signals[TEST_EXPAND_ROW] =
578     g_signal_new ("test_expand_row",
579                   G_TYPE_FROM_CLASS (object_class),
580                   G_SIGNAL_RUN_LAST,
581                   G_STRUCT_OFFSET (GtkTreeViewClass, test_expand_row),
582                   _gtk_boolean_handled_accumulator, NULL,
583                   gtk_marshal_BOOLEAN__BOXED_BOXED,
584                   G_TYPE_BOOLEAN, 2,
585                   GTK_TYPE_TREE_ITER,
586                   GTK_TYPE_TREE_PATH);
587
588   tree_view_signals[TEST_COLLAPSE_ROW] =
589     g_signal_new ("test_collapse_row",
590                   G_TYPE_FROM_CLASS (object_class),
591                   G_SIGNAL_RUN_LAST,
592                   G_STRUCT_OFFSET (GtkTreeViewClass, test_collapse_row),
593                   _gtk_boolean_handled_accumulator, NULL,
594                   gtk_marshal_BOOLEAN__BOXED_BOXED,
595                   G_TYPE_BOOLEAN, 2,
596                   GTK_TYPE_TREE_ITER,
597                   GTK_TYPE_TREE_PATH);
598
599   tree_view_signals[ROW_EXPANDED] =
600     g_signal_new ("row_expanded",
601                   G_TYPE_FROM_CLASS (object_class),
602                   G_SIGNAL_RUN_LAST,
603                   G_STRUCT_OFFSET (GtkTreeViewClass, row_expanded),
604                   NULL, NULL,
605                   gtk_marshal_VOID__BOXED_BOXED,
606                   GTK_TYPE_NONE, 2,
607                   GTK_TYPE_TREE_ITER,
608                   GTK_TYPE_TREE_PATH);
609
610   tree_view_signals[ROW_COLLAPSED] =
611     g_signal_new ("row_collapsed",
612                   G_TYPE_FROM_CLASS (object_class),
613                   G_SIGNAL_RUN_LAST,
614                   G_STRUCT_OFFSET (GtkTreeViewClass, row_collapsed),
615                   NULL, NULL,
616                   gtk_marshal_VOID__BOXED_BOXED,
617                   GTK_TYPE_NONE, 2,
618                   GTK_TYPE_TREE_ITER,
619                   GTK_TYPE_TREE_PATH);
620
621   tree_view_signals[COLUMNS_CHANGED] =
622     g_signal_new ("columns_changed",
623                   G_TYPE_FROM_CLASS (object_class),
624                   G_SIGNAL_RUN_LAST,
625                   G_STRUCT_OFFSET (GtkTreeViewClass, columns_changed),
626                   NULL, NULL,
627                   gtk_marshal_NONE__NONE,
628                   G_TYPE_NONE, 0);
629
630   tree_view_signals[BEGIN_EXTENDED_SELECTION] =
631     g_signal_new ("begin_extended_selection",
632                   G_TYPE_FROM_CLASS (object_class),
633                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
634                   G_STRUCT_OFFSET (GtkTreeViewClass, begin_extended_selection),
635                   NULL, NULL,
636                   gtk_marshal_NONE__NONE,
637                   G_TYPE_NONE, 0);
638
639   tree_view_signals[END_EXTENDED_SELECTION] =
640     g_signal_new ("end_extended_selection",
641                   G_TYPE_FROM_CLASS (object_class),
642                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
643                   G_STRUCT_OFFSET (GtkTreeViewClass, end_extended_selection),
644                   NULL, NULL,
645                   gtk_marshal_NONE__NONE,
646                   G_TYPE_NONE, 0);
647
648   tree_view_signals[BEGIN_FREE_MOTION] =
649     g_signal_new ("begin_free_motion",
650                   G_TYPE_FROM_CLASS (object_class),
651                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
652                   G_STRUCT_OFFSET (GtkTreeViewClass, begin_free_motion),
653                   NULL, NULL,
654                   gtk_marshal_NONE__NONE,
655                   G_TYPE_NONE, 0);
656
657   tree_view_signals[END_FREE_MOTION] =
658     g_signal_new ("end_free_motion",
659                   G_TYPE_FROM_CLASS (object_class),
660                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
661                   G_STRUCT_OFFSET (GtkTreeViewClass, end_free_motion),
662                   NULL, NULL,
663                   gtk_marshal_NONE__NONE,
664                   G_TYPE_NONE, 0);
665
666   tree_view_signals[MOVE_CURSOR] =
667     g_signal_new ("move_cursor",
668                   G_TYPE_FROM_CLASS (object_class),
669                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
670                   G_STRUCT_OFFSET (GtkTreeViewClass, move_cursor),
671                   NULL, NULL,
672                   gtk_marshal_VOID__ENUM_INT,
673                   GTK_TYPE_NONE, 2, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT);
674
675   tree_view_signals[SELECT_CURSOR_ROW] =
676     g_signal_new ("select_cursor_row",
677                   G_TYPE_FROM_CLASS (object_class),
678                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
679                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_row),
680                   NULL, NULL,
681                   gtk_marshal_NONE__NONE,
682                   GTK_TYPE_NONE, 0);
683
684   tree_view_signals[TOGGLE_CURSOR_ROW] =
685     g_signal_new ("toggle_cursor_row",
686                   G_TYPE_FROM_CLASS (object_class),
687                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
688                   G_STRUCT_OFFSET (GtkTreeViewClass, toggle_cursor_row),
689                   NULL, NULL,
690                   gtk_marshal_NONE__NONE,
691                   GTK_TYPE_NONE, 0);
692
693   tree_view_signals[EXPAND_COLLAPSE_CURSOR_ROW] =
694     g_signal_new ("expand_collapse_cursor_row",
695                   G_TYPE_FROM_CLASS (object_class),
696                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
697                   G_STRUCT_OFFSET (GtkTreeViewClass, expand_collapse_cursor_row),
698                   NULL, NULL,
699                   gtk_marshal_VOID__BOOLEAN_BOOLEAN_BOOLEAN,
700                   GTK_TYPE_NONE, 3, GTK_TYPE_BOOL, GTK_TYPE_BOOL, GTK_TYPE_BOOL);
701
702   tree_view_signals[SELECT_CURSOR_PARENT] =
703     g_signal_new ("select_cursor_parent",
704                   G_TYPE_FROM_CLASS (object_class),
705                   G_SIGNAL_RUN_LAST | GTK_RUN_ACTION,
706                   G_STRUCT_OFFSET (GtkTreeViewClass, select_cursor_parent),
707                   NULL, NULL,
708                   gtk_marshal_NONE__NONE,
709                   GTK_TYPE_NONE, 0);
710
711   /* Key bindings */
712   gtk_binding_entry_add_signal (binding_set, GDK_Shift_L, 0, "begin_extended_selection", 0);
713   gtk_binding_entry_add_signal (binding_set, GDK_Shift_L, GDK_SHIFT_MASK | GDK_RELEASE_MASK, "end_extended_selection", 0);
714   gtk_binding_entry_add_signal (binding_set, GDK_Control_L, 0, "begin_free_motion", 0);
715   gtk_binding_entry_add_signal (binding_set, GDK_Control_L, GDK_CONTROL_MASK | GDK_RELEASE_MASK, "end_free_motion", 0);
716   gtk_binding_entry_add_signal (binding_set, GDK_Shift_R, 0, "begin_extended_selection", 0);
717   gtk_binding_entry_add_signal (binding_set, GDK_Shift_R, GDK_SHIFT_MASK | GDK_RELEASE_MASK, "end_extended_selection", 0);
718   gtk_binding_entry_add_signal (binding_set, GDK_Control_R, 0, "begin_free_motion", 0);
719   gtk_binding_entry_add_signal (binding_set, GDK_Control_R, GDK_CONTROL_MASK | GDK_RELEASE_MASK, "end_free_motion", 0);
720
721   gtk_tree_view_add_move_binding (binding_set, GDK_Up, 0,
722                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
723
724   gtk_tree_view_add_move_binding (binding_set, GDK_Down, 0,
725                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
726
727   gtk_tree_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
728                                   GTK_MOVEMENT_DISPLAY_LINES, -1);
729
730   gtk_tree_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
731                                   GTK_MOVEMENT_DISPLAY_LINES, 1);
732
733   gtk_tree_view_add_move_binding (binding_set, GDK_Home, 0,
734                                   GTK_MOVEMENT_BUFFER_ENDS, -1);
735
736   gtk_tree_view_add_move_binding (binding_set, GDK_End, 0,
737                                   GTK_MOVEMENT_BUFFER_ENDS, 1);
738
739   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Up, 0,
740                                   GTK_MOVEMENT_PAGES, -1);
741
742   gtk_tree_view_add_move_binding (binding_set, GDK_Page_Down, 0,
743                                   GTK_MOVEMENT_PAGES, 1);
744
745   gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, "move_cursor", 2,
746                                 GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
747                                 GTK_TYPE_INT, 1);
748
749   gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, "move_cursor", 2,
750                                 GTK_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
751                                 GTK_TYPE_INT, -1);
752
753   gtk_binding_entry_add_signal (binding_set, GDK_f, GDK_CONTROL_MASK, "move_cursor", 2,
754                                 GTK_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
755                                 GTK_TYPE_INT, 1);
756
757   gtk_binding_entry_add_signal (binding_set, GDK_b, GDK_CONTROL_MASK, "move_cursor", 2,
758                                 GTK_TYPE_ENUM, GTK_MOVEMENT_LOGICAL_POSITIONS,
759                                 GTK_TYPE_INT, -1);
760
761   gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_row", 0);
762
763   gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_row", 0);
764
765   /* expand and collapse rows */
766   gtk_binding_entry_add_signal (binding_set, GDK_plus, 0, "expand_collapse_cursor_row", 3,
767                                 GTK_TYPE_BOOL, FALSE,
768                                 GTK_TYPE_BOOL, TRUE,
769                                 GTK_TYPE_BOOL, FALSE);
770   /* Not doable on US keyboards */
771   gtk_binding_entry_add_signal (binding_set, GDK_plus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
772                                 GTK_TYPE_BOOL, FALSE,
773                                 GTK_TYPE_BOOL, TRUE,
774                                 GTK_TYPE_BOOL, TRUE);
775   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, 0, "expand_collapse_cursor_row", 3,
776                                 GTK_TYPE_BOOL, FALSE,
777                                 GTK_TYPE_BOOL, TRUE,
778                                 GTK_TYPE_BOOL, FALSE);
779   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
780                                 GTK_TYPE_BOOL, FALSE,
781                                 GTK_TYPE_BOOL, TRUE,
782                                 GTK_TYPE_BOOL, TRUE);
783   gtk_binding_entry_add_signal (binding_set, GDK_KP_Add, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
784                                 GTK_TYPE_BOOL, FALSE,
785                                 GTK_TYPE_BOOL, TRUE,
786                                 GTK_TYPE_BOOL, TRUE);
787   gtk_binding_entry_add_signal (binding_set, GDK_Right, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
788                                 GTK_TYPE_BOOL, TRUE,
789                                 GTK_TYPE_BOOL, TRUE,
790                                 GTK_TYPE_BOOL, TRUE);
791
792   gtk_binding_entry_add_signal (binding_set, GDK_minus, 0, "expand_collapse_cursor_row", 3,
793                                 GTK_TYPE_BOOL, FALSE,
794                                 GTK_TYPE_BOOL, FALSE,
795                                 GTK_TYPE_BOOL, FALSE);
796   gtk_binding_entry_add_signal (binding_set, GDK_minus, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
797                                 GTK_TYPE_BOOL, FALSE,
798                                 GTK_TYPE_BOOL, FALSE,
799                                 GTK_TYPE_BOOL, TRUE);
800   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, 0, "expand_collapse_cursor_row", 3,
801                                 GTK_TYPE_BOOL, FALSE,
802                                 GTK_TYPE_BOOL, FALSE,
803                                 GTK_TYPE_BOOL, FALSE);
804   gtk_binding_entry_add_signal (binding_set, GDK_KP_Subtract, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
805                                 GTK_TYPE_BOOL, FALSE,
806                                 GTK_TYPE_BOOL, FALSE,
807                                 GTK_TYPE_BOOL, TRUE);
808   gtk_binding_entry_add_signal (binding_set, GDK_Left, GDK_SHIFT_MASK, "expand_collapse_cursor_row", 3,
809                                 GTK_TYPE_BOOL, FALSE,
810                                 GTK_TYPE_BOOL, FALSE,
811                                 GTK_TYPE_BOOL, TRUE);
812
813   gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0, "select_cursor_parent", 0);
814
815 }
816
817 static void
818 gtk_tree_view_init (GtkTreeView *tree_view)
819 {
820   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
821
822   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
823
824   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
825   gtk_widget_style_get (GTK_WIDGET (tree_view), "expander_width", &tree_view->priv->tab_offset, NULL);
826   tree_view->priv->n_columns = 0;
827   tree_view->priv->header_height = 1;
828   tree_view->priv->x_drag = 0;
829   tree_view->priv->drag_pos = -1;
830   tree_view->priv->header_has_focus = FALSE;
831   tree_view->priv->pressed_button = -1;
832   tree_view->priv->press_start_x = -1;
833   tree_view->priv->press_start_y = -1;
834   tree_view->priv->reorderable = FALSE;
835   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
836   tree_view->priv->selection = _gtk_tree_selection_new_with_tree_view (tree_view);
837   _gtk_tree_view_update_size (tree_view);
838 }
839
840 \f
841
842 /* GObject Methods
843  */
844
845 static void
846 gtk_tree_view_set_property (GObject         *object,
847                             guint            prop_id,
848                             const GValue    *value,
849                             GParamSpec      *pspec)
850 {
851   GtkTreeView *tree_view;
852
853   tree_view = GTK_TREE_VIEW (object);
854
855   switch (prop_id)
856     {
857     case PROP_MODEL:
858       gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (g_value_get_object (value)));
859       break;
860     case PROP_HADJUSTMENT:
861       gtk_tree_view_set_hadjustment (tree_view, GTK_ADJUSTMENT (g_value_get_object (value)));
862       break;
863     case PROP_VADJUSTMENT:
864       gtk_tree_view_set_vadjustment (tree_view, GTK_ADJUSTMENT (g_value_get_object (value)));
865       break;
866     case PROP_HEADERS_VISIBLE:
867       gtk_tree_view_set_headers_visible (tree_view, g_value_get_boolean (value));
868       break;
869     case PROP_HEADERS_CLICKABLE:
870       gtk_tree_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
871       break;
872     case PROP_EXPANDER_COLUMN:
873       gtk_tree_view_set_expander_column (tree_view, GTK_TREE_VIEW_COLUMN (g_value_get_object (value)));
874       break;
875     case PROP_REORDERABLE:
876       gtk_tree_view_set_reorderable (tree_view, g_value_get_boolean (value));
877       break;
878     case PROP_RULES_HINT:
879       gtk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
880       break;
881     default:
882       break;
883     }
884 }
885
886 static void
887 gtk_tree_view_get_property (GObject         *object,
888                             guint            prop_id,
889                             GValue          *value,
890                             GParamSpec      *pspec)
891 {
892   GtkTreeView *tree_view;
893
894   tree_view = GTK_TREE_VIEW (object);
895
896   switch (prop_id)
897     {
898     case PROP_MODEL:
899       g_value_set_object (value, G_OBJECT (tree_view->priv->model));
900       break;
901     case PROP_HADJUSTMENT:
902       g_value_set_object (value, G_OBJECT (tree_view->priv->hadjustment));
903       break;
904     case PROP_VADJUSTMENT:
905       g_value_set_object (value, G_OBJECT (tree_view->priv->vadjustment));
906       break;
907     case PROP_HEADERS_VISIBLE:
908       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
909       break;
910     case PROP_EXPANDER_COLUMN:
911       g_value_set_object (value, G_OBJECT (tree_view->priv->expander_column));
912       break;
913     case PROP_REORDERABLE:
914       g_value_set_boolean (value, tree_view->priv->reorderable);
915       break;
916     case PROP_RULES_HINT:
917       g_value_set_boolean (value, tree_view->priv->has_rules);
918       break;
919     default:
920       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
921       break;
922     }
923 }
924
925 static void
926 gtk_tree_view_finalize (GObject *object)
927 {
928   GtkTreeView *tree_view = (GtkTreeView *) object;
929
930   g_free (tree_view->priv);
931
932   if (G_OBJECT_CLASS (parent_class)->finalize)
933     (* G_OBJECT_CLASS (parent_class)->finalize) (object);
934 }
935
936 \f
937
938 /* GtkObject Methods
939  */
940
941 static void
942 gtk_tree_view_destroy (GtkObject *object)
943 {
944   GtkTreeView *tree_view = (GtkTreeView *) object;
945   GList *list;
946
947
948   if (tree_view->priv->tree != NULL)
949     {
950       gtk_tree_view_unref_and_check_selection_tree (tree_view, tree_view->priv->tree);
951       _gtk_rbtree_free (tree_view->priv->tree);
952       tree_view->priv->tree = NULL;
953     }
954
955   if (tree_view->priv->model != NULL)
956     {
957       g_object_unref (G_OBJECT (tree_view->priv->model));
958       tree_view->priv->model = NULL;
959     }
960
961   if (tree_view->priv->columns != NULL)
962     {
963       for (list = tree_view->priv->columns; list; list = list->next)
964         g_object_unref (G_OBJECT (list->data));
965       g_list_free (tree_view->priv->columns);
966       tree_view->priv->columns = NULL;
967     }
968
969   if (tree_view->priv->selection != NULL)
970     {
971       _gtk_tree_selection_set_tree_view (tree_view->priv->selection, NULL);
972       g_object_unref (tree_view->priv->selection);
973       tree_view->priv->selection = NULL;
974     }
975
976   if (tree_view->priv->scroll_to_path != NULL)
977     {
978       gtk_tree_path_free (tree_view->priv->scroll_to_path);
979       tree_view->priv->scroll_to_path = NULL;
980     }
981
982   if (tree_view->priv->drag_dest_row != NULL)
983     {
984       gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
985       tree_view->priv->drag_dest_row = NULL;
986     }
987
988   
989   if (tree_view->priv->column_drop_func_data &&
990       tree_view->priv->column_drop_func_data_destroy)
991     {
992       (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
993       tree_view->priv->column_drop_func_data = NULL;
994     }
995
996   if (tree_view->priv->destroy_count_destroy &&
997       tree_view->priv->destroy_count_data)
998     {
999       (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
1000       tree_view->priv->destroy_count_data = NULL;
1001     }
1002
1003   gtk_tree_row_reference_free (tree_view->priv->cursor);
1004   tree_view->priv->cursor = NULL;
1005
1006   gtk_tree_row_reference_free (tree_view->priv->anchor);
1007   tree_view->priv->anchor = NULL;
1008
1009   if (GTK_OBJECT_CLASS (parent_class)->destroy)
1010     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
1011 }
1012
1013 \f
1014
1015 /* GtkWidget Methods
1016  */
1017
1018 /* GtkWidget::map helper */
1019 static void
1020 gtk_tree_view_map_buttons (GtkTreeView *tree_view)
1021 {
1022   GList *list;
1023
1024   g_return_if_fail (GTK_WIDGET_MAPPED (tree_view));
1025
1026   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
1027     {
1028       GtkTreeViewColumn *column;
1029
1030       for (list = tree_view->priv->columns; list; list = list->next)
1031         {
1032           column = list->data;
1033           if (GTK_WIDGET_VISIBLE (column->button) &&
1034               !GTK_WIDGET_MAPPED (column->button))
1035             gtk_widget_map (column->button);
1036         }
1037       for (list = tree_view->priv->columns; list; list = list->next)
1038         {
1039           column = list->data;
1040           if (column->visible == FALSE)
1041             continue;
1042           if (column->column_type == GTK_TREE_VIEW_COLUMN_RESIZABLE)
1043             {
1044               gdk_window_raise (column->window);
1045               gdk_window_show (column->window);
1046             }
1047           else
1048             gdk_window_hide (column->window);
1049         }
1050       gdk_window_show (tree_view->priv->header_window);
1051     }
1052 }
1053
1054 static void
1055 gtk_tree_view_map (GtkWidget *widget)
1056 {
1057   GList *tmp_list;
1058   GtkTreeView *tree_view;
1059
1060   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1061
1062   tree_view = GTK_TREE_VIEW (widget);
1063
1064   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1065
1066   tmp_list = tree_view->priv->children;
1067   while (tmp_list)
1068     {
1069       GtkTreeViewChild *child = tmp_list->data;
1070       tmp_list = tmp_list->next;
1071
1072       if (GTK_WIDGET_VISIBLE (child->widget))
1073         {
1074           if (!GTK_WIDGET_MAPPED (child->widget))
1075             gtk_widget_map (child->widget);
1076         }
1077     }
1078   gdk_window_show (tree_view->priv->bin_window);
1079
1080   gtk_tree_view_map_buttons (tree_view);
1081
1082   gdk_window_show (widget->window);
1083 }
1084
1085 static void
1086 gtk_tree_view_realize (GtkWidget *widget)
1087 {
1088   GList *tmp_list;
1089   GtkTreeView *tree_view;
1090   GdkGCValues values;
1091   GdkWindowAttr attributes;
1092   gint attributes_mask;
1093
1094   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1095
1096   tree_view = GTK_TREE_VIEW (widget);
1097
1098   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
1099   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
1100
1101   /* Make the main, clipping window */
1102   attributes.window_type = GDK_WINDOW_CHILD;
1103   attributes.x = widget->allocation.x;
1104   attributes.y = widget->allocation.y;
1105   attributes.width = widget->allocation.width;
1106   attributes.height = widget->allocation.height;
1107   attributes.wclass = GDK_INPUT_OUTPUT;
1108   attributes.visual = gtk_widget_get_visual (widget);
1109   attributes.colormap = gtk_widget_get_colormap (widget);
1110   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
1111
1112   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1113
1114   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
1115                                    &attributes, attributes_mask);
1116   gdk_window_set_user_data (widget->window, widget);
1117
1118   /* Make the window for the tree */
1119   attributes.x = 0;
1120   attributes.y = 0;
1121   attributes.width = tree_view->priv->width;
1122   attributes.height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
1123   attributes.event_mask = GDK_EXPOSURE_MASK |
1124     GDK_SCROLL_MASK |
1125     GDK_POINTER_MOTION_MASK |
1126     GDK_ENTER_NOTIFY_MASK |
1127     GDK_LEAVE_NOTIFY_MASK |
1128     GDK_BUTTON_PRESS_MASK |
1129     GDK_BUTTON_RELEASE_MASK |
1130     gtk_widget_get_events (widget);
1131
1132   tree_view->priv->bin_window = gdk_window_new (widget->window,
1133                                                 &attributes, attributes_mask);
1134   gdk_window_set_user_data (tree_view->priv->bin_window, widget);
1135
1136   /* Make the column header window */
1137   attributes.x = 0;
1138   attributes.y = 0;
1139   attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
1140   attributes.height = tree_view->priv->header_height;
1141   attributes.event_mask = (GDK_EXPOSURE_MASK |
1142                            GDK_SCROLL_MASK |
1143                            GDK_BUTTON_PRESS_MASK |
1144                            GDK_BUTTON_RELEASE_MASK |
1145                            GDK_KEY_PRESS_MASK |
1146                            GDK_KEY_RELEASE_MASK) |
1147     gtk_widget_get_events (widget);
1148
1149   tree_view->priv->header_window = gdk_window_new (widget->window,
1150                                                    &attributes, attributes_mask);
1151   gdk_window_set_user_data (tree_view->priv->header_window, widget);
1152
1153
1154   values.foreground = (widget->style->white.pixel==0 ?
1155                        widget->style->black:widget->style->white);
1156   values.function = GDK_XOR;
1157   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1158   tree_view->priv->xor_gc = gdk_gc_new_with_values (widget->window,
1159                                                     &values,
1160                                                     GDK_GC_FOREGROUND |
1161                                                     GDK_GC_FUNCTION |
1162                                                     GDK_GC_SUBWINDOW);
1163   /* Add them all up. */
1164   widget->style = gtk_style_attach (widget->style, widget->window);
1165   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
1166   gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
1167   gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
1168
1169   tmp_list = tree_view->priv->children;
1170   while (tmp_list)
1171     {
1172       GtkTreeViewChild *child = tmp_list->data;
1173       tmp_list = tmp_list->next;
1174
1175       gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
1176     }
1177
1178   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1179     _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data));
1180
1181   _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
1182
1183   if (tree_view->priv->scroll_to_path != NULL ||
1184       tree_view->priv->scroll_to_column != NULL)
1185     {
1186       gtk_tree_view_scroll_to_cell (tree_view,
1187                                     tree_view->priv->scroll_to_path,
1188                                     tree_view->priv->scroll_to_column,
1189                                     tree_view->priv->scroll_to_row_align,
1190                                     tree_view->priv->scroll_to_col_align);
1191       if (tree_view->priv->scroll_to_path)
1192         {
1193           gtk_tree_path_free (tree_view->priv->scroll_to_path);
1194           tree_view->priv->scroll_to_path = NULL;
1195         }
1196       tree_view->priv->scroll_to_column = NULL;
1197     }
1198 }
1199
1200 static void
1201 gtk_tree_view_unrealize (GtkWidget *widget)
1202 {
1203   GtkTreeView *tree_view;
1204   GList *list;
1205
1206   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1207
1208   tree_view = GTK_TREE_VIEW (widget);
1209
1210   if (tree_view->priv->scroll_timeout != 0)
1211     {
1212       gtk_timeout_remove (tree_view->priv->scroll_timeout);
1213       tree_view->priv->scroll_timeout = 0;
1214     }
1215
1216   if (tree_view->priv->open_dest_timeout != 0)
1217     {
1218       gtk_timeout_remove (tree_view->priv->open_dest_timeout);
1219       tree_view->priv->open_dest_timeout = 0;
1220     }
1221
1222   for (list = tree_view->priv->columns; list; list = list->next)
1223     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
1224
1225   gdk_window_set_user_data (tree_view->priv->bin_window, NULL);
1226   gdk_window_destroy (tree_view->priv->bin_window);
1227   tree_view->priv->bin_window = NULL;
1228
1229   gdk_window_set_user_data (tree_view->priv->header_window, NULL);
1230   gdk_window_destroy (tree_view->priv->header_window);
1231   tree_view->priv->header_window = NULL;
1232
1233   if (tree_view->priv->drag_window)
1234     {
1235       gdk_window_set_user_data (tree_view->priv->drag_window, NULL);
1236       gdk_window_destroy (tree_view->priv->drag_window);
1237       tree_view->priv->drag_window = NULL;
1238     }
1239
1240   if (tree_view->priv->drag_highlight_window)
1241     {
1242       gdk_window_set_user_data (tree_view->priv->drag_highlight_window, NULL);
1243       gdk_window_destroy (tree_view->priv->drag_highlight_window);
1244       tree_view->priv->drag_highlight_window = NULL;
1245     }
1246
1247   if (tree_view->priv->cursor_drag)
1248     {
1249       gdk_cursor_destroy (tree_view->priv->cursor_drag);
1250       tree_view->priv->cursor_drag = NULL;
1251     }
1252
1253   if (tree_view->priv->xor_gc)
1254     {
1255       gdk_gc_destroy (tree_view->priv->xor_gc);
1256       tree_view->priv->xor_gc = NULL;
1257     }
1258
1259   /* GtkWidget::unrealize destroys children and widget->window */
1260   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
1261     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
1262 }
1263
1264 /* GtkWidget::size_request helper */
1265 static void
1266 gtk_tree_view_size_request_buttons (GtkTreeView *tree_view)
1267 {
1268   GList *list;
1269
1270   tree_view->priv->header_height = 1;
1271
1272   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
1273     {
1274       for (list = tree_view->priv->columns; list; list = list->next)
1275         {
1276           GtkRequisition requisition;
1277           GtkTreeViewColumn *column = list->data;
1278
1279           if (column->button == NULL)
1280             continue;
1281
1282           column = list->data;
1283
1284           gtk_widget_size_request (column->button, &requisition);
1285
1286           _gtk_tree_view_column_set_width (column, MAX (column->width, requisition.width));
1287           tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
1288         }
1289     }
1290 }
1291
1292 static void
1293 gtk_tree_view_size_request (GtkWidget      *widget,
1294                             GtkRequisition *requisition)
1295 {
1296   GtkTreeView *tree_view;
1297   GList *tmp_list;
1298
1299   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1300
1301   tree_view = GTK_TREE_VIEW (widget);
1302
1303   requisition->width = tree_view->priv->width;
1304   requisition->height = tree_view->priv->height + tree_view->priv->header_height;
1305
1306   tmp_list = tree_view->priv->children;
1307
1308   while (tmp_list)
1309     {
1310       GtkTreeViewChild *child = tmp_list->data;
1311       GtkRequisition child_requisition;
1312
1313       tmp_list = tmp_list->next;
1314
1315       if (GTK_WIDGET_VISIBLE (child->widget))
1316         gtk_widget_size_request (child->widget, &child_requisition);
1317     }
1318
1319   gtk_tree_view_size_request_buttons (tree_view);
1320 }
1321
1322 /* GtkWidget::size_allocate helper */
1323 static void
1324 gtk_tree_view_size_allocate_buttons (GtkWidget *widget)
1325 {
1326   GtkTreeView *tree_view;
1327   GList *list;
1328   GtkTreeViewColumn *column;
1329   GtkAllocation allocation;
1330   gint width = 0;
1331
1332   tree_view = GTK_TREE_VIEW (widget);
1333
1334   allocation.y = 0;
1335   allocation.height = tree_view->priv->header_height;
1336
1337   for (list = tree_view->priv->columns; list != NULL; list = list->next)
1338     {
1339       column = list->data;
1340
1341       if (!column->visible)
1342         continue;
1343
1344       allocation.x = width;
1345       allocation.width = column->displayed_width;
1346       width += column->width;
1347       gtk_widget_size_allocate (column->button, &allocation);
1348
1349       if (column->window)
1350         gdk_window_move_resize (column->window,
1351                                 allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
1352                                 allocation.y,
1353                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
1354     }
1355 }
1356
1357 static void
1358 gtk_tree_view_size_allocate (GtkWidget     *widget,
1359                              GtkAllocation *allocation)
1360 {
1361   GList *tmp_list;
1362   GtkTreeView *tree_view;
1363
1364   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1365
1366   widget->allocation = *allocation;
1367
1368   tree_view = GTK_TREE_VIEW (widget);
1369
1370   gtk_tree_view_check_dirty (tree_view);
1371
1372   tmp_list = tree_view->priv->children;
1373
1374   while (tmp_list)
1375     {
1376       GtkAllocation allocation;
1377       GtkRequisition requisition;
1378
1379       GtkTreeViewChild *child = tmp_list->data;
1380       tmp_list = tmp_list->next;
1381
1382       allocation.x = child->x;
1383       allocation.y = child->y;
1384       gtk_widget_get_child_requisition (child->widget, &requisition);
1385       allocation.width = requisition.width;
1386       allocation.height = requisition.height;
1387
1388       gtk_widget_size_allocate (child->widget, &allocation);
1389     }
1390
1391   if (GTK_WIDGET_REALIZED (widget))
1392     {
1393       gdk_window_move_resize (widget->window,
1394                               allocation->x, allocation->y,
1395                               allocation->width, allocation->height);
1396       gdk_window_resize (tree_view->priv->header_window,
1397                          MAX (tree_view->priv->width, allocation->width),
1398                          tree_view->priv->header_height);
1399       if (tree_view->priv->width < allocation->width)
1400           gdk_window_resize (tree_view->priv->bin_window,
1401                              allocation->width,
1402                              tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view));
1403
1404       _gtk_tree_view_update_col_width (tree_view);
1405     }
1406
1407   gtk_tree_view_size_allocate_buttons (widget);
1408
1409   tree_view->priv->hadjustment->page_size = allocation->width;
1410   tree_view->priv->hadjustment->page_increment = allocation->width;
1411   tree_view->priv->hadjustment->step_increment = allocation->width / 10;
1412   tree_view->priv->hadjustment->lower = 0;
1413   tree_view->priv->hadjustment->upper = tree_view->priv->width;
1414
1415   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
1416     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
1417   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
1418
1419   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
1420   tree_view->priv->vadjustment->step_increment = (tree_view->priv->vadjustment->page_size) / 10;
1421   tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
1422   tree_view->priv->vadjustment->lower = 0;
1423   tree_view->priv->vadjustment->upper = tree_view->priv->height;
1424
1425   if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height)
1426     gtk_adjustment_set_value (tree_view->priv->vadjustment,
1427                               MAX (tree_view->priv->height - allocation->height, 0));
1428
1429   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
1430
1431 }
1432
1433 static gboolean
1434 gtk_tree_view_button_press (GtkWidget      *widget,
1435                             GdkEventButton *event)
1436 {
1437   GtkTreeView *tree_view;
1438   GList *list;
1439   GtkTreeViewColumn *column = NULL;
1440   gint i;
1441   GdkRectangle background_area;
1442   GdkRectangle cell_area;
1443   gint vertical_separator;
1444
1445   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1446   g_return_val_if_fail (event != NULL, FALSE);
1447
1448   tree_view = GTK_TREE_VIEW (widget);
1449   gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
1450
1451   if (event->window == tree_view->priv->bin_window)
1452     {
1453       GtkRBNode *node;
1454       GtkRBTree *tree;
1455       GtkTreePath *path;
1456       gchar *path_string;
1457       gint depth;
1458       gint new_y;
1459       gint y_offset;
1460       GtkTreeViewColumn *column = NULL;
1461
1462       if (!GTK_WIDGET_HAS_FOCUS (widget))
1463         gtk_widget_grab_focus (widget);
1464       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1465
1466       /* are we in an arrow? */
1467       if (tree_view->priv->prelight_node &&
1468           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1469         {
1470           if (event->button == 1)
1471             {
1472               gtk_grab_add (widget);
1473               tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
1474               tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
1475               gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
1476                                         tree_view->priv->prelight_tree,
1477                                         tree_view->priv->prelight_node,
1478                                         event->x,
1479                                         event->y);
1480             }
1481           return TRUE;
1482         }
1483
1484       /* find the node that was clicked */
1485       new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1486       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
1487                                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
1488                                            &tree,
1489                                            &node) + new_y - (gint)event->y;
1490
1491       if (node == NULL)
1492         /* We clicked in dead space */
1493         return TRUE;
1494
1495       /* Get the path and the node */
1496       path = _gtk_tree_view_find_path (tree_view, tree, node);
1497       depth = gtk_tree_path_get_depth (path);
1498       background_area.y = y_offset + event->y + vertical_separator;
1499       background_area.height = GTK_RBNODE_GET_HEIGHT (node) - vertical_separator;
1500       background_area.x = 0;
1501
1502       /* Let the column have a chance at selecting it. */
1503       for (list = tree_view->priv->columns; list; list = list->next)
1504         {
1505           GtkTreeIter iter;
1506
1507           column = list->data;
1508
1509           if (!column->visible)
1510             continue;
1511
1512           background_area.width = column->displayed_width;
1513           if (gtk_tree_view_is_expander_column (tree_view, column) &&
1514               TREE_VIEW_DRAW_EXPANDERS(tree_view))
1515             {
1516               cell_area = background_area;
1517               cell_area.x += depth*tree_view->priv->tab_offset;
1518               cell_area.width -= depth*tree_view->priv->tab_offset;
1519             }
1520           else
1521             {
1522               cell_area = background_area;
1523             }
1524
1525           if ((background_area.x > (gint) event->x) ||
1526               (background_area.y > (gint) event->y) ||
1527               (background_area.x + background_area.width <= (gint) event->x) ||
1528               (background_area.y + background_area.height <= (gint) event->y))
1529             {
1530               background_area.x += background_area.width;
1531               continue;
1532             }
1533
1534           gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
1535           gtk_tree_view_column_cell_set_cell_data (column,
1536                                                    tree_view->priv->model,
1537                                                    &iter);
1538
1539           path_string = gtk_tree_path_to_string (path);
1540
1541           if (gtk_tree_view_column_cell_event (column,
1542                                                (GdkEvent *)event,
1543                                                path_string,
1544                                                &background_area,
1545                                                &cell_area, 0))
1546             {
1547               g_free (path_string);
1548               gtk_tree_path_free (path);
1549               return TRUE;
1550             }
1551           else
1552             {
1553               g_free (path_string);
1554               break;
1555             }
1556         }
1557
1558       if (column == NULL)
1559         return FALSE;
1560
1561       /* The columns didn't want the event.  We handle it */
1562
1563       /* Save press to possibly begin a drag
1564        */
1565       if (tree_view->priv->pressed_button < 0)
1566         {
1567           tree_view->priv->pressed_button = event->button;
1568           tree_view->priv->press_start_x = event->x;
1569           tree_view->priv->press_start_y = event->y;
1570         }
1571
1572       gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
1573
1574       if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1575         {
1576           if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
1577             {
1578               if (node->children == NULL)
1579                 gtk_tree_view_real_expand_row (tree_view, path,
1580                                                tree, node, FALSE);
1581               else
1582                 gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
1583                                                  tree, node);
1584             }
1585           gtk_tree_view_row_activated (tree_view, path, column);
1586
1587         }
1588       gtk_tree_path_free (path);
1589       return TRUE;
1590     }
1591
1592   /* We didn't click in the window.  Let's check to see if we clicked on a column resize window.
1593    */
1594   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
1595     {
1596       column = list->data;
1597       if (event->window == column->window &&
1598           column->column_type == GTK_TREE_VIEW_COLUMN_RESIZABLE &&
1599           column->window)
1600         {
1601           gpointer drag_data;
1602
1603           if (gdk_pointer_grab (column->window, FALSE,
1604                                 GDK_POINTER_MOTION_HINT_MASK |
1605                                 GDK_BUTTON1_MOTION_MASK |
1606                                 GDK_BUTTON_RELEASE_MASK,
1607                                 NULL, NULL, event->time))
1608             return FALSE;
1609
1610           gtk_grab_add (widget);
1611           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1612
1613           /* block attached dnd signal handler */
1614           drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1615           if (drag_data)
1616             gtk_signal_handler_block_by_data (GTK_OBJECT (widget), drag_data);
1617
1618           if (!GTK_WIDGET_HAS_FOCUS (widget))
1619             gtk_widget_grab_focus (widget);
1620
1621           tree_view->priv->drag_pos = i;
1622           tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
1623         }
1624     }
1625   return TRUE;
1626 }
1627
1628 /* GtkWidget::button_release_event helper */
1629 static gboolean
1630 gtk_tree_view_button_release_drag_column (GtkWidget      *widget,
1631                                           GdkEventButton *event)
1632 {
1633   GtkTreeView *tree_view;
1634   GtkAllocation allocation;
1635
1636   tree_view = GTK_TREE_VIEW (widget);
1637
1638   allocation = tree_view->priv->drag_column->button->allocation;
1639   allocation.x = tree_view->priv->drag_column_x;
1640   gdk_pointer_ungrab (GDK_CURRENT_TIME);
1641   gdk_keyboard_ungrab (GDK_CURRENT_TIME);
1642   gdk_window_reparent (tree_view->priv->drag_column->button->window,
1643                        tree_view->priv->header_window,
1644                        tree_view->priv->drag_column_x,
1645                        tree_view->priv->drag_column->button->allocation.y);
1646   gtk_widget_set_parent_window (tree_view->priv->drag_column->button, tree_view->priv->header_window);
1647
1648   gtk_widget_size_allocate (tree_view->priv->drag_column->button, &allocation);
1649   gtk_widget_grab_focus (tree_view->priv->drag_column->button);
1650
1651   if (tree_view->priv->cur_reorder &&
1652       tree_view->priv->cur_reorder->left_column != tree_view->priv->drag_column)
1653     gtk_tree_view_move_column_after (tree_view, tree_view->priv->drag_column,
1654                                      tree_view->priv->cur_reorder->left_column);
1655   tree_view->priv->drag_column = NULL;
1656   gdk_window_hide (tree_view->priv->drag_window);
1657
1658   g_list_foreach (tree_view->priv->column_drag_info, (GFunc) g_free, NULL);
1659   g_list_free (tree_view->priv->column_drag_info);
1660   tree_view->priv->column_drag_info = NULL;
1661
1662   gdk_window_hide (tree_view->priv->drag_highlight_window);
1663
1664   /* Reset our flags */
1665   tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
1666   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG);
1667
1668   return TRUE;
1669 }
1670
1671 /* GtkWidget::button_release_event helper */
1672 static gboolean
1673 gtk_tree_view_button_release_column_resize (GtkWidget      *widget,
1674                                             GdkEventButton *event)
1675 {
1676   GtkTreeView *tree_view;
1677   gpointer drag_data;
1678   gint width;
1679   gint x;
1680   gint i;
1681
1682   tree_view = GTK_TREE_VIEW (widget);
1683
1684   i = tree_view->priv->drag_pos;
1685   tree_view->priv->drag_pos = -1;
1686
1687       /* unblock attached dnd signal handler */
1688   drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1689   if (drag_data)
1690     gtk_signal_handler_unblock_by_data (GTK_OBJECT (widget), drag_data);
1691
1692   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1693   gtk_widget_get_pointer (widget, &x, NULL);
1694   gtk_grab_remove (widget);
1695   gdk_pointer_ungrab (event->time);
1696
1697   width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), i, &x);
1698   _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i), width);
1699
1700   return TRUE;
1701 }
1702
1703 static gboolean
1704 gtk_tree_view_button_release (GtkWidget      *widget,
1705                               GdkEventButton *event)
1706 {
1707   GtkTreeView *tree_view;
1708
1709   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1710   g_return_val_if_fail (event != NULL, FALSE);
1711
1712   tree_view = GTK_TREE_VIEW (widget);
1713
1714   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
1715     return gtk_tree_view_button_release_drag_column (widget, event);
1716
1717   if (tree_view->priv->pressed_button == event->button)
1718     tree_view->priv->pressed_button = -1;
1719
1720   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
1721     return gtk_tree_view_button_release_column_resize (widget, event);
1722
1723   if (tree_view->priv->button_pressed_node == NULL)
1724     return FALSE;
1725
1726   if (event->button == 1)
1727     {
1728       gtk_grab_remove (widget);
1729       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
1730           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1731         {
1732           GtkTreePath *path = NULL;
1733
1734           path = _gtk_tree_view_find_path (tree_view,
1735                                            tree_view->priv->button_pressed_tree,
1736                                            tree_view->priv->button_pressed_node);
1737           /* Actually activate the node */
1738           if (tree_view->priv->button_pressed_node->children == NULL)
1739             gtk_tree_view_real_expand_row (tree_view, path,
1740                                            tree_view->priv->button_pressed_tree,
1741                                            tree_view->priv->button_pressed_node,
1742                                            FALSE);
1743           else
1744             gtk_tree_view_real_collapse_row (GTK_TREE_VIEW (widget), path,
1745                                              tree_view->priv->button_pressed_tree,
1746                                              tree_view->priv->button_pressed_node);
1747           gtk_tree_path_free (path);
1748         }
1749
1750       tree_view->priv->button_pressed_tree = NULL;
1751       tree_view->priv->button_pressed_node = NULL;
1752     }
1753
1754   return TRUE;
1755 }
1756
1757
1758 /* GtkWidget::motion_event function set.
1759  */
1760
1761 static gboolean
1762 coords_are_over_arrow (GtkTreeView *tree_view,
1763                        GtkRBTree   *tree,
1764                        GtkRBNode   *node,
1765                        /* these are in tree window coords */
1766                        gint         x,
1767                        gint         y)
1768 {
1769   GdkRectangle arrow;
1770   gint x2;
1771
1772   if (!GTK_WIDGET_REALIZED (tree_view))
1773     return FALSE;
1774
1775   if ((node->flags & GTK_RBNODE_IS_PARENT) == 0)
1776     return FALSE;
1777
1778   arrow.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
1779
1780   arrow.height = BACKGROUND_HEIGHT (node);
1781
1782   gtk_tree_view_get_arrow_xrange (tree_view, &arrow.x, &x2);
1783
1784   arrow.width = x2 - arrow.x;
1785
1786   return (x >= arrow.x &&
1787           x < (arrow.x + arrow.height) &&
1788           y >= arrow.y &&
1789           y < (arrow.y + arrow.height));
1790 }
1791
1792 static void
1793 do_unprelight (GtkTreeView *tree_view,
1794                /* these are in tree window coords */
1795                gint x,
1796                gint y)
1797 {
1798   if (tree_view->priv->prelight_node == NULL)
1799     return;
1800
1801   GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
1802
1803   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) &&
1804       !coords_are_over_arrow (tree_view,
1805                               tree_view->priv->prelight_tree,
1806                               tree_view->priv->prelight_node,
1807                               x,
1808                               y))
1809     /* We need to unprelight the old arrow. */
1810     {
1811       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1812
1813       gtk_tree_view_draw_arrow (tree_view,
1814                                 tree_view->priv->prelight_tree,
1815                                 tree_view->priv->prelight_node,
1816                                 x,
1817                                 y);
1818
1819     }
1820
1821   tree_view->priv->prelight_node = NULL;
1822   tree_view->priv->prelight_tree = NULL;
1823 }
1824
1825 static void
1826 do_prelight (GtkTreeView *tree_view,
1827              GtkRBTree   *tree,
1828              GtkRBNode   *node,
1829              /* these are in tree window coords */
1830              gint         x,
1831              gint         y)
1832 {
1833   if (coords_are_over_arrow (tree_view, tree, node, x, y))
1834     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1835
1836   tree_view->priv->prelight_node = node;
1837   tree_view->priv->prelight_tree = tree;
1838
1839   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
1840 }
1841
1842 static void
1843 ensure_unprelighted (GtkTreeView *tree_view)
1844 {
1845   do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
1846   g_assert (tree_view->priv->prelight_node == NULL);
1847 }
1848
1849
1850
1851 /* Our motion arrow is either a box (in the case of the original spot)
1852  * or an arrow.  It is expander_width wide.
1853  */
1854 /*
1855  * 11111111111111
1856  * 01111111111110
1857  * 00111111111100
1858  * 00011111111000
1859  * 00001111110000
1860  * 00000111100000
1861  * 00000111100000
1862  * 00000111100000
1863  * ~ ~ ~ ~ ~ ~ ~
1864  * 00000111100000
1865  * 00000111100000
1866  * 00000111100000
1867  * 00001111110000
1868  * 00011111111000
1869  * 00111111111100
1870  * 01111111111110
1871  * 11111111111111
1872  */
1873
1874 static void
1875 gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
1876 {
1877   GtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder;
1878   GtkWidget *widget = GTK_WIDGET (tree_view);
1879   GdkBitmap *mask = NULL;
1880   gint x;
1881   gint y;
1882   gint width;
1883   gint height;
1884   gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
1885   GdkWindowAttr attributes;
1886   guint attributes_mask;
1887
1888   if (!reorder ||
1889       reorder->left_column == tree_view->priv->drag_column ||
1890       reorder->right_column == tree_view->priv->drag_column)
1891     arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
1892   else if (reorder->left_column || reorder->right_column)
1893     {
1894       GdkRectangle visible_rect;
1895       gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
1896       if (reorder->left_column)
1897         x = reorder->left_column->button->allocation.x + reorder->left_column->button->allocation.width;
1898       else
1899         x = reorder->right_column->button->allocation.x;
1900       if (x < visible_rect.x)
1901         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
1902       else if (x > visible_rect.x + visible_rect.width)
1903         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
1904       else
1905         arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
1906     }
1907
1908   /* We want to draw the rectangle over the initial location. */
1909   if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
1910     {
1911       GdkGC *gc;
1912       GdkColor col;
1913
1914       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
1915         {
1916
1917           if (tree_view->priv->drag_highlight_window)
1918             gdk_window_destroy (tree_view->priv->drag_highlight_window);
1919
1920           attributes.window_type = GDK_WINDOW_CHILD;
1921           attributes.wclass = GDK_INPUT_OUTPUT;
1922           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
1923           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
1924           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
1925           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1926           tree_view->priv->drag_highlight_window = gdk_window_new (tree_view->priv->header_window, &attributes, attributes_mask);
1927           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
1928
1929           width = tree_view->priv->drag_column->button->allocation.width;
1930           height = tree_view->priv->drag_column->button->allocation.height;
1931           gdk_window_move_resize (tree_view->priv->drag_highlight_window,
1932                                   tree_view->priv->drag_column_x, 0, width, height);
1933
1934           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
1935           gc = gdk_gc_new (mask);
1936           col.pixel = 1;
1937           gdk_gc_set_foreground (gc, &col);
1938           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
1939           col.pixel = 0;
1940           gdk_gc_set_foreground(gc, &col);
1941           gdk_draw_rectangle (mask, gc, TRUE, 2, 2, width - 4, height - 4);
1942           gdk_gc_destroy (gc);
1943
1944           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
1945                                          mask, 0, 0);
1946           if (mask) gdk_pixmap_unref (mask);
1947           tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
1948         }
1949     }
1950   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
1951     {
1952       gint i, j = 1;
1953       GdkGC *gc;
1954       GdkColor col;
1955       gint expander_width;
1956
1957       gtk_widget_style_get (widget,
1958                             "expander_height", &width,
1959                             "expander_width", &expander_width,
1960                             NULL);
1961
1962       /* Get x, y, width, height of arrow */
1963       if (reorder->left_column)
1964         {
1965           gdk_window_get_origin (reorder->left_column->button->window, &x, &y);
1966           x += reorder->left_column->button->allocation.width - width/2;
1967           height = reorder->left_column->button->allocation.height;
1968         }
1969       else
1970         {
1971           gdk_window_get_origin (reorder->right_column->button->window, &x, &y);
1972           x -= width/2;
1973           height = reorder->right_column->button->allocation.height;
1974         }
1975       y -= expander_width/2; /* The arrow takes up only half the space */
1976       height += expander_width;
1977
1978       /* Create the new window */
1979       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
1980         {
1981           if (tree_view->priv->drag_highlight_window)
1982             gdk_window_destroy (tree_view->priv->drag_highlight_window);
1983
1984           attributes.window_type = GDK_WINDOW_TEMP;
1985           attributes.wclass = GDK_INPUT_OUTPUT;
1986           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
1987           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
1988           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
1989           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1990           attributes.width = width;
1991           attributes.height = height;
1992           tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
1993           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
1994
1995           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
1996           gc = gdk_gc_new (mask);
1997           col.pixel = 1;
1998           gdk_gc_set_foreground (gc, &col);
1999           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2000
2001           /* Draw the 2 arrows as per above */
2002           col.pixel = 0;
2003           gdk_gc_set_foreground (gc, &col);
2004           for (i = 0; i < width; i ++)
2005             {
2006               if (i == (width/2 - 1))
2007                 continue;
2008               gdk_draw_line (mask, gc, i, j, i, height - j);
2009               if (i < (width/2 - 1))
2010                 j++;
2011               else
2012                 j--;
2013             }
2014           gdk_gc_destroy (gc);
2015           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2016                                          mask, 0, 0);
2017           if (mask) gdk_pixmap_unref (mask);
2018         }
2019
2020       tree_view->priv->drag_column_window_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
2021       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
2022     }
2023   else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
2024            arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2025     {
2026       gint i, j = 1;
2027       GdkGC *gc;
2028       GdkColor col;
2029       gint expander_height;
2030
2031       gtk_widget_style_get (widget,
2032                             "expander_height", &expander_height,
2033                             "expander_width", &width,
2034                             NULL);
2035
2036       /* Get x, y, width, height of arrow */
2037       width = width/2; /* remember, the arrow only takes half the available width */
2038       gdk_window_get_origin (widget->window, &x, &y);
2039       if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2040         x += widget->allocation.width - width;
2041
2042       if (reorder->left_column)
2043         height = reorder->left_column->button->allocation.height;
2044       else
2045         height = reorder->right_column->button->allocation.height;
2046
2047       y -= expander_height;
2048       height += 2*expander_height;
2049
2050       /* Create the new window */
2051       if (tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
2052           tree_view->priv->drag_column_window_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
2053         {
2054           if (tree_view->priv->drag_highlight_window)
2055             gdk_window_destroy (tree_view->priv->drag_highlight_window);
2056
2057           attributes.window_type = GDK_WINDOW_TEMP;
2058           attributes.wclass = GDK_INPUT_OUTPUT;
2059           attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
2060           attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
2061           attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
2062           attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
2063           attributes.width = width;
2064           attributes.height = height;
2065           tree_view->priv->drag_highlight_window = gdk_window_new (NULL, &attributes, attributes_mask);
2066           gdk_window_set_user_data (tree_view->priv->drag_highlight_window, GTK_WIDGET (tree_view));
2067
2068           mask = gdk_pixmap_new (tree_view->priv->drag_highlight_window, width, height, 1);
2069           gc = gdk_gc_new (mask);
2070           col.pixel = 1;
2071           gdk_gc_set_foreground (gc, &col);
2072           gdk_draw_rectangle (mask, gc, TRUE, 0, 0, width, height);
2073
2074           /* Draw the 2 arrows as per above */
2075           col.pixel = 0;
2076           gdk_gc_set_foreground (gc, &col);
2077           j = expander_height;
2078           for (i = 0; i < width; i ++)
2079             {
2080               gint k;
2081               if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
2082                 k = width - i - 1;
2083               else
2084                 k = i;
2085               gdk_draw_line (mask, gc, k, j, k, height - j);
2086               gdk_draw_line (mask, gc, k, 0, k, expander_height - j);
2087               gdk_draw_line (mask, gc, k, height, k, height - expander_height + j);
2088               j--;
2089             }
2090           gdk_gc_destroy (gc);
2091           gdk_window_shape_combine_mask (tree_view->priv->drag_highlight_window,
2092                                          mask, 0, 0);
2093           if (mask) gdk_pixmap_unref (mask);
2094         }
2095
2096       tree_view->priv->drag_column_window_state = arrow_type;
2097       gdk_window_move (tree_view->priv->drag_highlight_window, x, y);
2098    }
2099   else
2100     {
2101       g_warning (G_STRLOC"Invalid GtkTreeViewColumnReorder struct");
2102       gdk_window_hide (tree_view->priv->drag_highlight_window);
2103       return;
2104     }
2105
2106   gdk_window_show (tree_view->priv->drag_highlight_window);
2107   gdk_window_raise (tree_view->priv->drag_highlight_window);
2108 }
2109
2110 static gboolean
2111 gtk_tree_view_motion_resize_column (GtkWidget      *widget,
2112                                     GdkEventMotion *event)
2113 {
2114   gint x;
2115   gint new_width;
2116
2117   if (event->is_hint || event->window != widget->window)
2118     gtk_widget_get_pointer (widget, &x, NULL);
2119   else
2120     x = event->x;
2121
2122   new_width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget),
2123                                               GTK_TREE_VIEW (widget)->priv->drag_pos, &x);
2124   if (x != GTK_TREE_VIEW (widget)->priv->x_drag)
2125     _gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), GTK_TREE_VIEW (widget)->priv->drag_pos), new_width);
2126
2127   /* FIXME: Do we need to scroll */
2128   _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
2129   return FALSE;
2130 }
2131
2132
2133 static void
2134 gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
2135 {
2136   GtkTreeViewColumnReorder *reorder = NULL;
2137   GList *list;
2138   gint mouse_x;
2139
2140   gdk_window_get_pointer (tree_view->priv->bin_window, &mouse_x, NULL, NULL);
2141
2142   for (list = tree_view->priv->column_drag_info; list; list = list->next)
2143     {
2144       reorder = (GtkTreeViewColumnReorder *) list->data;
2145       if (mouse_x >= reorder->left_align && mouse_x < reorder->right_align)
2146         break;
2147       reorder = NULL;
2148     }
2149
2150   /*  if (reorder && reorder == tree_view->priv->cur_reorder)
2151       return;*/
2152
2153   tree_view->priv->cur_reorder = reorder;
2154   gtk_tree_view_motion_draw_column_motion_arrow (tree_view);
2155 }
2156
2157 static gboolean
2158 gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
2159 {
2160   GdkRectangle visible_rect;
2161   gint x;
2162   gint offset;
2163   gfloat value;
2164
2165   gdk_window_get_pointer (tree_view->priv->bin_window, &x, NULL, NULL);
2166
2167   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
2168
2169   /* See if we are near the edge. */
2170   offset = x - (visible_rect.x + SCROLL_EDGE_SIZE);
2171   if (offset > 0)
2172     {
2173       offset = x - (visible_rect.x + visible_rect.width - SCROLL_EDGE_SIZE);
2174       if (offset < 0)
2175         return TRUE;
2176     }
2177   offset = offset/3;
2178
2179   value = CLAMP (tree_view->priv->hadjustment->value + offset,
2180                  0.0, tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size);
2181   gtk_adjustment_set_value (tree_view->priv->hadjustment, value);
2182
2183   return TRUE;
2184
2185 }
2186
2187 static gboolean
2188 gtk_tree_view_motion_drag_column (GtkWidget      *widget,
2189                                   GdkEventMotion *event)
2190 {
2191   GtkTreeView *tree_view = (GtkTreeView *) widget;
2192   GtkTreeViewColumn *column = tree_view->priv->drag_column;
2193   gint x, y;
2194
2195   /* Sanity Check */
2196   if ((column == NULL) ||
2197       (event->window != tree_view->priv->drag_window))
2198     return FALSE;
2199
2200   /* Handle moving the header */
2201   gdk_window_get_position (tree_view->priv->drag_window, &x, &y);
2202   x = CLAMP (x + (gint)event->x - column->drag_x, 0,
2203              MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width) - column->button->allocation.width);
2204   gdk_window_move (tree_view->priv->drag_window, x, y);
2205
2206   /* autoscroll, if needed */
2207   gtk_tree_view_horizontal_autoscroll (tree_view);
2208   /* Update the current reorder position and arrow; */
2209   gtk_tree_view_update_current_reorder (tree_view);
2210
2211   return TRUE;
2212 }
2213
2214 static gboolean
2215 gtk_tree_view_motion_bin_window (GtkWidget      *widget,
2216                                  GdkEventMotion *event)
2217 {
2218   GtkTreeView *tree_view;
2219   GtkRBTree *tree;
2220   GtkRBNode *node;
2221   gint new_y;
2222   GtkRBTree *old_prelight_tree;
2223   GtkRBNode *old_prelight_node;
2224
2225   tree_view = (GtkTreeView *) widget;
2226
2227   if (tree_view->priv->tree == NULL)
2228     return FALSE;
2229
2230   gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
2231
2232   old_prelight_tree = tree_view->priv->prelight_tree;
2233   old_prelight_node = tree_view->priv->prelight_node;
2234
2235   do_unprelight (tree_view, event->x, event->y);
2236
2237   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
2238
2239   _gtk_rbtree_find_offset (tree_view->priv->tree,
2240                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
2241                            &tree,
2242                            &node);
2243
2244   if (tree == NULL)
2245     return TRUE;
2246
2247   /* If we are currently pressing down a button, we don't want to prelight anything else. */
2248   if ((tree_view->priv->button_pressed_node != NULL) &&
2249       (tree_view->priv->button_pressed_node != node))
2250     return TRUE;
2251
2252
2253   do_prelight (tree_view, tree, node, event->x, new_y);
2254
2255   if (old_prelight_node != tree_view->priv->prelight_node)
2256     {
2257       if (old_prelight_node)
2258         gtk_tree_view_queue_draw_node (tree_view,
2259                                        old_prelight_tree,
2260                                        old_prelight_node,
2261                                        NULL);
2262
2263       if (tree_view->priv->prelight_node)
2264         gtk_tree_view_queue_draw_node (tree_view,
2265                                        tree_view->priv->prelight_tree,
2266                                        tree_view->priv->prelight_node,
2267                                        NULL);
2268     }
2269
2270   return TRUE;
2271 }
2272
2273 static gboolean
2274 gtk_tree_view_motion (GtkWidget      *widget,
2275                       GdkEventMotion *event)
2276 {
2277   GtkTreeView *tree_view;
2278
2279   tree_view = (GtkTreeView *) widget;
2280
2281   /* Resizing a column */
2282   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
2283     return gtk_tree_view_motion_resize_column (widget, event);
2284
2285   /* Drag column */
2286   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
2287     return gtk_tree_view_motion_drag_column (widget, event);
2288
2289   /* Sanity check it */
2290   if (event->window == tree_view->priv->bin_window)
2291     return gtk_tree_view_motion_bin_window (widget, event);
2292
2293   return FALSE;
2294 }
2295
2296 /* Draws the focus rectangle around the cursor row */
2297 static void
2298 gtk_tree_view_draw_focus (GtkWidget *widget)
2299 {
2300   GtkTreeView *tree_view;
2301   GtkTreePath *cursor_path;
2302   GtkRBTree *tree = NULL;
2303   GtkRBNode *node = NULL;
2304   gint x, y;
2305   gint width, height;
2306   gint vertical_separator;
2307
2308   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
2309
2310   tree_view = GTK_TREE_VIEW (widget);
2311
2312   gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
2313
2314   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
2315     return;
2316
2317   if (! gtk_tree_row_reference_valid (tree_view->priv->cursor))
2318     return;
2319
2320   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2321
2322   _gtk_tree_view_find_node (tree_view, cursor_path, &tree, &node);
2323
2324   if (tree == NULL)
2325     {
2326       gtk_tree_path_free (cursor_path);
2327       return;
2328     }
2329
2330   gdk_drawable_get_size (tree_view->priv->bin_window,
2331                          &width, NULL);
2332
2333
2334   x = 0;
2335   y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
2336   gdk_drawable_get_size (tree_view->priv->bin_window,
2337                          &width, NULL);
2338   width = width - 1;
2339   height = BACKGROUND_HEIGHT (node) - 1;
2340   if (tree_view->priv->focus_column != NULL)
2341     {
2342       GtkTreeIter iter;
2343
2344       gtk_tree_model_get_iter (tree_view->priv->model, &iter, cursor_path);
2345       gtk_tree_view_column_cell_set_cell_data (tree_view->priv->focus_column, tree_view->priv->model, &iter);
2346
2347       if (gtk_tree_view_column_cell_can_focus (tree_view->priv->focus_column))
2348         {
2349           GdkRectangle cell_area;
2350           gint x_offset;
2351           gint y_offset;
2352
2353           cell_area.x = tree_view->priv->focus_column->button->allocation.x;
2354           cell_area.y = y;
2355           cell_area.width = tree_view->priv->focus_column->displayed_width;
2356           cell_area.height = CELL_HEIGHT (node, vertical_separator);
2357
2358           gtk_tree_view_column_cell_get_size (tree_view->priv->focus_column,
2359                                               &cell_area, &x_offset, &y_offset, &width, &height);
2360
2361           width += 2;
2362           height += 2;
2363           x = cell_area.x + x_offset - 1;
2364           y = cell_area.y + y_offset - 1 + vertical_separator/2;
2365         }
2366     }
2367
2368   gtk_paint_focus (widget->style,
2369                    tree_view->priv->bin_window,
2370                    NULL,
2371                    widget,
2372                    "add-mode",
2373                    x, y, width, height);
2374
2375   gtk_tree_path_free (cursor_path);
2376 }
2377
2378 /* Warning: Very scary function.
2379  * Modify at your own risk
2380  */
2381 static gboolean
2382 gtk_tree_view_bin_expose (GtkWidget      *widget,
2383                           GdkEventExpose *event)
2384 {
2385   GtkTreeView *tree_view;
2386   GtkTreePath *path;
2387   GtkRBTree *tree;
2388   GList *list;
2389   GtkRBNode *node;
2390   GtkRBNode *cursor = NULL;
2391   GtkRBTree *cursor_tree = NULL;
2392   GtkRBNode *drag_highlight = NULL;
2393   GtkRBTree *drag_highlight_tree = NULL;
2394   GtkTreeIter iter;
2395   gint new_y;
2396   gint y_offset, x_offset, cell_offset;
2397   gint max_height;
2398   gint depth;
2399   GdkRectangle background_area;
2400   GdkRectangle cell_area;
2401   guint flags;
2402   gint highlight_x;
2403   gint bin_window_width;
2404   GtkTreePath *cursor_path;
2405   GtkTreePath *drag_dest_path;
2406   GList *last_column;
2407   gint vertical_separator;
2408
2409   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2410
2411   tree_view = GTK_TREE_VIEW (widget);
2412   gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
2413
2414   if (tree_view->priv->tree == NULL)
2415     return TRUE;
2416
2417   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
2418   /* we want to account for a potential HEADER offset.
2419    * That is, if the header exists, we want to offset our event by its
2420    * height to find the right node.
2421    */
2422   new_y = (event->area.y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):event->area.y;
2423
2424   /* y_offset is the */
2425
2426   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
2427                                        TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
2428                                        &tree,
2429                                        &node) + new_y - event->area.y;
2430   if (node == NULL)
2431     return TRUE;
2432
2433   /* find the path for the node */
2434   path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
2435                                    tree,
2436                                    node);
2437   gtk_tree_model_get_iter (tree_view->priv->model,
2438                            &iter,
2439                            path);
2440   depth = gtk_tree_path_get_depth (path);
2441   gtk_tree_path_free (path);
2442
2443   cursor_path = NULL;
2444   drag_dest_path = NULL;
2445
2446   if (tree_view->priv->cursor)
2447     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2448
2449   if (cursor_path)
2450     _gtk_tree_view_find_node (tree_view, cursor_path,
2451                               &cursor_tree, &cursor);
2452
2453   if (tree_view->priv->drag_dest_row)
2454     drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
2455
2456   if (drag_dest_path)
2457     _gtk_tree_view_find_node (tree_view, drag_dest_path,
2458                               &drag_highlight_tree, &drag_highlight);
2459
2460   gdk_drawable_get_size (tree_view->priv->bin_window,
2461                          &bin_window_width, NULL);
2462
2463   for (last_column = g_list_last (tree_view->priv->columns);
2464        last_column &&
2465          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
2466          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
2467        last_column = last_column->prev)
2468     ;
2469
2470   /* Actually process the expose event.  To do this, we want to
2471    * start at the first node of the event, and walk the tree in
2472    * order, drawing each successive node.
2473    */
2474
2475   do
2476     {
2477       gboolean parity;
2478
2479       max_height = BACKGROUND_HEIGHT (node);
2480
2481       x_offset = -event->area.x;
2482       cell_offset = 0;
2483       highlight_x = 0; /* should match x coord of first cell */
2484
2485       background_area.y = y_offset + event->area.y;
2486       background_area.height = max_height;
2487       flags = 0;
2488
2489       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
2490         flags |= GTK_CELL_RENDERER_PRELIT;
2491
2492       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
2493         flags |= GTK_CELL_RENDERER_SELECTED;
2494
2495       parity = _gtk_rbtree_node_find_parity (tree, node);
2496       
2497       for (list = tree_view->priv->columns; list; list = list->next)
2498         {
2499           GtkTreeViewColumn *column = list->data;
2500           const gchar *detail = NULL;
2501
2502           if (!column->visible)
2503             continue;
2504
2505           if (cell_offset > event->area.x + event->area.width ||
2506               cell_offset + column->displayed_width < event->area.x)
2507             {
2508               cell_offset += column->displayed_width;
2509               continue;
2510             }
2511
2512           if (column->show_sort_indicator)
2513             flags |= GTK_CELL_RENDERER_SORTED;
2514           else
2515             flags &= ~GTK_CELL_RENDERER_SORTED;
2516
2517           gtk_tree_view_column_cell_set_cell_data (column,
2518                                                    tree_view->priv->model,
2519                                                    &iter);
2520
2521           background_area.x = cell_offset;
2522           background_area.width = column->displayed_width;
2523
2524           cell_area = background_area;
2525           cell_area.y += vertical_separator / 2;
2526           cell_area.height -= vertical_separator;
2527
2528           /* Select the detail for drawing the cell.  relevant
2529            * factors are parity, sortedness, and whether to
2530            * display rules.
2531            */
2532
2533           /* FIXME when we have style properties, clean this up.
2534            */
2535
2536           if (tree_view->priv->has_rules)
2537             {
2538               if (flags & GTK_CELL_RENDERER_SORTED)
2539                 {
2540                   if (parity)
2541                     detail = "cell_odd_ruled_sorted";
2542                   else
2543                     detail = "cell_even_ruled_sorted";
2544                 }
2545               else
2546                 {
2547                   if (parity)
2548                     detail = "cell_odd_ruled";
2549                   else
2550                     detail = "cell_even_ruled";
2551                 }
2552             }
2553           else
2554             {
2555               if (flags & GTK_CELL_RENDERER_SORTED)
2556                 {
2557                   if (parity)
2558                     detail = "cell_odd_sorted";
2559                   else
2560                     detail = "cell_even_sorted";
2561                 }
2562               else
2563                 {
2564                   if (parity)
2565                     detail = "cell_odd";
2566                   else
2567                     detail = "cell_even";
2568                 }
2569             }
2570
2571           g_assert (detail);
2572
2573           /* Draw background */
2574           gtk_paint_flat_box (widget->style,
2575                               event->window,
2576                               (flags & GTK_CELL_RENDERER_SELECTED) ?
2577                               GTK_STATE_SELECTED : GTK_STATE_NORMAL,
2578                               GTK_SHADOW_NONE,
2579                               &event->area,
2580                               widget,
2581                               detail,
2582                               background_area.x,
2583                               background_area.y,
2584                               background_area.width,
2585                               background_area.height);
2586
2587           if (gtk_tree_view_is_expander_column (tree_view, column) &&
2588               TREE_VIEW_DRAW_EXPANDERS(tree_view))
2589             {
2590               cell_area.x += depth*tree_view->priv->tab_offset;
2591               cell_area.width -= depth*tree_view->priv->tab_offset;
2592
2593               /* If we have an expander column, the highlight underline
2594                * starts with that column, so that it indicates which
2595                * level of the tree we're dropping at.
2596                */
2597               highlight_x = cell_area.x;
2598
2599               gtk_tree_view_column_cell_render (column,
2600                                                 event->window,
2601                                                 &background_area,
2602                                                 &cell_area,
2603                                                 &event->area,
2604                                                 flags);
2605               if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
2606                 {
2607                   gint x, y;
2608                   gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, 0);
2609                   gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
2610                                             tree,
2611                                             node,
2612                                             x, y);
2613                 }
2614             }
2615           else
2616             {
2617               gtk_tree_view_column_cell_render (column,
2618                                                 event->window,
2619                                                 &background_area,
2620                                                 &cell_area,
2621                                                 &event->area,
2622                                                 flags);
2623             }
2624           cell_offset += column->displayed_width;
2625         }
2626
2627       if (node == cursor && GTK_WIDGET_HAS_FOCUS (widget))
2628         gtk_tree_view_draw_focus (widget);
2629
2630       if (node == drag_highlight)
2631         {
2632           /* Draw indicator for the drop
2633            */
2634           gint highlight_y = -1;
2635           GtkRBTree *tree = NULL;
2636           GtkRBNode *node = NULL;
2637           gint width;
2638
2639           switch (tree_view->priv->drag_dest_pos)
2640             {
2641             case GTK_TREE_VIEW_DROP_BEFORE:
2642               highlight_y = background_area.y - vertical_separator/2;
2643               break;
2644
2645             case GTK_TREE_VIEW_DROP_AFTER:
2646               highlight_y = background_area.y + background_area.height + vertical_separator/2;
2647               break;
2648
2649             case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
2650             case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
2651               _gtk_tree_view_find_node (tree_view, drag_dest_path, &tree, &node);
2652
2653               if (tree == NULL)
2654                 break;
2655               gdk_drawable_get_size (tree_view->priv->bin_window,
2656                                      &width, NULL);
2657               gtk_paint_focus (widget->style,
2658                                tree_view->priv->bin_window,
2659                                NULL,
2660                                widget,
2661                                "add-mode",
2662                                0, BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
2663                                width - 1, BACKGROUND_HEIGHT (node) - 1);
2664
2665               break;
2666             }
2667
2668           if (highlight_y >= 0)
2669             {
2670               gdk_draw_line (event->window,
2671                              widget->style->black_gc,
2672                              highlight_x,
2673                              highlight_y,
2674                              bin_window_width - highlight_x,
2675                              highlight_y);
2676             }
2677         }
2678
2679       y_offset += max_height;
2680       if (node->children)
2681         {
2682           GtkTreeIter parent = iter;
2683           gboolean has_child;
2684
2685           tree = node->children;
2686           node = tree->root;
2687
2688           g_assert (node != tree->nil);
2689
2690           while (node->left != tree->nil)
2691             node = node->left;
2692           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
2693                                                     &iter,
2694                                                     &parent);
2695           depth++;
2696
2697           /* Sanity Check! */
2698           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
2699         }
2700       else
2701         {
2702           gboolean done = FALSE;
2703           do
2704             {
2705               node = _gtk_rbtree_next (tree, node);
2706               if (node != NULL)
2707                 {
2708                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
2709                   done = TRUE;
2710
2711                   /* Sanity Check! */
2712                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
2713                 }
2714               else
2715                 {
2716                   GtkTreeIter parent_iter = iter;
2717                   gboolean has_parent;
2718
2719                   node = tree->parent_node;
2720                   tree = tree->parent_tree;
2721                   if (tree == NULL)
2722                     /* we've run out of tree.  It's okay to return though, as
2723                      * we'd only break out of the while loop below. */
2724                     return TRUE;
2725                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
2726                                                            &iter,
2727                                                            &parent_iter);
2728                   depth--;
2729
2730                   /* Sanity check */
2731                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
2732                 }
2733             }
2734           while (!done);
2735         }
2736     }
2737   while (y_offset < event->area.height);
2738
2739   if (cursor_path)
2740     gtk_tree_path_free (cursor_path);
2741
2742   if (drag_dest_path)
2743     gtk_tree_path_free (drag_dest_path);
2744
2745   return TRUE;
2746 }
2747
2748 static gboolean
2749 gtk_tree_view_expose (GtkWidget      *widget,
2750                       GdkEventExpose *event)
2751 {
2752   GtkTreeView *tree_view;
2753
2754   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2755
2756   tree_view = GTK_TREE_VIEW (widget);
2757
2758   if (event->window == tree_view->priv->bin_window)
2759     return gtk_tree_view_bin_expose (widget, event);
2760
2761   return TRUE;
2762 }
2763
2764 static gboolean
2765 gtk_tree_view_key_press (GtkWidget   *widget,
2766                          GdkEventKey *event)
2767 {
2768   GtkTreeView *tree_view = (GtkTreeView *) widget;
2769
2770   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG))
2771     {
2772       if (event->keyval == GDK_Escape)
2773         {
2774           tree_view->priv->cur_reorder = NULL;
2775           gtk_tree_view_button_release_drag_column (widget, NULL);
2776         }
2777       return TRUE;
2778     }
2779   return (* GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event);
2780 }
2781
2782 /* FIXME Is this function necessary? Can I get an enter_notify event
2783  * w/o either an expose event or a mouse motion event?
2784  */
2785 static gboolean
2786 gtk_tree_view_enter_notify (GtkWidget        *widget,
2787                             GdkEventCrossing *event)
2788 {
2789   GtkTreeView *tree_view;
2790   GtkRBTree *tree;
2791   GtkRBNode *node;
2792   gint new_y;
2793
2794   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2795
2796   tree_view = GTK_TREE_VIEW (widget);
2797
2798   /* Sanity check it */
2799   if (event->window != tree_view->priv->bin_window)
2800     return FALSE;
2801
2802   if (tree_view->priv->tree == NULL)
2803     return FALSE;
2804
2805   if ((tree_view->priv->button_pressed_node != NULL) &&
2806       (tree_view->priv->button_pressed_node != node))
2807     return TRUE;
2808
2809   /* find the node internally */
2810   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
2811
2812   _gtk_rbtree_find_offset (tree_view->priv->tree,
2813                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
2814                            &tree,
2815                            &node);
2816
2817   if (node == NULL)
2818     return FALSE;
2819
2820   do_prelight (tree_view, tree, node, event->x, new_y);
2821
2822   if (tree_view->priv->prelight_node)
2823     gtk_tree_view_queue_draw_node (tree_view,
2824                                    tree_view->priv->prelight_tree,
2825                                    tree_view->priv->prelight_node,
2826                                    NULL);
2827
2828   return TRUE;
2829 }
2830
2831 static gboolean
2832 gtk_tree_view_leave_notify (GtkWidget        *widget,
2833                             GdkEventCrossing *event)
2834 {
2835   GtkTreeView *tree_view;
2836
2837   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2838
2839   tree_view = GTK_TREE_VIEW (widget);
2840
2841   if (tree_view->priv->prelight_node)
2842     gtk_tree_view_queue_draw_node (tree_view,
2843                                    tree_view->priv->prelight_tree,
2844                                    tree_view->priv->prelight_node,
2845                                    NULL);
2846
2847   ensure_unprelighted (tree_view);
2848
2849   return TRUE;
2850 }
2851
2852
2853 static gint
2854 gtk_tree_view_focus_in (GtkWidget     *widget,
2855                         GdkEventFocus *event)
2856 {
2857   GtkTreeView *tree_view;
2858
2859   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2860   g_return_val_if_fail (event != NULL, FALSE);
2861
2862   tree_view = GTK_TREE_VIEW (widget);
2863
2864   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2865
2866   gtk_widget_queue_draw (widget);
2867
2868   return FALSE;
2869 }
2870
2871
2872 static gint
2873 gtk_tree_view_focus_out (GtkWidget     *widget,
2874                          GdkEventFocus *event)
2875 {
2876   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2877   g_return_val_if_fail (event != NULL, FALSE);
2878
2879   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2880
2881   gtk_widget_queue_draw (widget);
2882   GTK_TREE_VIEW (widget)->priv->in_extended_selection = FALSE;
2883   GTK_TREE_VIEW (widget)->priv->in_free_motion = FALSE;
2884   return FALSE;
2885 }
2886
2887
2888 /* Drag-and-drop */
2889
2890 static void
2891 set_source_row (GdkDragContext *context,
2892                 GtkTreeModel   *model,
2893                 GtkTreePath    *source_row)
2894 {
2895   g_object_set_data_full (G_OBJECT (context),
2896                           "gtk-tree-view-source-row",
2897                           source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
2898                           (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
2899 }
2900
2901 static GtkTreePath*
2902 get_source_row (GdkDragContext *context)
2903 {
2904   GtkTreeRowReference *ref =
2905     g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
2906
2907   if (ref)
2908     return gtk_tree_row_reference_get_path (ref);
2909   else
2910     return NULL;
2911 }
2912
2913
2914 static void
2915 set_dest_row (GdkDragContext *context,
2916               GtkTreeModel   *model,
2917               GtkTreePath    *dest_row)
2918 {
2919   g_object_set_data_full (G_OBJECT (context),
2920                           "gtk-tree-view-dest-row",
2921                           dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
2922                           (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
2923 }
2924
2925 static GtkTreePath*
2926 get_dest_row (GdkDragContext *context)
2927 {
2928   GtkTreeRowReference *ref =
2929     g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
2930
2931   if (ref)
2932     return gtk_tree_row_reference_get_path (ref);
2933   else
2934     return NULL;
2935 }
2936
2937 /* Get/set whether drag_motion requested the drag data and
2938  * drag_data_received should thus not actually insert the data,
2939  * since the data doesn't result from a drop.
2940  */
2941 static void
2942 set_status_pending (GdkDragContext *context,
2943                     GdkDragAction   suggested_action)
2944 {
2945   g_object_set_data (G_OBJECT (context),
2946                      "gtk-tree-view-status-pending",
2947                      GINT_TO_POINTER (suggested_action));
2948 }
2949
2950 static GdkDragAction
2951 get_status_pending (GdkDragContext *context)
2952 {
2953   return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
2954                                              "gtk-tree-view-status-pending"));
2955 }
2956
2957 static TreeViewDragInfo*
2958 get_info (GtkTreeView *tree_view)
2959 {
2960   return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
2961 }
2962
2963 static void
2964 clear_source_info (TreeViewDragInfo *di)
2965 {
2966   if (di->source_target_list)
2967     gtk_target_list_unref (di->source_target_list);
2968
2969   if (di->row_draggable_closure)
2970     g_closure_unref (di->row_draggable_closure);
2971
2972   di->source_target_list = NULL;
2973   di->row_draggable_closure = NULL;
2974 }
2975
2976 static void
2977 clear_dest_info (TreeViewDragInfo *di)
2978 {
2979   if (di->location_droppable_closure)
2980     g_closure_unref (di->location_droppable_closure);
2981
2982   if (di->dest_target_list)
2983     gtk_target_list_unref (di->dest_target_list);
2984
2985   di->location_droppable_closure = NULL;
2986   di->dest_target_list = NULL;
2987 }
2988
2989 static void
2990 destroy_info (TreeViewDragInfo *di)
2991 {
2992   clear_source_info (di);
2993   clear_dest_info (di);
2994   g_free (di);
2995 }
2996
2997 static TreeViewDragInfo*
2998 ensure_info (GtkTreeView *tree_view)
2999 {
3000   TreeViewDragInfo *di;
3001
3002   di = get_info (tree_view);
3003
3004   if (di == NULL)
3005     {
3006       di = g_new0 (TreeViewDragInfo, 1);
3007
3008       g_object_set_data_full (G_OBJECT (tree_view),
3009                               "gtk-tree-view-drag-info",
3010                               di,
3011                               (GDestroyNotify) destroy_info);
3012     }
3013
3014   return di;
3015 }
3016
3017 static void
3018 remove_info (GtkTreeView *tree_view)
3019 {
3020   g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
3021 }
3022
3023 #if 0
3024 static gint
3025 drag_scan_timeout (gpointer data)
3026 {
3027   GtkTreeView *tree_view;
3028   gint x, y;
3029   GdkModifierType state;
3030   GtkTreePath *path = NULL;
3031   GtkTreeViewColumn *column = NULL;
3032   GdkRectangle visible_rect;
3033
3034   GDK_THREADS_ENTER ();
3035
3036   tree_view = GTK_TREE_VIEW (data);
3037
3038   gdk_window_get_pointer (tree_view->priv->bin_window,
3039                           &x, &y, &state);
3040
3041   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
3042
3043   /* See if we are near the edge. */
3044   if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
3045       (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
3046       (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
3047       (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
3048     {
3049       gtk_tree_view_get_path_at_pos (tree_view,
3050                                      tree_view->priv->bin_window,
3051                                      x, y,
3052                                      &path,
3053                                      &column,
3054                                      NULL,
3055                                      NULL);
3056
3057       if (path != NULL)
3058         {
3059           gtk_tree_view_scroll_to_cell (tree_view,
3060                                         path,
3061                                         column,
3062                                         0.5, 0.5);
3063
3064           gtk_tree_path_free (path);
3065         }
3066     }
3067
3068   GDK_THREADS_LEAVE ();
3069
3070   return TRUE;
3071 }
3072 #endif /* 0 */
3073
3074 static void
3075 remove_scroll_timeout (GtkTreeView *tree_view)
3076 {
3077   if (tree_view->priv->scroll_timeout != 0)
3078     {
3079       gtk_timeout_remove (tree_view->priv->scroll_timeout);
3080       tree_view->priv->scroll_timeout = 0;
3081     }
3082 }
3083 static gboolean
3084 check_model_dnd (GtkTreeModel *model,
3085                  GType         required_iface,
3086                  const gchar  *signal)
3087 {
3088   if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
3089     {
3090       g_warning ("You must override the default '%s' handler "
3091                  "on GtkTreeView when using models that don't support "
3092                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
3093                  "is to connect to '%s' and call "
3094                  "gtk_signal_emit_stop_by_name() in your signal handler to prevent "
3095                  "the default handler from running. Look at the source code "
3096                  "for the default handler in gtktreeview.c to get an idea what "
3097                  "your handler should do. (gtktreeview.c is in the GTK source "
3098                  "code.) If you're using GTK from a language other than C, "
3099                  "there may be a more natural way to override default handlers, e.g. via derivation.",
3100                  signal, g_type_name (required_iface), signal);
3101       return FALSE;
3102     }
3103   else
3104     return TRUE;
3105 }
3106
3107 static void
3108 remove_open_timeout (GtkTreeView *tree_view)
3109 {
3110   if (tree_view->priv->open_dest_timeout != 0)
3111     {
3112       gtk_timeout_remove (tree_view->priv->open_dest_timeout);
3113       tree_view->priv->open_dest_timeout = 0;
3114     }
3115 }
3116
3117
3118 static gint
3119 open_row_timeout (gpointer data)
3120 {
3121   GtkTreeView *tree_view = data;
3122   GtkTreePath *dest_path = NULL;
3123   GtkTreeViewDropPosition pos;
3124   gboolean result = FALSE;
3125
3126   GDK_THREADS_ENTER ();
3127   
3128   gtk_tree_view_get_drag_dest_row (tree_view,
3129                                    &dest_path,
3130                                    &pos);
3131
3132   if (dest_path &&
3133       (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
3134        pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
3135     {
3136       gtk_tree_view_expand_row (tree_view, dest_path, FALSE);
3137       tree_view->priv->open_dest_timeout = 0;
3138
3139       gtk_tree_path_free (dest_path);
3140     }
3141   else
3142     {
3143       if (dest_path)
3144         gtk_tree_path_free (dest_path);
3145       
3146       result = TRUE;
3147     }
3148   
3149   GDK_THREADS_LEAVE ();
3150
3151   return result;
3152 }
3153
3154 /* Returns TRUE if event should not be propagated to parent widgets */
3155 static gboolean
3156 set_destination_row (GtkTreeView    *tree_view,
3157                      GdkDragContext *context,
3158                      gint            x,
3159                      gint            y,
3160                      GdkDragAction  *suggested_action,
3161                      GdkAtom        *target)
3162 {
3163   GtkTreePath *path = NULL;
3164   GtkTreeViewDropPosition pos;
3165   GtkTreeViewDropPosition old_pos;
3166   TreeViewDragInfo *di;
3167   GtkWidget *widget;
3168   GtkTreePath *old_dest_path = NULL;
3169
3170   *suggested_action = 0;
3171   *target = GDK_NONE;
3172
3173   widget = GTK_WIDGET (tree_view);
3174
3175   di = get_info (tree_view);
3176
3177   if (di == NULL)
3178     {
3179       /* someone unset us as a drag dest, note that if
3180        * we return FALSE drag_leave isn't called
3181        */
3182
3183       gtk_tree_view_set_drag_dest_row (tree_view,
3184                                        NULL,
3185                                        GTK_TREE_VIEW_DROP_BEFORE);
3186
3187       remove_scroll_timeout (GTK_TREE_VIEW (widget));
3188       remove_open_timeout (GTK_TREE_VIEW (widget));
3189
3190       return FALSE; /* no longer a drop site */
3191     }
3192
3193   *target = gtk_drag_dest_find_target (widget, context, di->dest_target_list);
3194   if (*target == GDK_NONE)
3195     {
3196       return FALSE;
3197     }
3198
3199   if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
3200                                           x, y,
3201                                           &path,
3202                                           &pos))
3203     {
3204       /* can't drop here */
3205       remove_open_timeout (tree_view);
3206
3207       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3208                                        NULL,
3209                                        GTK_TREE_VIEW_DROP_BEFORE);
3210
3211       /* don't propagate to parent though */
3212       return TRUE;
3213     }
3214
3215   g_assert (path);
3216
3217   /* If we left the current row's "open" zone, unset the timeout for
3218    * opening the row
3219    */
3220   gtk_tree_view_get_drag_dest_row (tree_view,
3221                                    &old_dest_path,
3222                                    &old_pos);
3223
3224   if (old_dest_path &&
3225       (gtk_tree_path_compare (path, old_dest_path) != 0 ||
3226        !(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
3227          pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
3228     remove_open_timeout (tree_view);
3229
3230   if (old_dest_path)
3231     gtk_tree_path_free (old_dest_path);
3232
3233   if (TRUE /* FIXME if the location droppable predicate */)
3234     {
3235       GtkWidget *source_widget;
3236
3237       *suggested_action = context->suggested_action;
3238
3239       source_widget = gtk_drag_get_source_widget (context);
3240
3241       if (source_widget == widget)
3242         {
3243           /* Default to MOVE, unless the user has
3244            * pressed ctrl or alt to affect available actions
3245            */
3246           if ((context->actions & GDK_ACTION_MOVE) != 0)
3247             *suggested_action = GDK_ACTION_MOVE;
3248         }
3249
3250       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3251                                        path, pos);
3252     }
3253   else
3254     {
3255       /* can't drop here */
3256       remove_open_timeout (tree_view);
3257
3258       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3259                                        NULL,
3260                                        GTK_TREE_VIEW_DROP_BEFORE);
3261     }
3262
3263   return TRUE;
3264 }
3265 static GtkTreePath*
3266 get_logical_dest_row (GtkTreeView *tree_view)
3267
3268 {
3269   /* adjust path to point to the row the drop goes in front of */
3270   GtkTreePath *path = NULL;
3271   GtkTreeViewDropPosition pos;
3272
3273   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
3274
3275   if (path == NULL)
3276     return NULL;
3277
3278   if (pos == GTK_TREE_VIEW_DROP_BEFORE)
3279     ; /* do nothing */
3280   else if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
3281            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
3282     {
3283       /* get first child, drop before it */
3284       gtk_tree_path_append_index (path, 0);
3285     }
3286   else
3287     {
3288       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
3289       gtk_tree_path_next (path);
3290     }
3291
3292   return path;
3293 }
3294
3295 static gboolean
3296 gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
3297                                         GdkEventMotion   *event)
3298 {
3299   GdkDragContext *context;
3300   TreeViewDragInfo *di;
3301   GtkTreePath *path = NULL;
3302   gint button;
3303   gint cell_x, cell_y;
3304   GtkTreeModel *model;
3305
3306   di = get_info (tree_view);
3307
3308   if (di == NULL)
3309     return FALSE;
3310
3311   if (tree_view->priv->pressed_button < 0)
3312     return FALSE;
3313
3314   if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view),
3315                                  tree_view->priv->press_start_x,
3316                                  tree_view->priv->press_start_y,
3317                                  event->x, event->y))
3318     return FALSE;
3319
3320   model = gtk_tree_view_get_model (tree_view);
3321
3322   if (model == NULL)
3323     return FALSE;
3324
3325   button = tree_view->priv->pressed_button;
3326   tree_view->priv->pressed_button = -1;
3327
3328   gtk_tree_view_get_path_at_pos (tree_view,
3329                                  tree_view->priv->bin_window,
3330                                  tree_view->priv->press_start_x,
3331                                  tree_view->priv->press_start_y,
3332                                  &path,
3333                                  NULL,
3334                                  &cell_x,
3335                                  &cell_y);
3336
3337   if (path == NULL)
3338     return FALSE;
3339
3340   /* FIXME if the path doesn't match the row_draggable predicate,
3341    * return FALSE and free path
3342    */
3343
3344   /* FIXME Check whether we're a start button, if not return FALSE and
3345    * free path
3346    */
3347
3348   context = gtk_drag_begin (GTK_WIDGET (tree_view),
3349                             di->source_target_list,
3350                             di->source_actions,
3351                             button,
3352                             (GdkEvent*)event);
3353
3354   gtk_drag_set_icon_default (context);
3355
3356   {
3357     GdkPixmap *row_pix;
3358
3359     row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
3360                                                   path);
3361
3362     gtk_drag_set_icon_pixmap (context,
3363                               gdk_drawable_get_colormap (row_pix),
3364                               row_pix,
3365                               NULL,
3366                               /* the + 1 is for the black border in the icon */
3367                               tree_view->priv->press_start_x + 1,
3368                               cell_y + 1);
3369
3370     gdk_pixmap_unref (row_pix);
3371   }
3372
3373   set_source_row (context, model, path);
3374   gtk_tree_path_free (path);
3375
3376   return TRUE;
3377 }
3378
3379
3380 static void
3381 gtk_tree_view_drag_begin (GtkWidget      *widget,
3382                           GdkDragContext *context)
3383 {
3384   /* do nothing */
3385 }
3386
3387 static void
3388 gtk_tree_view_drag_end (GtkWidget      *widget,
3389                         GdkDragContext *context)
3390 {
3391   /* do nothing */
3392 }
3393
3394 /* Default signal implementations for the drag signals */
3395 static void
3396 gtk_tree_view_drag_data_get (GtkWidget        *widget,
3397                              GdkDragContext   *context,
3398                              GtkSelectionData *selection_data,
3399                              guint             info,
3400                              guint             time)
3401 {
3402   GtkTreeView *tree_view;
3403   GtkTreeModel *model;
3404   TreeViewDragInfo *di;
3405   GtkTreePath *source_row;
3406
3407   tree_view = GTK_TREE_VIEW (widget);
3408
3409   model = gtk_tree_view_get_model (tree_view);
3410
3411   if (model == NULL)
3412     return;
3413
3414   di = get_info (GTK_TREE_VIEW (widget));
3415
3416   if (di == NULL)
3417     return;
3418
3419   source_row = get_source_row (context);
3420
3421   if (source_row == NULL)
3422     return;
3423
3424   /* We can implement the GTK_TREE_MODEL_ROW target generically for
3425    * any model; for DragSource models there are some other targets
3426    * we also support.
3427    */
3428
3429   if (GTK_IS_TREE_DRAG_SOURCE (model) &&
3430       gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
3431                                           source_row,
3432                                           selection_data))
3433     goto done;
3434
3435   /* If drag_data_get does nothing, try providing row data. */
3436   if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
3437     {
3438       gtk_selection_data_set_tree_row (selection_data,
3439                                        model,
3440                                        source_row);
3441     }
3442
3443  done:
3444   gtk_tree_path_free (source_row);
3445 }
3446
3447
3448 static void
3449 gtk_tree_view_drag_data_delete (GtkWidget      *widget,
3450                                 GdkDragContext *context)
3451 {
3452   TreeViewDragInfo *di;
3453   GtkTreeModel *model;
3454   GtkTreeView *tree_view;
3455   GtkTreePath *source_row;
3456
3457   tree_view = GTK_TREE_VIEW (widget);
3458   model = gtk_tree_view_get_model (tree_view);
3459
3460   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
3461     return;
3462
3463   di = get_info (tree_view);
3464
3465   if (di == NULL)
3466     return;
3467
3468   source_row = get_source_row (context);
3469
3470   if (source_row == NULL)
3471     return;
3472
3473   gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
3474                                          source_row);
3475
3476   gtk_tree_path_free (source_row);
3477
3478   set_source_row (context, NULL, NULL);
3479 }
3480
3481 static void
3482 gtk_tree_view_drag_leave (GtkWidget      *widget,
3483                           GdkDragContext *context,
3484                           guint             time)
3485 {
3486   TreeViewDragInfo *di;
3487
3488   di = get_info (GTK_TREE_VIEW (widget));
3489
3490   /* unset any highlight row */
3491   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3492                                    NULL,
3493                                    GTK_TREE_VIEW_DROP_BEFORE);
3494
3495   remove_scroll_timeout (GTK_TREE_VIEW (widget));
3496   remove_open_timeout (GTK_TREE_VIEW (widget));
3497 }
3498
3499
3500 static gboolean
3501 gtk_tree_view_drag_motion (GtkWidget        *widget,
3502                            GdkDragContext   *context,
3503                            gint              x,
3504                            gint              y,
3505                            guint             time)
3506 {
3507   GtkTreePath *path = NULL;
3508   GtkTreeViewDropPosition pos;
3509   GtkTreeView *tree_view;
3510   GdkDragAction suggested_action = 0;
3511   GdkAtom target;
3512
3513   tree_view = GTK_TREE_VIEW (widget);
3514
3515   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
3516     return FALSE;
3517
3518   //  gtk_tree_view_ensure_scroll_timeout (tree_view);
3519
3520   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
3521
3522   if (path == NULL)
3523     {
3524       /* Can't drop here. */
3525       gdk_drag_status (context, 0, time);
3526     }
3527   else
3528     {
3529       if (tree_view->priv->open_dest_timeout == 0 &&
3530           (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
3531            pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
3532         {
3533           tree_view->priv->open_dest_timeout =
3534             gtk_timeout_add (500, open_row_timeout, tree_view);
3535         }
3536
3537       if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
3538         {
3539           /* Request data so we can use the source row when
3540            * determining whether to accept the drop
3541            */
3542           set_status_pending (context, suggested_action);
3543           gtk_drag_get_data (widget, context, target, time);
3544         }
3545       else
3546         {
3547           set_status_pending (context, 0);
3548           gdk_drag_status (context, suggested_action, time);
3549         }
3550     }
3551
3552   if (path)
3553     gtk_tree_path_free (path);
3554
3555   return TRUE;
3556 }
3557
3558
3559 static gboolean
3560 gtk_tree_view_drag_drop (GtkWidget        *widget,
3561                          GdkDragContext   *context,
3562                          gint              x,
3563                          gint              y,
3564                          guint             time)
3565 {
3566   GtkTreeView *tree_view;
3567   GtkTreePath *path;
3568   GdkDragAction suggested_action = 0;
3569   GdkAtom target = GDK_NONE;
3570   TreeViewDragInfo *di;
3571   GtkTreeModel *model;
3572
3573   tree_view = GTK_TREE_VIEW (widget);
3574
3575   model = gtk_tree_view_get_model (tree_view);
3576
3577   remove_scroll_timeout (GTK_TREE_VIEW (widget));
3578   remove_open_timeout (GTK_TREE_VIEW (widget));
3579
3580   di = get_info (tree_view);
3581
3582   if (di == NULL)
3583     return FALSE;
3584
3585   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
3586     return FALSE;
3587
3588   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
3589     return FALSE;
3590
3591   path = get_logical_dest_row (tree_view);
3592
3593   if (target != GDK_NONE && path != NULL)
3594     {
3595       /* in case a motion had requested drag data, change things so we
3596        * treat drag data receives as a drop.
3597        */
3598       set_status_pending (context, 0);
3599
3600       set_dest_row (context, model, path);
3601     }
3602
3603   if (path)
3604     gtk_tree_path_free (path);
3605
3606   /* Unset this thing */
3607   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3608                                    NULL,
3609                                    GTK_TREE_VIEW_DROP_BEFORE);
3610
3611   if (target != GDK_NONE)
3612     {
3613       gtk_drag_get_data (widget, context, target, time);
3614       return TRUE;
3615     }
3616   else
3617     return FALSE;
3618 }
3619
3620 static void
3621 gtk_tree_view_drag_data_received (GtkWidget        *widget,
3622                                   GdkDragContext   *context,
3623                                   gint              x,
3624                                   gint              y,
3625                                   GtkSelectionData *selection_data,
3626                                   guint             info,
3627                                   guint             time)
3628 {
3629   GtkTreePath *path;
3630   TreeViewDragInfo *di;
3631   gboolean accepted = FALSE;
3632   GtkTreeModel *model;
3633   GtkTreeView *tree_view;
3634   GtkTreePath *dest_row;
3635   GdkDragAction suggested_action;
3636
3637   tree_view = GTK_TREE_VIEW (widget);
3638
3639   model = gtk_tree_view_get_model (tree_view);
3640
3641   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
3642     return;
3643
3644   di = get_info (tree_view);
3645
3646   if (di == NULL)
3647     return;
3648
3649   suggested_action = get_status_pending (context);
3650
3651   if (suggested_action)
3652     {
3653       /* We are getting this data due to a request in drag_motion,
3654        * rather than due to a request in drag_drop, so we are just
3655        * supposed to call drag_status, not actually paste in the
3656        * data.
3657        */
3658       path = get_logical_dest_row (tree_view);
3659
3660       if (path == NULL)
3661         suggested_action = 0;
3662
3663       if (suggested_action)
3664         {
3665           GtkTreeModel *src_model = NULL;
3666           GtkTreePath *src_path = NULL;
3667
3668           if (!gtk_selection_data_get_tree_row (selection_data,
3669                                                 &src_model,
3670                                                 &src_path))
3671             suggested_action = 0;
3672
3673           if (suggested_action)
3674             {
3675               if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
3676                                                          src_model,
3677                                                          src_path,
3678                                                          path))
3679                 suggested_action = 0;
3680
3681               gtk_tree_path_free (src_path);
3682             }
3683         }
3684
3685       gdk_drag_status (context, suggested_action, time);
3686
3687       if (path)
3688         gtk_tree_path_free (path);
3689
3690       /* If you can't drop, remove user drop indicator until the next motion */
3691       if (suggested_action == 0)
3692         gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
3693                                          NULL,
3694                                          GTK_TREE_VIEW_DROP_BEFORE);
3695
3696       return;
3697     }
3698
3699   dest_row = get_dest_row (context);
3700
3701   if (dest_row == NULL)
3702     return;
3703
3704   if (selection_data->length >= 0)
3705     {
3706       if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
3707                                                  dest_row,
3708                                                  selection_data))
3709         accepted = TRUE;
3710     }
3711
3712   gtk_drag_finish (context,
3713                    accepted,
3714                    (context->action == GDK_ACTION_MOVE),
3715                    time);
3716
3717   gtk_tree_path_free (dest_row);
3718
3719   /* drop dest_row */
3720   set_dest_row (context, NULL, NULL);
3721 }
3722
3723
3724
3725 /* GtkContainer Methods
3726  */
3727
3728
3729 static void
3730 gtk_tree_view_remove (GtkContainer *container,
3731                       GtkWidget    *widget)
3732 {
3733   GtkTreeView *tree_view;
3734   GtkTreeViewChild *child = NULL;
3735   GList *tmp_list;
3736
3737   g_return_if_fail (GTK_IS_TREE_VIEW (container));
3738
3739   tree_view = GTK_TREE_VIEW (container);
3740
3741   tmp_list = tree_view->priv->children;
3742   while (tmp_list)
3743     {
3744       child = tmp_list->data;
3745       if (child->widget == widget)
3746         {
3747           gtk_widget_unparent (widget);
3748
3749           tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
3750           g_list_free_1 (tmp_list);
3751           g_free (child);
3752           return;
3753         }
3754
3755       tmp_list = tmp_list->next;
3756     }
3757
3758   tmp_list = tree_view->priv->columns;
3759
3760   while (tmp_list)
3761     {
3762       GtkTreeViewColumn *column;
3763       column = tmp_list->data;
3764       if (column->button == widget)
3765         {
3766           gtk_widget_unparent (widget);
3767           return;
3768         }
3769       tmp_list = tmp_list->next;
3770     }
3771
3772 }
3773
3774 static void
3775 gtk_tree_view_forall (GtkContainer *container,
3776                       gboolean      include_internals,
3777                       GtkCallback   callback,
3778                       gpointer      callback_data)
3779 {
3780   GtkTreeView *tree_view;
3781   GtkTreeViewChild *child = NULL;
3782   GtkTreeViewColumn *column;
3783   GList *tmp_list;
3784
3785   g_return_if_fail (GTK_IS_TREE_VIEW (container));
3786   g_return_if_fail (callback != NULL);
3787
3788   tree_view = GTK_TREE_VIEW (container);
3789
3790   tmp_list = tree_view->priv->children;
3791   while (tmp_list)
3792     {
3793       child = tmp_list->data;
3794       tmp_list = tmp_list->next;
3795
3796       (* callback) (child->widget, callback_data);
3797     }
3798   if (include_internals == FALSE)
3799     return;
3800
3801   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
3802     {
3803       column = tmp_list->data;
3804
3805       if (column->button)
3806         (* callback) (column->button, callback_data);
3807     }
3808 }
3809
3810 /* Returns TRUE if the focus is within the headers, after the focus operation is
3811  * done
3812  */
3813 static gboolean
3814 gtk_tree_view_header_focus (GtkTreeView      *tree_view,
3815                             GtkDirectionType  dir)
3816 {
3817   GtkWidget *focus_child;
3818   GtkContainer *container;
3819
3820   GList *last_column, *first_column;
3821   GList *tmp_list;
3822
3823   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
3824     return FALSE;
3825
3826   focus_child = GTK_CONTAINER (tree_view)->focus_child;
3827   container = GTK_CONTAINER (tree_view);
3828
3829   last_column = g_list_last (tree_view->priv->columns);
3830   while (last_column)
3831     {
3832       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button) &&
3833           GTK_TREE_VIEW_COLUMN (last_column->data)->visible)
3834         break;
3835       last_column = last_column->prev;
3836     }
3837
3838   /* No headers are visible, or are focusable.  We can't focus in or out.
3839    */
3840   if (last_column == NULL)
3841     return FALSE;
3842
3843   first_column = tree_view->priv->columns;
3844   while (first_column)
3845     {
3846       if (GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button) &&
3847           GTK_TREE_VIEW_COLUMN (first_column->data)->visible)
3848         break;
3849       first_column = first_column->next;
3850     }
3851
3852   switch (dir)
3853     {
3854     case GTK_DIR_TAB_BACKWARD:
3855     case GTK_DIR_TAB_FORWARD:
3856     case GTK_DIR_UP:
3857     case GTK_DIR_DOWN:
3858       if (focus_child == NULL)
3859         {
3860           if (tree_view->priv->focus_column != NULL)
3861             focus_child = tree_view->priv->focus_column->button;
3862           else
3863             focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
3864           gtk_widget_grab_focus (focus_child);
3865           break;
3866         }
3867       return FALSE;
3868
3869     case GTK_DIR_LEFT:
3870     case GTK_DIR_RIGHT:
3871       if (focus_child == NULL)
3872         {
3873           if (tree_view->priv->focus_column != NULL)
3874             focus_child = tree_view->priv->focus_column->button;
3875           else if (dir == GTK_DIR_LEFT)
3876             focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
3877           else
3878             focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
3879           gtk_widget_grab_focus (focus_child);
3880           break;
3881         }
3882
3883       if (gtk_widget_child_focus (focus_child, dir))
3884         {
3885           /* The focus moves inside the button. */
3886           /* This is probably a great example of bad UI */
3887           break;
3888         }
3889
3890       /* We need to move the focus among the row of buttons. */
3891       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
3892         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
3893           break;
3894
3895       if (tmp_list == first_column && dir == GTK_DIR_LEFT)
3896         {
3897           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
3898           gtk_widget_grab_focus (focus_child);
3899           break;
3900         }
3901       else if (tmp_list == last_column && dir == GTK_DIR_RIGHT)
3902         {
3903           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
3904           gtk_widget_grab_focus (focus_child);
3905           break;
3906         }
3907
3908       while (tmp_list)
3909         {
3910           GtkTreeViewColumn *column;
3911
3912           if (dir == GTK_DIR_RIGHT)
3913             tmp_list = tmp_list->next;
3914           else
3915             tmp_list = tmp_list->prev;
3916
3917           if (tmp_list == NULL)
3918             {
3919               g_warning ("Internal button not found");
3920               break;
3921             }
3922           column = tmp_list->data;
3923           if (column->button &&
3924               column->visible &&
3925               GTK_WIDGET_CAN_FOCUS (column->button))
3926             {
3927               focus_child = column->button;
3928               gtk_widget_grab_focus (column->button);
3929               break;
3930             }
3931         }
3932       break;
3933     default:
3934       g_assert_not_reached ();
3935       break;
3936     }
3937
3938   /* if focus child is non-null, we assume it's been set to the current focus child
3939    */
3940   if (focus_child)
3941     {
3942       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
3943         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
3944           break;
3945
3946       tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
3947
3948       /* If the following isn't true, then the view is smaller then the scrollpane.
3949        */
3950       if ((focus_child->allocation.x + focus_child->allocation.width) <=
3951           (tree_view->priv->hadjustment->upper))
3952         {
3953           /* Scroll to the button, if needed */
3954           if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
3955               (focus_child->allocation.x + focus_child->allocation.width))
3956             gtk_adjustment_set_value (tree_view->priv->hadjustment,
3957                                       focus_child->allocation.x + focus_child->allocation.width -
3958                                       tree_view->priv->hadjustment->page_size);
3959           else if (tree_view->priv->hadjustment->value > focus_child->allocation.x)
3960             gtk_adjustment_set_value (tree_view->priv->hadjustment,
3961                                       focus_child->allocation.x);
3962         }
3963     }
3964
3965   return (focus_child != NULL);
3966 }
3967
3968 /* We make the assumption that if container->focus_child != NULL, the focus must
3969  * be in the header.  For now, this is accurate.  It may not be in the future.
3970  */
3971
3972 /* The sordid relationship between focus_column and scroll_column:
3973  *
3974  * The focus_column represents the column that currently has keyboard focus, and
3975  * is used when navigating columns by keyboard.  scroll_column is used for
3976  * handling scrolling by keyboard, such that in cases.
3977  */
3978 static gint
3979 gtk_tree_view_focus (GtkWidget        *widget,
3980                      GtkDirectionType  direction)
3981 {
3982   GtkTreeView *tree_view;
3983   GtkWidget *focus_child;
3984   GtkContainer *container;
3985
3986   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
3987   g_return_val_if_fail (GTK_WIDGET_VISIBLE (widget), FALSE);
3988
3989   container = GTK_CONTAINER (widget);
3990   tree_view = GTK_TREE_VIEW (widget);
3991
3992   if (!GTK_WIDGET_IS_SENSITIVE (container))
3993     return FALSE;
3994
3995   focus_child = container->focus_child;
3996
3997   /* Case 1.  Headers currently have focus. */
3998   if (focus_child)
3999     {
4000       switch (direction)
4001         {
4002         case GTK_DIR_LEFT:
4003         case GTK_DIR_RIGHT:
4004           gtk_tree_view_header_focus (tree_view, direction);
4005           return TRUE;
4006         case GTK_DIR_TAB_BACKWARD:
4007         case GTK_DIR_UP:
4008           return FALSE;
4009         case GTK_DIR_TAB_FORWARD:
4010         case GTK_DIR_DOWN:
4011           if (tree_view->priv->tree == NULL)
4012             return FALSE;
4013           gtk_tree_view_focus_to_cursor (tree_view);
4014           return TRUE;
4015         }
4016     }
4017
4018   /* Case 2. We don't have focus at all. */
4019   if (!GTK_WIDGET_HAS_FOCUS (container))
4020     {
4021       if (tree_view->priv->tree == NULL &&
4022           (direction == GTK_DIR_TAB_BACKWARD ||
4023            direction == GTK_DIR_UP))
4024         return gtk_tree_view_header_focus (tree_view, direction);
4025       if (((direction == GTK_DIR_TAB_FORWARD) ||
4026            (direction == GTK_DIR_RIGHT) ||
4027            (direction == GTK_DIR_DOWN) ||
4028            (direction == GTK_DIR_LEFT)) &&
4029           gtk_tree_view_header_focus (tree_view, direction))
4030         return TRUE;
4031
4032       if (tree_view->priv->tree == NULL)
4033         return FALSE;
4034       gtk_tree_view_focus_to_cursor (tree_view);
4035       return TRUE;
4036     }
4037
4038   /* Case 3. We have focus already. */
4039   if (tree_view->priv->tree == NULL)
4040     return gtk_tree_view_header_focus (tree_view, direction);
4041
4042   if (direction == GTK_DIR_TAB_BACKWARD)
4043     return (gtk_tree_view_header_focus (tree_view, direction));
4044   else if (direction == GTK_DIR_TAB_FORWARD)
4045     return FALSE;
4046
4047   /* Other directions caught by the keybindings */
4048   gtk_tree_view_focus_to_cursor (tree_view);
4049   return TRUE;
4050 }
4051
4052
4053 static void
4054 gtk_tree_view_set_focus_child (GtkContainer *container,
4055                                GtkWidget    *child)
4056 {
4057   GtkTreeView *tree_view = GTK_TREE_VIEW (container);
4058   GList *list;
4059
4060   for (list = tree_view->priv->columns; list; list = list->next)
4061     {
4062       if (GTK_TREE_VIEW_COLUMN (list->data)->button == child)
4063         {
4064           tree_view->priv->focus_column = GTK_TREE_VIEW_COLUMN (list->data);
4065           break;
4066         }
4067     }
4068
4069   (* parent_class->set_focus_child) (container, child);
4070 }
4071
4072 static void
4073 gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
4074                                GtkAdjustment *hadj,
4075                                GtkAdjustment *vadj)
4076 {
4077   gboolean need_adjust = FALSE;
4078
4079   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4080
4081   if (hadj)
4082     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
4083   else
4084     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
4085   if (vadj)
4086     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
4087   else
4088     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
4089
4090   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
4091     {
4092       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->hadjustment), tree_view);
4093       gtk_object_unref (GTK_OBJECT (tree_view->priv->hadjustment));
4094     }
4095
4096   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
4097     {
4098       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->vadjustment), tree_view);
4099       gtk_object_unref (GTK_OBJECT (tree_view->priv->vadjustment));
4100     }
4101
4102   if (tree_view->priv->hadjustment != hadj)
4103     {
4104       tree_view->priv->hadjustment = hadj;
4105       gtk_object_ref (GTK_OBJECT (tree_view->priv->hadjustment));
4106       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
4107
4108       gtk_signal_connect (GTK_OBJECT (tree_view->priv->hadjustment), "value_changed",
4109                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
4110                           tree_view);
4111       need_adjust = TRUE;
4112     }
4113
4114   if (tree_view->priv->vadjustment != vadj)
4115     {
4116       tree_view->priv->vadjustment = vadj;
4117       gtk_object_ref (GTK_OBJECT (tree_view->priv->vadjustment));
4118       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
4119
4120       gtk_signal_connect (GTK_OBJECT (tree_view->priv->vadjustment), "value_changed",
4121                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
4122                           tree_view);
4123       need_adjust = TRUE;
4124     }
4125
4126   if (need_adjust)
4127     gtk_tree_view_adjustment_changed (NULL, tree_view);
4128 }
4129
4130 static void
4131 gtk_tree_view_real_begin_extended_selection (GtkTreeView *tree_view)
4132 {
4133   tree_view->priv->in_extended_selection = TRUE;
4134 }
4135
4136 static void
4137 gtk_tree_view_real_end_extended_selection (GtkTreeView *tree_view)
4138 {
4139   tree_view->priv->in_extended_selection = FALSE;
4140 }
4141
4142 static void
4143 gtk_tree_view_real_begin_free_motion (GtkTreeView *tree_view)
4144 {
4145   tree_view->priv->in_free_motion = TRUE;
4146 }
4147
4148 static void
4149 gtk_tree_view_real_end_free_motion (GtkTreeView *tree_view)
4150 {
4151   tree_view->priv->in_free_motion = FALSE;
4152 }
4153
4154 static void
4155 gtk_tree_view_real_move_cursor (GtkTreeView       *tree_view,
4156                                 GtkMovementStep    step,
4157                                 gint               count)
4158 {
4159   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4160   g_return_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
4161                     step == GTK_MOVEMENT_VISUAL_POSITIONS ||
4162                     step == GTK_MOVEMENT_DISPLAY_LINES ||
4163                     step == GTK_MOVEMENT_PAGES ||
4164                     step == GTK_MOVEMENT_BUFFER_ENDS);
4165
4166   if (tree_view->priv->tree == NULL)
4167     return;
4168
4169   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
4170   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
4171
4172   switch (step)
4173     {
4174       /* currently we make no distinction.  When we go bi-di, we need to */
4175     case GTK_MOVEMENT_LOGICAL_POSITIONS:
4176     case GTK_MOVEMENT_VISUAL_POSITIONS:
4177       gtk_tree_view_move_cursor_left_right (tree_view, count);
4178       break;
4179     case GTK_MOVEMENT_DISPLAY_LINES:
4180       gtk_tree_view_move_cursor_up_down (tree_view, count);
4181       break;
4182     case GTK_MOVEMENT_PAGES:
4183       gtk_tree_view_move_cursor_page_up_down (tree_view, count);
4184       break;
4185     case GTK_MOVEMENT_BUFFER_ENDS:
4186       gtk_tree_view_move_cursor_start_end (tree_view, count);
4187       break;
4188     default:
4189       g_assert_not_reached ();
4190     }
4191 }
4192
4193 /* TreeModel Callbacks
4194  */
4195
4196 static void
4197 gtk_tree_view_range_changed (GtkTreeModel *model,
4198                              GtkTreePath  *path,
4199                              GtkTreeIter  *iter,
4200                              GtkTreePath  *end_path,
4201                              GtkTreeIter  *end_iter,
4202                              gpointer      data)
4203 {
4204   GtkTreeView *tree_view = (GtkTreeView *)data;
4205   GtkRBTree *tree;
4206   GtkRBNode *node;
4207   gint height;
4208   gboolean dirty_marked;
4209   gboolean free_path = FALSE;
4210   gint vertical_separator;
4211
4212
4213   g_return_if_fail (path != NULL || iter != NULL);
4214
4215   gtk_widget_style_get (GTK_WIDGET (data), "vertical_separator", &vertical_separator, NULL);
4216
4217   if (path == NULL)
4218     {
4219       path = gtk_tree_model_get_path (model, iter);
4220       free_path = TRUE;
4221     }
4222   else if (iter == NULL)
4223     gtk_tree_model_get_iter (model, iter, path);
4224
4225   if (_gtk_tree_view_find_node (tree_view,
4226                                 path,
4227                                 &tree,
4228                                 &node))
4229     /* We aren't actually showing the node */
4230     goto done;
4231
4232   if (tree == NULL)
4233     goto done;
4234
4235   dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view,
4236                                                     iter,
4237                                                     gtk_tree_path_get_depth (path),
4238                                                     &height);
4239
4240   if (GTK_RBNODE_GET_HEIGHT (node) != height + vertical_separator)
4241     {
4242       _gtk_rbtree_node_set_height (tree, node, height + vertical_separator);
4243       gtk_widget_queue_resize (GTK_WIDGET (data));
4244       goto done;
4245     }
4246   if (dirty_marked)
4247     gtk_widget_queue_resize (GTK_WIDGET (data));
4248   else
4249     gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
4250
4251  done:
4252   if (free_path)
4253     gtk_tree_path_free (path);
4254 }
4255
4256 static void
4257 gtk_tree_view_inserted (GtkTreeModel *model,
4258                         GtkTreePath  *path,
4259                         GtkTreeIter  *iter,
4260                         gpointer      data)
4261 {
4262   GtkTreeView *tree_view = (GtkTreeView *) data;
4263   gint *indices;
4264   GtkRBTree *tmptree, *tree;
4265   GtkRBNode *tmpnode = NULL;
4266   gint max_height;
4267   gint depth;
4268   gint i = 0;
4269   gboolean free_path = FALSE;
4270
4271   if (tree_view->priv->tree == NULL)
4272     tree_view->priv->tree = _gtk_rbtree_new ();
4273
4274   tmptree = tree = tree_view->priv->tree;
4275   g_return_if_fail (path != NULL || iter != NULL);
4276
4277   if (path == NULL)
4278     {
4279       path = gtk_tree_model_get_path (model, iter);
4280       free_path = TRUE;
4281     }
4282   else if (iter == NULL)
4283     gtk_tree_model_get_iter (model, iter, path);
4284
4285   /* Update all row-references */
4286   gtk_tree_row_reference_inserted (G_OBJECT (data), path);
4287
4288   depth = gtk_tree_path_get_depth (path);
4289   indices = gtk_tree_path_get_indices (path);
4290
4291   /* First, find the parent tree */
4292   while (i < depth - 1)
4293     {
4294       if (tmptree == NULL)
4295         {
4296           /* We aren't showing the node */
4297           goto done;
4298         }
4299
4300       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
4301       if (tmpnode == NULL)
4302         {
4303           g_warning ("A node was inserted with a parent that's not in the tree.\n" \
4304                      "This possibly means that a GtkTreeModel inserted a child node\n" \
4305                      "before the parent was inserted.");
4306           goto done;
4307         }
4308       else if (!GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_IS_PARENT))
4309         {
4310           /* FIXME enforce correct behavior on model, probably */
4311           /* In theory, the model should have emitted has_child_toggled here.  We
4312            * try to catch it anyway, just to be safe, in case the model hasn't.
4313            */
4314           GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
4315                                                            tree,
4316                                                            tmpnode);
4317           gtk_tree_view_has_child_toggled (model, tmppath, NULL, data);
4318           gtk_tree_path_free (tmppath);
4319           goto done;
4320         }
4321
4322       tmptree = tmpnode->children;
4323       tree = tmptree;
4324       i++;
4325     }
4326
4327   if (tree == NULL)
4328     goto done;
4329
4330   /* ref the node */
4331   gtk_tree_model_ref_node (tree_view->priv->model, iter);
4332   max_height = gtk_tree_view_insert_iter_height (tree_view,
4333                                                  tree,
4334                                                  iter,
4335                                                  depth);
4336   if (indices[depth - 1] == 0)
4337     {
4338       tmpnode = _gtk_rbtree_find_count (tree, 1);
4339       _gtk_rbtree_insert_before (tree, tmpnode, max_height);
4340     }
4341   else
4342     {
4343       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
4344       _gtk_rbtree_insert_after (tree, tmpnode, max_height);
4345     }
4346
4347   _gtk_tree_view_update_size (tree_view);
4348
4349  done:
4350   if (free_path)
4351     gtk_tree_path_free (path);
4352 }
4353
4354 static void
4355 gtk_tree_view_has_child_toggled (GtkTreeModel *model,
4356                                  GtkTreePath  *path,
4357                                  GtkTreeIter  *iter,
4358                                  gpointer      data)
4359 {
4360   GtkTreeView *tree_view = (GtkTreeView *)data;
4361   GtkTreeIter real_iter;
4362   gboolean has_child;
4363   GtkRBTree *tree;
4364   GtkRBNode *node;
4365   gboolean free_path = FALSE;
4366
4367   g_return_if_fail (path != NULL || iter != NULL);
4368
4369   if (iter)
4370     real_iter = *iter;
4371
4372   if (path == NULL)
4373     {
4374       path = gtk_tree_model_get_path (model, iter);
4375       free_path = TRUE;
4376     }
4377   else if (iter == NULL)
4378     gtk_tree_model_get_iter (model, &real_iter, path);
4379
4380   if (_gtk_tree_view_find_node (tree_view,
4381                                 path,
4382                                 &tree,
4383                                 &node))
4384     /* We aren't actually showing the node */
4385     goto done;
4386
4387   if (tree == NULL)
4388     goto done;
4389
4390   has_child = gtk_tree_model_iter_has_child (model, &real_iter);
4391   /* Sanity check.
4392    */
4393   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT) == has_child)
4394     goto done;
4395
4396   if (has_child)
4397     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PARENT);
4398   else
4399     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_PARENT);
4400
4401   if (has_child && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
4402     {
4403       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
4404       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
4405         {
4406           GList *list;
4407
4408           for (list = tree_view->priv->columns; list; list = list->next)
4409             if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
4410               {
4411                 GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
4412                 break;
4413               }
4414         }
4415       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4416     }
4417   else
4418     {
4419       /* FIXME: Just redraw the node */
4420       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4421     }
4422
4423  done:
4424   if (free_path)
4425     gtk_tree_path_free (path);
4426 }
4427
4428 static void
4429 count_children_helper (GtkRBTree *tree,
4430                        GtkRBNode *node,
4431                        gpointer   data)
4432 {
4433   if (node->children)
4434     _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, data);
4435   (*((gint *)data))++;
4436 }
4437
4438 static void
4439 gtk_tree_view_deleted (GtkTreeModel *model,
4440                        GtkTreePath  *path,
4441                        gpointer      data)
4442 {
4443   GtkTreeView *tree_view = (GtkTreeView *)data;
4444   GtkRBTree *tree;
4445   GtkRBNode *node;
4446   GList *list;
4447
4448   g_return_if_fail (path != NULL);
4449
4450   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
4451     return;
4452
4453   if (tree == NULL)
4454     return;
4455
4456   gtk_tree_row_reference_deleted (G_OBJECT (data), path);
4457
4458   /* Change the selection */
4459   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
4460     g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed");
4461
4462   for (list = tree_view->priv->columns; list; list = list->next)
4463     if (((GtkTreeViewColumn *)list->data)->visible &&
4464         ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
4465       ((GtkTreeViewColumn *)list->data)->dirty = TRUE;
4466
4467   /* Ensure we don't have a dangling pointer to a dead node */
4468   ensure_unprelighted (tree_view);
4469
4470   if (tree_view->priv->destroy_count_func)
4471     {
4472       gint child_count = 0;
4473       if (node->children)
4474         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
4475       (* tree_view->priv->destroy_count_func) (tree_view, path, child_count, tree_view->priv->destroy_count_data);
4476     }
4477
4478   if (tree->root->count == 1)
4479     {
4480       if (tree_view->priv->tree == tree)
4481         tree_view->priv->tree = NULL;
4482
4483       _gtk_rbtree_remove (tree);
4484     }
4485   else
4486     {
4487       _gtk_rbtree_remove_node (tree, node);
4488     }
4489
4490   _gtk_tree_view_update_size (GTK_TREE_VIEW (data));
4491 }
4492
4493
4494 static void
4495 gtk_tree_view_reordered (GtkTreeModel *model,
4496                          GtkTreePath  *parent,
4497                          GtkTreeIter  *iter,
4498                          gint         *new_order,
4499                          gpointer      data)
4500 {
4501   GtkTreeView *tree_view = GTK_TREE_VIEW (data);
4502   GtkRBTree *tree;
4503   GtkRBNode *node;
4504   gint len;
4505
4506   len = gtk_tree_model_iter_n_children (model, iter);
4507
4508   if (len < 2)
4509     return;
4510
4511   gtk_tree_row_reference_reordered (G_OBJECT (data),
4512                                     parent,
4513                                     iter,
4514                                     new_order);
4515
4516   if (_gtk_tree_view_find_node (tree_view,
4517                                 parent,
4518                                 &tree,
4519                                 &node))
4520     return;
4521
4522   /* We need to special case the parent path */
4523   if (tree == NULL)
4524     tree = tree_view->priv->tree;
4525   else
4526     tree = node->children;
4527
4528   if (tree == NULL)
4529     return;
4530
4531   /* FIXME: we need to unprelight our tree, if it's prelit. */
4532   _gtk_rbtree_reorder (tree, new_order, len);
4533
4534   gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4535 }
4536
4537
4538 /* Internal tree functions
4539  */
4540
4541
4542 static void
4543 gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
4544                                      GtkRBTree         *tree,
4545                                      GtkTreeViewColumn *column,
4546                                      gint              *x1,
4547                                      gint              *x2)
4548 {
4549   GtkTreeViewColumn *tmp_column = NULL;
4550   gint total_width;
4551   GList *list;
4552
4553   if (x1)
4554     *x1 = 0;
4555
4556   if (x2)
4557     *x2 = 0;
4558
4559   total_width = 0;
4560   for (list = tree_view->priv->columns; list; list = list->next)
4561     {
4562       tmp_column = list->data;
4563
4564       if (tmp_column == column)
4565         break;
4566
4567       if (tmp_column->visible)
4568         total_width += tmp_column->width;
4569     }
4570
4571   if (tmp_column != column)
4572     {
4573       g_warning (G_STRLOC": passed-in column isn't in the tree");
4574       return;
4575     }
4576
4577   if (x1)
4578     *x1 = total_width;
4579
4580   if (x2)
4581     {
4582       if (column->visible)
4583         *x2 = total_width + column->width;
4584       else
4585         *x2 = total_width; /* width of 0 */
4586     }
4587 }
4588
4589 static void
4590 gtk_tree_view_get_cell_xrange (GtkTreeView       *tree_view,
4591                                GtkRBTree         *tree,
4592                                GtkTreeViewColumn *column,
4593                                gint              *x1,
4594                                gint              *x2)
4595 {
4596   GtkTreeViewColumn *tmp_column = NULL;
4597   gint total_width;
4598   GList *list;
4599
4600   if (x1)
4601     *x1 = 0;
4602
4603   if (x2)
4604     *x2 = 0;
4605
4606   total_width = 0;
4607   for (list = tree_view->priv->columns; list; list = list->next)
4608     {
4609       tmp_column = list->data;
4610
4611       if (tmp_column == column)
4612         break;
4613
4614       if (tmp_column->visible)
4615         total_width += tmp_column->width;
4616     }
4617
4618   if (tmp_column != column)
4619     {
4620       g_warning (G_STRLOC": passed-in column isn't in the tree");
4621       return;
4622     }
4623
4624   /* Remember we're getting the cell range, i.e. the cell_area passed
4625    * to the cell renderer.
4626    */
4627
4628   if (gtk_tree_view_is_expander_column (tree_view, column))
4629     total_width += tree_view->priv->tab_offset * _gtk_rbtree_get_depth (tree);
4630
4631   if (x1)
4632     *x1 = total_width;
4633
4634   if (x2)
4635     {
4636       if (column->visible)
4637         *x2 = total_width + column->displayed_width;
4638       else
4639         *x2 = total_width; /* width of 0 */
4640     }
4641 }
4642
4643 static void
4644 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
4645                                 gint        *x1,
4646                                 gint        *x2)
4647 {
4648   gint x_offset = 0;
4649   GList *list;
4650   GtkTreeViewColumn *tmp_column = NULL;
4651   gint total_width;
4652
4653   total_width = 0;
4654   for (list = tree_view->priv->columns; list; list = list->next)
4655     {
4656       tmp_column = list->data;
4657
4658       if (gtk_tree_view_is_expander_column (tree_view, tmp_column))
4659         {
4660           x_offset = total_width;
4661           break;
4662         }
4663
4664       if (tmp_column->visible)
4665         total_width += tmp_column->width;
4666     }
4667
4668   if (x1)
4669     *x1 = x_offset;
4670
4671   if (tmp_column && tmp_column->visible)
4672     {
4673       /* +1 because x2 isn't included in the range. */
4674       if (x2)
4675         *x2 = x_offset + tree_view->priv->tab_offset + 1;
4676     }
4677   else
4678     {
4679       /* return an empty range, the expander column is hidden */
4680       if (x2)
4681         *x2 = x_offset;
4682     }
4683 }
4684
4685 static void
4686 gtk_tree_view_setup_model (GtkTreeView *tree_view)
4687 {
4688   GtkTreePath *path;
4689   GtkTreeIter iter;
4690
4691   tree_view->priv->tree = NULL;
4692
4693   g_signal_connect (tree_view->priv->model,
4694                     "range_changed",
4695                     (GCallback) gtk_tree_view_range_changed,
4696                     tree_view);
4697   g_signal_connect (tree_view->priv->model,
4698                     "inserted",
4699                     (GCallback) gtk_tree_view_inserted,
4700                     tree_view);
4701   g_signal_connect (tree_view->priv->model,
4702                     "has_child_toggled",
4703                     (GCallback) gtk_tree_view_has_child_toggled,
4704                     tree_view);
4705   g_signal_connect (tree_view->priv->model,
4706                     "deleted",
4707                     (GCallback) gtk_tree_view_deleted,
4708                     tree_view);
4709   g_signal_connect (tree_view->priv->model,
4710                     "reordered",
4711                     (GCallback) gtk_tree_view_reordered,
4712                     tree_view);
4713
4714   if (tree_view->priv->columns == NULL)
4715     return;
4716
4717   path = gtk_tree_path_new_root ();
4718
4719   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
4720     {
4721       tree_view->priv->tree = _gtk_rbtree_new ();
4722       gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE, GTK_WIDGET_REALIZED (tree_view));
4723     }
4724
4725   gtk_tree_path_free (path);
4726
4727   /*  FIXME: do I need to do this? gtk_tree_view_create_buttons (tree_view); */
4728
4729   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
4730 }
4731
4732 static gint
4733 gtk_tree_view_insert_iter_height (GtkTreeView *tree_view,
4734                                   GtkRBTree   *tree,
4735                                   GtkTreeIter *iter,
4736                                   gint         depth)
4737 {
4738   GtkTreeViewColumn *column;
4739   GList *list;
4740   gint max_height = 0;
4741   gint vertical_separator;
4742
4743   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
4744   /* do stuff with node */
4745   for (list = tree_view->priv->columns; list; list = list->next)
4746     {
4747       gint height = 0, width = 0;
4748       column = list->data;
4749
4750       if (!column->visible)
4751         continue;
4752
4753       if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
4754         continue;
4755
4756       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter);
4757
4758       gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height);
4759       max_height = MAX (max_height, vertical_separator + height);
4760
4761       if (gtk_tree_view_is_expander_column (tree_view, column) &&
4762           TREE_VIEW_DRAW_EXPANDERS (tree_view))
4763         _gtk_tree_view_column_set_width (column,
4764                                         MAX (column->width, depth * tree_view->priv->tab_offset + width));
4765       else
4766         _gtk_tree_view_column_set_width (column,
4767                                         MAX (column->width, width));
4768     }
4769   return max_height;
4770 }
4771
4772 static void
4773 gtk_tree_view_build_tree (GtkTreeView *tree_view,
4774                           GtkRBTree   *tree,
4775                           GtkTreeIter *iter,
4776                           gint         depth,
4777                           gboolean     recurse,
4778                           gboolean     calc_bounds)
4779 {
4780   GtkRBNode *temp = NULL;
4781   gint max_height;
4782
4783   do
4784     {
4785       max_height = 0;
4786       if (calc_bounds)
4787         max_height = gtk_tree_view_insert_iter_height (tree_view,
4788                                                        tree,
4789                                                        iter,
4790                                                        depth);
4791
4792       gtk_tree_model_ref_node (tree_view->priv->model, iter);
4793       temp = _gtk_rbtree_insert_after (tree, temp, max_height);
4794       if (recurse)
4795         {
4796           GtkTreeIter child;
4797
4798           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
4799             {
4800               temp->children = _gtk_rbtree_new ();
4801               temp->children->parent_tree = tree;
4802               temp->children->parent_node = temp;
4803               gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse, calc_bounds);
4804             }
4805         }
4806       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
4807         {
4808           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
4809             temp->flags ^= GTK_RBNODE_IS_PARENT;
4810           GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
4811         }
4812     }
4813   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
4814 }
4815
4816 static void
4817 gtk_tree_view_calc_size (GtkTreeView *tree_view,
4818                          GtkRBTree   *tree,
4819                          GtkTreeIter *iter,
4820                          gint         depth)
4821 {
4822   GtkRBNode *temp;
4823   GtkTreeIter child;
4824   GList *list;
4825   GtkTreeViewColumn *column;
4826   gint max_height;
4827   gint vertical_separator;
4828
4829   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
4830
4831   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
4832
4833   temp = tree->root;
4834   while (temp->left != tree->nil)
4835     temp = temp->left;
4836
4837   do
4838     {
4839       max_height = 0;
4840       /* Do stuff with node */
4841       for (list = tree_view->priv->columns; list; list = list->next)
4842         {
4843           gint height = 0, width = 0;
4844           column = list->data;
4845
4846           if (!column->visible)
4847             continue;
4848
4849           gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter);
4850           gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, &width, &height);
4851           max_height = MAX (max_height, vertical_separator + height);
4852
4853           /* FIXME: I'm getting the width of all nodes here. )-: */
4854           if (column->dirty == FALSE)
4855             continue;
4856
4857           if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
4858             {
4859               continue;
4860             }
4861           if (gtk_tree_view_is_expander_column (tree_view, column) &&
4862               TREE_VIEW_DRAW_EXPANDERS (tree_view))
4863             _gtk_tree_view_column_set_width (column,
4864                                             MAX (column->width, depth * tree_view->priv->tab_offset + width));
4865           else
4866             _gtk_tree_view_column_set_width (column, MAX (column->width, width));
4867         }
4868
4869       _gtk_rbtree_node_set_height (tree, temp, max_height);
4870
4871       if (temp->children != NULL &&
4872           gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
4873         gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
4874       temp = _gtk_rbtree_next (tree, temp);
4875     }
4876   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
4877 }
4878
4879 static gboolean
4880 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
4881                                    GtkTreeIter *iter,
4882                                    gint         depth,
4883                                    gint        *height)
4884 {
4885   GtkTreeViewColumn *column;
4886   GList *list;
4887   gboolean retval = FALSE;
4888   gint tmpheight;
4889
4890   if (height)
4891     *height = 0;
4892
4893   for (list = tree_view->priv->columns; list; list = list->next)
4894     {
4895       gint width;
4896       column = list->data;
4897       if (column->dirty == TRUE || column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
4898         continue;
4899       if (!column->visible)
4900         continue;
4901
4902       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, iter);
4903
4904       if (height)
4905         {
4906           gtk_tree_view_column_cell_get_size (column,
4907                                               NULL, NULL, NULL,
4908                                               &width, &tmpheight);
4909           *height = MAX (*height, tmpheight);
4910         }
4911       else
4912         {
4913           gtk_tree_view_column_cell_get_size (column,
4914                                               NULL, NULL, NULL,
4915                                               &width, NULL);
4916         }
4917       if (gtk_tree_view_is_expander_column (tree_view, column) &&
4918           TREE_VIEW_DRAW_EXPANDERS (tree_view))
4919         {
4920           if (depth * tree_view->priv->tab_offset + width > column->width)
4921             {
4922               column->dirty = TRUE;
4923               retval = TRUE;
4924             }
4925         }
4926       else
4927         {
4928           if (width > column->width)
4929             {
4930               column->dirty = TRUE;
4931               retval = TRUE;
4932             }
4933         }
4934     }
4935
4936   return retval;
4937 }
4938
4939 static void
4940 gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
4941                               GtkRBTree   *tree,
4942                               GtkTreeIter *iter,
4943                               gint         depth)
4944 {
4945   GtkRBNode *temp = tree->root;
4946   GtkTreeViewColumn *column;
4947   GList *list;
4948   GtkTreeIter child;
4949   gboolean is_all_dirty;
4950
4951   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
4952
4953   while (temp->left != tree->nil)
4954     temp = temp->left;
4955
4956   do
4957     {
4958       TREE_VIEW_INTERNAL_ASSERT_VOID (temp != NULL);
4959       is_all_dirty = TRUE;
4960       for (list = tree_view->priv->columns; list; list = list->next)
4961         {
4962           column = list->data;
4963           if (column->dirty == FALSE)
4964             {
4965               is_all_dirty = FALSE;
4966               break;
4967             }
4968         }
4969
4970       if (is_all_dirty)
4971         return;
4972
4973       gtk_tree_view_discover_dirty_iter (tree_view,
4974                                          iter,
4975                                          depth,
4976                                          FALSE);
4977       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
4978           temp->children != NULL)
4979         gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
4980       temp = _gtk_rbtree_next (tree, temp);
4981     }
4982   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
4983 }
4984
4985
4986 static void
4987 gtk_tree_view_check_dirty (GtkTreeView *tree_view)
4988 {
4989   GtkTreePath *path;
4990   gboolean dirty = FALSE;
4991   GList *list;
4992   GtkTreeViewColumn *column;
4993   GtkTreeIter iter;
4994
4995   if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) &&
4996       tree_view->priv->model)
4997     gtk_tree_view_setup_model (tree_view);
4998
4999   for (list = tree_view->priv->columns; list; list = list->next)
5000     {
5001       column = list->data;
5002       if (column->dirty)
5003         {
5004           dirty = TRUE;
5005           if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
5006             {
5007               gint w = 1;
5008
5009               if (column->button)
5010                 w = MAX (w, column->button->requisition.width);
5011
5012               _gtk_tree_view_column_set_width (column, w);
5013             }
5014         }
5015     }
5016
5017   if (dirty == FALSE)
5018     return;
5019
5020   if (tree_view->priv->model == NULL)
5021     return;
5022
5023   path = gtk_tree_path_new_root ();
5024   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
5025     {
5026       gtk_tree_view_calc_size (tree_view, tree_view->priv->tree, &iter, 1);
5027       _gtk_tree_view_update_size (tree_view);
5028     }
5029
5030   gtk_tree_path_free (path);
5031
5032   for (list = tree_view->priv->columns; list; list = list->next)
5033     {
5034       column = list->data;
5035       column->dirty = FALSE;
5036     }
5037 }
5038
5039 /* Make sure the node is visible vertically */
5040 static void
5041 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
5042                                   GtkRBTree   *tree,
5043                                   GtkRBNode   *node)
5044 {
5045   gint offset;
5046
5047   /* We process updates because we want to clear old selected items when we scroll.
5048    * if this is removed, we get a "selection streak" at the bottom. */
5049   if (GTK_WIDGET_REALIZED (tree_view))
5050     gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
5051
5052   offset = _gtk_rbtree_node_find_offset (tree, node);
5053
5054   /* we reverse the order, b/c in the unusual case of the
5055    * node's height being taller then the visible area, we'd rather
5056    * have the node flush to the top
5057    */
5058   if (offset + GTK_RBNODE_GET_HEIGHT (node) >
5059       tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size)
5060     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
5061                               offset + GTK_RBNODE_GET_HEIGHT (node) -
5062                               tree_view->priv->vadjustment->page_size);
5063   if (offset < tree_view->priv->vadjustment->value)
5064     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
5065                               offset);
5066
5067 }
5068
5069 /* This function could be more efficient.
5070  * I'll optimize it if profiling seems to imply that
5071  * it's important
5072  */
5073 GtkTreePath *
5074 _gtk_tree_view_find_path (GtkTreeView *tree_view,
5075                           GtkRBTree   *tree,
5076                           GtkRBNode   *node)
5077 {
5078   GtkTreePath *path;
5079   GtkRBTree *tmp_tree;
5080   GtkRBNode *tmp_node, *last;
5081   gint count;
5082
5083   path = gtk_tree_path_new ();
5084
5085   g_return_val_if_fail (node != NULL, path);
5086   g_return_val_if_fail (node != tree->nil, path);
5087
5088   count = 1 + node->left->count;
5089
5090   last = node;
5091   tmp_node = node->parent;
5092   tmp_tree = tree;
5093   while (tmp_tree)
5094     {
5095       while (tmp_node != tmp_tree->nil)
5096         {
5097           if (tmp_node->right == last)
5098             count += 1 + tmp_node->left->count;
5099           last = tmp_node;
5100           tmp_node = tmp_node->parent;
5101         }
5102       gtk_tree_path_prepend_index (path, count - 1);
5103       last = tmp_tree->parent_node;
5104       tmp_tree = tmp_tree->parent_tree;
5105       if (last)
5106         {
5107           count = 1 + last->left->count;
5108           tmp_node = last->parent;
5109         }
5110     }
5111   return path;
5112 }
5113
5114 /* Returns TRUE if we ran out of tree before finding the path.
5115  */
5116 gboolean
5117 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
5118                           GtkTreePath  *path,
5119                           GtkRBTree   **tree,
5120                           GtkRBNode   **node)
5121 {
5122   GtkRBNode *tmpnode = NULL;
5123   GtkRBTree *tmptree = tree_view->priv->tree;
5124   gint *indices = gtk_tree_path_get_indices (path);
5125   gint depth = gtk_tree_path_get_depth (path);
5126   gint i = 0;
5127
5128   *node = NULL;
5129   *tree = NULL;
5130
5131   if (depth == 0)
5132     return FALSE;
5133   do
5134     {
5135       if (tmptree == NULL)
5136         {
5137           *node = tmpnode;
5138           *tree = tmptree;
5139           return TRUE;
5140         }
5141       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
5142       ++i;
5143       if (i >= depth)
5144         {
5145           *node = tmpnode;
5146           *tree = tmptree;
5147           return FALSE;
5148         }
5149       tmptree = tmpnode->children;
5150     }
5151   while (1);
5152 }
5153
5154 static gboolean
5155 gtk_tree_view_is_expander_column (GtkTreeView       *tree_view,
5156                                   GtkTreeViewColumn *column)
5157 {
5158   GList *list;
5159
5160   if (tree_view->priv->expander_column != NULL)
5161     {
5162       if (tree_view->priv->expander_column == column)
5163         return TRUE;
5164       return FALSE;
5165     }
5166   else
5167     {
5168       for (list = tree_view->priv->columns; list; list = list->next)
5169         if (((GtkTreeViewColumn *)list->data)->visible)
5170           break;
5171       if (list && list->data == column)
5172         return TRUE;
5173     }
5174   return FALSE;
5175 }
5176
5177 static void
5178 gtk_tree_view_add_move_binding (GtkBindingSet  *binding_set,
5179                                 guint           keyval,
5180                                 guint           modmask,
5181                                 GtkMovementStep step,
5182                                 gint            count)
5183 {
5184
5185   gtk_binding_entry_add_signal (binding_set, keyval, modmask,
5186                                 "move_cursor", 2,
5187                                 GTK_TYPE_ENUM, step,
5188                                 GTK_TYPE_INT, count);
5189
5190   gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
5191                                 "move_cursor", 2,
5192                                 GTK_TYPE_ENUM, step,
5193                                 GTK_TYPE_INT, count);
5194
5195   if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
5196    return;
5197
5198   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
5199                                 "move_cursor", 2,
5200                                 GTK_TYPE_ENUM, step,
5201                                 GTK_TYPE_INT, count);
5202
5203   gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
5204                                 "move_cursor", 2,
5205                                 GTK_TYPE_ENUM, step,
5206                                 GTK_TYPE_INT, count);
5207 }
5208
5209 static gint
5210 gtk_tree_view_unref_tree_helper (GtkTreeModel *model,
5211                                  GtkTreeIter  *iter,
5212                                  GtkRBTree    *tree,
5213                                  GtkRBNode    *node)
5214 {
5215   gint retval = FALSE;
5216   do
5217     {
5218       g_return_val_if_fail (node != NULL, FALSE);
5219
5220       if (node->children)
5221         {
5222           GtkTreeIter child;
5223           GtkRBTree *new_tree;
5224           GtkRBNode *new_node;
5225
5226           new_tree = node->children;
5227           new_node = new_tree->root;
5228
5229           while (new_node && new_node->left != new_tree->nil)
5230             new_node = new_node->left;
5231
5232           g_return_val_if_fail (gtk_tree_model_iter_children (model, &child, iter), FALSE);
5233           retval = retval || gtk_tree_view_unref_tree_helper (model, &child, new_tree, new_node);
5234         }
5235
5236       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
5237         retval = TRUE;
5238       gtk_tree_model_unref_node (model, iter);
5239       node = _gtk_rbtree_next (tree, node);
5240     }
5241   while (gtk_tree_model_iter_next (model, iter));
5242
5243   return retval;
5244 }
5245
5246 static gint
5247 gtk_tree_view_unref_and_check_selection_tree (GtkTreeView *tree_view,
5248                                               GtkRBTree   *tree)
5249 {
5250   GtkTreeIter iter;
5251   GtkTreePath *path;
5252   GtkRBNode *node;
5253   gint retval;
5254
5255   node = tree->root;
5256   while (node && node->left != tree->nil)
5257     node = node->left;
5258
5259   g_return_val_if_fail (node != NULL, FALSE);
5260   path = _gtk_tree_view_find_path (tree_view, tree, node);
5261   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model),
5262                            &iter, path);
5263   retval = gtk_tree_view_unref_tree_helper (GTK_TREE_MODEL (tree_view->priv->model), &iter, tree, node);
5264   gtk_tree_path_free (path);
5265
5266   return retval;
5267 }
5268
5269 static void
5270 gtk_tree_view_set_column_drag_info (GtkTreeView       *tree_view,
5271                                     GtkTreeViewColumn *column)
5272 {
5273   GtkTreeViewColumn *left_column;
5274   GtkTreeViewColumn *cur_column = NULL;
5275   GtkTreeViewColumnReorder *reorder;
5276
5277   GList *tmp_list;
5278   gint left;
5279
5280   /* We want to precalculate the motion list such that we know what column slots
5281    * are available.
5282    */
5283   left_column = NULL;
5284
5285   /* First, identify all possible drop spots */
5286   tmp_list = tree_view->priv->columns;
5287
5288   while (tmp_list)
5289     {
5290       g_assert (tmp_list);
5291
5292       cur_column = GTK_TREE_VIEW_COLUMN (tmp_list->data);
5293       tmp_list = tmp_list->next;
5294
5295       if (cur_column->visible == FALSE)
5296         continue;
5297
5298       /* If it's not the column moving and func tells us to skip over the column, we continue. */
5299       if (left_column != column && cur_column != column &&
5300           tree_view->priv->column_drop_func &&
5301           ! (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data))
5302         {
5303           left_column = cur_column;
5304           continue;
5305         }
5306       reorder = g_new (GtkTreeViewColumnReorder, 1);
5307       reorder->left_column = left_column;
5308       left_column = reorder->right_column = cur_column;
5309
5310       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
5311     }
5312
5313   /* Add the last one */
5314   if (tree_view->priv->column_drop_func == NULL ||
5315       ((left_column != column) &&
5316        (* tree_view->priv->column_drop_func) (tree_view, column, left_column, cur_column, tree_view->priv->column_drop_func_data)))
5317     {
5318       reorder = g_new (GtkTreeViewColumnReorder, 1);
5319       reorder->left_column = left_column;
5320       reorder->right_column = NULL;
5321       tree_view->priv->column_drag_info = g_list_append (tree_view->priv->column_drag_info, reorder);
5322     }
5323
5324   /* We quickly check to see if it even makes sense to reorder columns. */
5325   /* If there is nothing that can be moved, then we return */
5326
5327   if (tree_view->priv->column_drag_info == NULL)
5328     return;
5329
5330   /* We know there are always 2 slots possbile, as you can always return column. */
5331   /* If that's all there is, return */
5332   if (tree_view->priv->column_drag_info->next->next == NULL &&
5333       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->data)->right_column == column &&
5334       ((GtkTreeViewColumnReorder *)tree_view->priv->column_drag_info->next->data)->left_column == column)
5335     {
5336       for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
5337         g_free (tmp_list->data);
5338       g_list_free (tree_view->priv->column_drag_info);
5339       tree_view->priv->column_drag_info = NULL;
5340       return;
5341     }
5342   /* We fill in the ranges for the columns, now that we've isolated them */
5343   left = - TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
5344
5345   for (tmp_list = tree_view->priv->column_drag_info; tmp_list; tmp_list = tmp_list->next)
5346     {
5347       reorder = (GtkTreeViewColumnReorder *) tmp_list->data;
5348
5349       reorder->left_align = left;
5350       if (tmp_list->next != NULL)
5351         {
5352           g_assert (tmp_list->next->data);
5353           left = reorder->right_align = (reorder->right_column->button->allocation.x +
5354                                          reorder->right_column->button->allocation.width +
5355                                          ((GtkTreeViewColumnReorder *)tmp_list->next->data)->left_column->button->allocation.x)/2;
5356         }
5357       else
5358         {
5359           gint width;
5360
5361           gdk_window_get_size (tree_view->priv->header_window, &width, NULL);
5362           reorder->right_align = width + TREE_VIEW_COLUMN_DRAG_DEAD_MULTIPLIER (tree_view);
5363         }
5364     }
5365 }
5366
5367 void
5368 _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
5369                                   GtkTreeViewColumn *column)
5370 {
5371   GdkEvent send_event;
5372   GtkAllocation allocation;
5373   gint x, y, width, height;
5374
5375   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
5376
5377   gtk_tree_view_set_column_drag_info (tree_view, column);
5378
5379   if (tree_view->priv->column_drag_info == NULL)
5380     return;
5381
5382   if (tree_view->priv->drag_window == NULL)
5383     {
5384       GdkWindowAttr attributes;
5385       guint attributes_mask;
5386
5387       attributes.window_type = GDK_WINDOW_CHILD;
5388       attributes.wclass = GDK_INPUT_OUTPUT;
5389       attributes.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
5390       attributes.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
5391       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
5392       attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
5393
5394       tree_view->priv->drag_window = gdk_window_new (tree_view->priv->bin_window,
5395                                                      &attributes,
5396                                                      attributes_mask);
5397       gdk_window_set_user_data (tree_view->priv->drag_window, GTK_WIDGET (tree_view));
5398     }
5399
5400   gdk_pointer_ungrab (GDK_CURRENT_TIME);
5401   gdk_keyboard_ungrab (GDK_CURRENT_TIME);
5402
5403   gtk_grab_remove (column->button);
5404
5405   send_event.crossing.type = GDK_LEAVE_NOTIFY;
5406   send_event.crossing.send_event = TRUE;
5407   send_event.crossing.window = column->button->window;
5408   send_event.crossing.subwindow = NULL;
5409   send_event.crossing.detail = GDK_NOTIFY_ANCESTOR;
5410   send_event.crossing.time = GDK_CURRENT_TIME;
5411
5412   gtk_propagate_event (column->button, &send_event);
5413
5414   send_event.button.type = GDK_BUTTON_RELEASE;
5415   send_event.button.window = GDK_ROOT_PARENT ();
5416   send_event.button.send_event = TRUE;
5417   send_event.button.time = GDK_CURRENT_TIME;
5418   send_event.button.x = -1;
5419   send_event.button.y = -1;
5420   send_event.button.axes = NULL;
5421   send_event.button.state = 0;
5422   send_event.button.button = 1;
5423   send_event.button.device = gdk_core_pointer;
5424   send_event.button.x_root = 0;
5425   send_event.button.y_root = 0;
5426
5427   gtk_propagate_event (column->button, &send_event);
5428
5429   gdk_window_move_resize (tree_view->priv->drag_window,
5430                           column->button->allocation.x,
5431                           column->button->allocation.y + column->button->allocation.height,
5432                           column->button->allocation.width,
5433                           column->button->allocation.height);
5434   gdk_window_reparent (column->button->window, tree_view->priv->drag_window, 0, 0);
5435   tree_view->priv->drag_column_x = column->button->allocation.x;
5436   allocation = column->button->allocation;
5437   allocation.x = 0;
5438   gtk_widget_size_allocate (column->button, &allocation);
5439   gtk_widget_set_parent_window (column->button, tree_view->priv->drag_window);
5440
5441   tree_view->priv->drag_column = column;
5442   gdk_window_show (tree_view->priv->drag_window);
5443
5444   gdk_window_get_origin (tree_view->priv->header_window, &x, &y);
5445   gdk_window_get_size (tree_view->priv->header_window, &width, &height);
5446
5447   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5448   while (gtk_events_pending ())
5449     gtk_main_iteration ();
5450
5451   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_DRAG);
5452   gdk_pointer_grab (tree_view->priv->drag_window,
5453                     FALSE,
5454                     GDK_POINTER_MOTION_MASK|GDK_BUTTON_RELEASE_MASK,
5455                     NULL, NULL, GDK_CURRENT_TIME);
5456   gdk_keyboard_grab (tree_view->priv->drag_window,
5457                      FALSE,
5458                      GDK_CURRENT_TIME);
5459
5460 }
5461
5462 static void
5463 gtk_tree_view_queue_draw_node (GtkTreeView  *tree_view,
5464                                GtkRBTree    *tree,
5465                                GtkRBNode    *node,
5466                                GdkRectangle *clip_rect)
5467 {
5468   GdkRectangle rect;
5469
5470   if (!GTK_WIDGET_REALIZED (tree_view))
5471     return;
5472
5473   rect.x = 0;
5474   rect.width = MAX (tree_view->priv->width, GTK_WIDGET (tree_view)->allocation.width);
5475
5476   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
5477   rect.height = BACKGROUND_HEIGHT (node);
5478
5479   if (clip_rect)
5480     {
5481       GdkRectangle new_rect;
5482
5483       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
5484
5485       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
5486     }
5487   else
5488     {
5489       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
5490     }
5491 }
5492
5493 static void
5494 gtk_tree_view_queue_draw_path (GtkTreeView      *tree_view,
5495                                GtkTreePath      *path,
5496                                GdkRectangle     *clip_rect)
5497 {
5498   GtkRBTree *tree = NULL;
5499   GtkRBNode *node = NULL;
5500
5501   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
5502
5503   if (tree)
5504     gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
5505 }
5506
5507 /* x and y are the mouse position
5508  */
5509 static void
5510 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
5511                           GtkRBTree   *tree,
5512                           GtkRBNode   *node,
5513                           gint         x,
5514                           gint         y)
5515 {
5516   GdkRectangle area;
5517   GtkStateType state;
5518   GtkWidget *widget;
5519   gint x_offset = 0;
5520   gint vertical_separator;
5521   gint expander_height;
5522
5523   gtk_widget_style_get (GTK_WIDGET (tree_view),
5524                         "vertical_separator", &vertical_separator,
5525                         "expander_height", &expander_height,
5526                         NULL);
5527
5528   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
5529     return;
5530
5531   widget = GTK_WIDGET (tree_view);
5532
5533   gtk_tree_view_get_arrow_xrange (tree_view, &x_offset, NULL);
5534
5535   area.x = x_offset;
5536   area.y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
5537   area.width = tree_view->priv->tab_offset - 2;
5538   area.height = CELL_HEIGHT (node, vertical_separator);
5539
5540   if (node == tree_view->priv->button_pressed_node)
5541     {
5542       if (x >= area.x && x <= (area.x + area.width) &&
5543           y >= area.y && y <= (area.y + area.height))
5544         state = GTK_STATE_ACTIVE;
5545       else
5546         state = GTK_STATE_NORMAL;
5547     }
5548   else
5549     {
5550       if (node == tree_view->priv->prelight_node &&
5551           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
5552         state = GTK_STATE_PRELIGHT;
5553       else
5554         state = GTK_STATE_NORMAL;
5555     }
5556
5557   gtk_paint_expander (widget->style,
5558                       tree_view->priv->bin_window,
5559                       state,
5560                       &area,
5561                       widget,
5562                       "treeview",
5563                       area.x,
5564                       (area.y + (area.height - expander_height) / 2 - (area.height + 1) % 2),
5565                       node->children != NULL);
5566 }
5567
5568
5569 static void
5570 _gtk_tree_view_update_col_width (GtkTreeView *tree_view)
5571 {
5572   GList *list, *last_column;
5573   GtkTreeViewColumn *column;
5574   gint width = 0;
5575
5576   for (last_column = g_list_last (tree_view->priv->columns);
5577        last_column &&
5578          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
5579          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
5580        last_column = last_column->prev)
5581     ;
5582
5583   if (last_column == NULL)
5584     return;
5585
5586   for (list = tree_view->priv->columns; list != last_column; list = list->next)
5587     {
5588       column = GTK_TREE_VIEW_COLUMN (list->data);
5589       if (! column->visible)
5590         continue;
5591
5592       width += column->width;
5593       column->displayed_width = (CLAMP (column->width, (column->min_width!=-1)?column->min_width:column->width, (column->max_width!=-1)?column->max_width:column->width));
5594     }
5595   column = GTK_TREE_VIEW_COLUMN (last_column->data);
5596   column->displayed_width = MAX (GTK_WIDGET (tree_view)->allocation.width, tree_view->priv->width) - width;
5597 }
5598
5599 static void
5600 gtk_tree_view_focus_to_cursor (GtkTreeView *tree_view)
5601
5602 {
5603   GtkTreePath *cursor_path;
5604
5605   if ((tree_view->priv->tree == NULL) ||
5606       (! GTK_WIDGET_REALIZED (tree_view)))
5607     return;
5608
5609   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
5610   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5611
5612   cursor_path = NULL;
5613   if (tree_view->priv->cursor)
5614     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5615
5616   if (cursor_path == NULL)
5617     {
5618       GtkTreePath *tmp_path = gtk_tree_path_new_root ();
5619       /* FIXME: Get the first one visible!!! */
5620       if (tree_view->priv->cursor)
5621         gtk_tree_row_reference_free (tree_view->priv->cursor);
5622
5623       tree_view->priv->cursor =
5624         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path);
5625       cursor_path = tmp_path;
5626     }
5627
5628   if (tree_view->priv->selection->type == GTK_TREE_SELECTION_SINGLE)
5629     gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
5630   else
5631     gtk_tree_view_real_set_cursor (tree_view, cursor_path, FALSE);
5632   gtk_tree_path_free (cursor_path);
5633 }
5634
5635 static void
5636 gtk_tree_view_move_cursor_up_down (GtkTreeView *tree_view,
5637                                    gint         count)
5638 {
5639   GtkRBTree *cursor_tree = NULL;
5640   GtkRBNode *cursor_node = NULL;
5641   GtkRBTree *new_cursor_tree = NULL;
5642   GtkRBNode *new_cursor_node = NULL;
5643   GtkTreePath *cursor_path = NULL;
5644
5645   cursor_path = NULL;
5646   if (!gtk_tree_row_reference_valid (tree_view->priv->cursor))
5647     return;
5648
5649   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5650   _gtk_tree_view_find_node (tree_view, cursor_path,
5651                             &cursor_tree, &cursor_node);
5652   gtk_tree_path_free (cursor_path);
5653
5654   if (count == -1)
5655     _gtk_rbtree_prev_full (cursor_tree, cursor_node,
5656                            &new_cursor_tree, &new_cursor_node);
5657   else
5658     _gtk_rbtree_next_full (cursor_tree, cursor_node,
5659                            &new_cursor_tree, &new_cursor_node);
5660
5661   if (new_cursor_node)
5662     {
5663       cursor_path = _gtk_tree_view_find_path (tree_view, new_cursor_tree, new_cursor_node);
5664       gtk_tree_view_real_set_cursor (tree_view, cursor_path, TRUE);
5665       gtk_tree_path_free (cursor_path);
5666     }
5667   else
5668     {
5669       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
5670     }
5671
5672   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5673 }
5674
5675 static void
5676 gtk_tree_view_move_cursor_page_up_down (GtkTreeView *tree_view,
5677                                         gint         count)
5678 {
5679   GtkRBTree *cursor_tree = NULL;
5680   GtkRBNode *cursor_node = NULL;
5681   GtkTreePath *cursor_path = NULL;
5682   gint y;
5683   gint vertical_separator;
5684
5685   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
5686     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5687   else
5688     /* This is sorta weird.  Focus in should give us a cursor */
5689     return;
5690
5691   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
5692   _gtk_tree_view_find_node (tree_view, cursor_path,
5693                             &cursor_tree, &cursor_node);
5694
5695   gtk_tree_path_free (cursor_path);
5696
5697   g_return_if_fail (cursor_node != NULL);
5698
5699   y = CELL_FIRST_PIXEL (tree_view, cursor_tree, cursor_node, vertical_separator);
5700   y += count * tree_view->priv->vadjustment->page_size;
5701   y = CLAMP (y, (gint)tree_view->priv->vadjustment->lower,  (gint)tree_view->priv->vadjustment->upper - vertical_separator);
5702
5703   _gtk_rbtree_find_offset (tree_view->priv->tree, y, &cursor_tree, &cursor_node);
5704   cursor_path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
5705   g_return_if_fail (cursor_path != NULL);
5706   gtk_tree_view_real_set_cursor (tree_view,
5707                                  cursor_path,
5708                                  TRUE);
5709 }
5710
5711 static void
5712 gtk_tree_view_move_cursor_left_right (GtkTreeView *tree_view,
5713                                       gint         count)
5714 {
5715   GtkRBTree *cursor_tree = NULL;
5716   GtkRBNode *cursor_node = NULL;
5717   GtkTreePath *cursor_path = NULL;
5718
5719   g_print ("gtk_tree_view_move_cursor_left_right\n");
5720
5721   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
5722     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5723   else
5724     return;
5725
5726   _gtk_tree_view_find_node (tree_view, cursor_path,
5727                             &cursor_tree, &cursor_node);
5728   gtk_tree_path_free (cursor_path);
5729
5730
5731 }
5732
5733 static void
5734 gtk_tree_view_move_cursor_start_end (GtkTreeView *tree_view,
5735                                      gint         count)
5736 {
5737   GtkRBTree *cursor_tree;
5738   GtkRBNode *cursor_node;
5739   GtkTreePath *path;
5740
5741   g_return_if_fail (tree_view->priv->tree != NULL);
5742
5743   if (count == -1)
5744     {
5745       cursor_tree = tree_view->priv->tree;
5746       cursor_node = cursor_tree->root;
5747       while (cursor_node && cursor_node->left != cursor_tree->nil)
5748         cursor_node = cursor_node->left;
5749     }
5750   else
5751     {
5752       cursor_tree = tree_view->priv->tree;
5753       cursor_node = cursor_tree->root;
5754       do
5755         {
5756           while (cursor_node && cursor_node->right != cursor_tree->nil)
5757             cursor_node = cursor_node->right;
5758           if (cursor_node->children == NULL)
5759             break;
5760
5761           cursor_tree = cursor_node->children;
5762           cursor_node = cursor_tree->root;
5763         }
5764       while (1);
5765     }
5766
5767   path = _gtk_tree_view_find_path (tree_view, cursor_tree, cursor_node);
5768   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
5769                                             cursor_node,
5770                                             cursor_tree,
5771                                             path,
5772                                             FALSE?GDK_SHIFT_MASK:0);
5773
5774   gtk_tree_row_reference_free (tree_view->priv->cursor);
5775   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
5776   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
5777 }
5778
5779 static void
5780 gtk_tree_view_real_select_cursor_row (GtkTreeView *tree_view)
5781 {
5782   GtkRBTree *cursor_tree = NULL;
5783   GtkRBNode *cursor_node = NULL;
5784   GtkTreePath *cursor_path = NULL;
5785
5786   cursor_path = NULL;
5787   if (tree_view->priv->cursor)
5788     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5789
5790   if (cursor_path == NULL)
5791     return;
5792
5793   _gtk_tree_view_find_node (tree_view, cursor_path,
5794                             &cursor_tree, &cursor_node);
5795   if (cursor_tree == NULL)
5796     return;
5797
5798   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
5799                                             cursor_node,
5800                                             cursor_tree,
5801                                             cursor_path,
5802                                             0);
5803
5804   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
5805
5806   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5807   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
5808   gtk_tree_path_free (cursor_path);
5809 }
5810
5811 static void
5812 gtk_tree_view_real_toggle_cursor_row (GtkTreeView *tree_view)
5813 {
5814   GtkRBTree *cursor_tree = NULL;
5815   GtkRBNode *cursor_node = NULL;
5816   GtkTreePath *cursor_path = NULL;
5817
5818   cursor_path = NULL;
5819   if (tree_view->priv->cursor)
5820     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5821
5822   if (cursor_path == NULL)
5823     return;
5824
5825   _gtk_tree_view_find_node (tree_view, cursor_path,
5826                             &cursor_tree, &cursor_node);
5827   if (cursor_tree == NULL)
5828     return;
5829
5830   _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
5831                                             cursor_node,
5832                                             cursor_tree,
5833                                             cursor_path,
5834                                             GDK_CONTROL_MASK);
5835
5836   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
5837
5838   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5839   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
5840   gtk_tree_path_free (cursor_path);
5841 }
5842
5843
5844
5845 static void
5846 gtk_tree_view_real_expand_collapse_cursor_row (GtkTreeView *tree_view,
5847                                                gboolean     logical,
5848                                                gboolean     expand,
5849                                                gboolean     open_all)
5850 {
5851   GtkTreePath *cursor_path = NULL;
5852
5853   cursor_path = NULL;
5854   if (tree_view->priv->cursor)
5855     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5856
5857   if (cursor_path == NULL)
5858     return;
5859
5860   if (expand)
5861     gtk_tree_view_expand_row (tree_view, cursor_path, open_all);
5862   else
5863     gtk_tree_view_collapse_row (tree_view, cursor_path);
5864
5865   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5866   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
5867   gtk_tree_path_free (cursor_path);
5868 }
5869
5870 static void
5871 gtk_tree_view_real_select_cursor_parent (GtkTreeView *tree_view)
5872 {
5873   GtkRBTree *cursor_tree = NULL;
5874   GtkRBNode *cursor_node = NULL;
5875   GtkTreePath *cursor_path = NULL;
5876
5877   cursor_path = NULL;
5878   if (tree_view->priv->cursor)
5879     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
5880
5881   if (cursor_path == NULL)
5882     return;
5883
5884   _gtk_tree_view_find_node (tree_view, cursor_path,
5885                             &cursor_tree, &cursor_node);
5886   if (cursor_tree == NULL)
5887     return;
5888
5889   if (cursor_tree->parent_node)
5890     {
5891       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
5892       cursor_node = cursor_tree->parent_node;
5893       cursor_tree = cursor_tree->parent_tree;
5894
5895       gtk_tree_path_up (cursor_path);
5896       gtk_tree_row_reference_free (tree_view->priv->cursor);
5897       tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
5898       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
5899                                                 cursor_node,
5900                                                 cursor_tree,
5901                                                 cursor_path,
5902                                                 0);
5903     }
5904
5905   gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
5906
5907   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
5908   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
5909   gtk_tree_path_free (cursor_path);
5910 }
5911
5912 void
5913 _gtk_tree_view_update_size (GtkTreeView *tree_view)
5914 {
5915   gint width, height;
5916   GList *list;
5917   GtkTreeViewColumn *column;
5918   gint vertical_separator;
5919   gint i;
5920
5921   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
5922
5923   if (tree_view->priv->model == NULL)
5924     {
5925       tree_view->priv->width = 0;
5926       tree_view->priv->height = 0;
5927       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
5928       return;
5929     }
5930
5931   width = 0;
5932   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
5933     {
5934       column = list->data;
5935       if (!column->visible)
5936         continue;
5937       width += TREE_VIEW_COLUMN_WIDTH (column);
5938     }
5939
5940   if (tree_view->priv->tree == NULL)
5941     height = 0;
5942   else
5943     height = tree_view->priv->tree->root->offset + vertical_separator;
5944
5945   if (tree_view->priv->width != width)
5946     {
5947       tree_view->priv->width = width;
5948       tree_view->priv->hadjustment->upper = width;
5949       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
5950     }
5951
5952   if (tree_view->priv->height != height)
5953     {
5954       tree_view->priv->height = height;
5955       tree_view->priv->vadjustment->upper = tree_view->priv->height;
5956       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
5957     }
5958
5959   if (GTK_WIDGET_REALIZED (tree_view))
5960     {
5961       gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view));
5962       gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height);
5963
5964       _gtk_tree_view_update_col_width (tree_view);
5965     }
5966
5967   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
5968 }
5969
5970 /* this function returns the new width of the column being resized given
5971  * the column and x position of the cursor; the x cursor position is passed
5972  * in as a pointer and automagicly corrected if it's beyond min/max limits
5973  */
5974 static gint
5975 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
5976                                 gint       i,
5977                                 gint      *x)
5978 {
5979   GtkTreeViewColumn *column;
5980   gint width;
5981
5982   /* first translate the x position from widget->window
5983    * to clist->clist_window
5984    */
5985
5986   column = g_list_nth (tree_view->priv->columns, i)->data;
5987   width = *x - column->button->allocation.x;
5988
5989   /* Clamp down the value */
5990   if (column->min_width == -1)
5991     width = MAX (column->button->requisition.width,
5992                  width);
5993   else
5994     width = MAX (column->min_width,
5995                  width);
5996   if (column->max_width != -1)
5997     width = MIN (width, column->max_width != -1);
5998   *x = column->button->allocation.x + width;
5999
6000   return width;
6001 }
6002
6003
6004 /* Callbacks */
6005 static void
6006 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
6007                                   GtkTreeView   *tree_view)
6008 {
6009   if (GTK_WIDGET_REALIZED (tree_view))
6010     {
6011       gdk_window_move (tree_view->priv->bin_window,
6012                        - tree_view->priv->hadjustment->value,
6013                        - tree_view->priv->vadjustment->value);
6014       gdk_window_move (tree_view->priv->header_window,
6015                        - tree_view->priv->hadjustment->value,
6016                        0);
6017
6018       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
6019       gdk_window_process_updates (tree_view->priv->header_window, TRUE);
6020     }
6021 }
6022
6023 \f
6024
6025 /* Public methods
6026  */
6027
6028 /**
6029  * gtk_tree_view_new:
6030  *
6031  * Creates a new #GtkTreeView widget.
6032  *
6033  * Return value: A newly created #GtkTreeView widget.
6034  **/
6035 GtkWidget *
6036 gtk_tree_view_new (void)
6037 {
6038   GtkTreeView *tree_view;
6039
6040   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
6041
6042   return GTK_WIDGET (tree_view);
6043 }
6044
6045 /**
6046  * gtk_tree_view_new_with_model:
6047  * @model: the model.
6048  *
6049  * Creates a new #GtkTreeView widget with the model initialized to @model.
6050  *
6051  * Return value: A newly created #GtkTreeView widget.
6052  **/
6053 GtkWidget *
6054 gtk_tree_view_new_with_model (GtkTreeModel *model)
6055 {
6056   GtkTreeView *tree_view;
6057
6058   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
6059   gtk_tree_view_set_model (tree_view, model);
6060
6061   return GTK_WIDGET (tree_view);
6062 }
6063
6064 /* Public Accessors
6065  */
6066
6067 /**
6068  * gtk_tree_view_get_model:
6069  * @tree_view: a #GtkTreeView
6070  *
6071  * Returns the model the the #GtkTreeView is based on.  Returns NULL if the
6072  * model is unset.
6073  *
6074  * Return value: A #GtkTreeModel, or NULL if none is currently being used.
6075  **/
6076 GtkTreeModel *
6077 gtk_tree_view_get_model (GtkTreeView *tree_view)
6078 {
6079   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6080
6081   return tree_view->priv->model;
6082 }
6083
6084 /**
6085  * gtk_tree_view_set_model:
6086  * @tree_view: A #GtkTreeNode.
6087  * @model: The model.
6088  *
6089  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
6090  * set, it will remove it before setting the new model.  If @model is NULL, then
6091  * it will unset the old model.
6092  **/
6093 void
6094 gtk_tree_view_set_model (GtkTreeView  *tree_view,
6095                          GtkTreeModel *model)
6096 {
6097   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6098
6099   if (model == tree_view->priv->model)
6100     return;
6101
6102   if (model != NULL)
6103     g_object_ref (model);
6104
6105   if (tree_view->priv->model != NULL)
6106     {
6107       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
6108         {
6109           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
6110                                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
6111                                                 0, 0, NULL,
6112                                                 gtk_tree_view_range_changed, tree_view);
6113           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
6114                                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
6115                                                 0, 0, NULL,
6116                                                 gtk_tree_view_inserted, tree_view);
6117           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
6118                                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
6119                                                 0, 0, NULL,
6120                                                 gtk_tree_view_has_child_toggled, tree_view);
6121           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
6122                                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
6123                                                 0, 0, NULL,
6124                                                 gtk_tree_view_deleted, tree_view);
6125           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
6126                                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
6127                                                 0, 0, NULL,
6128                                                 gtk_tree_view_reordered, tree_view);
6129           if (tree_view->priv->tree)
6130             _gtk_rbtree_free (tree_view->priv->tree);
6131         }
6132
6133       if (tree_view->priv->drag_dest_row)
6134         gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
6135
6136       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
6137       g_object_unref (tree_view->priv->model);
6138     }
6139
6140   tree_view->priv->model = model;
6141
6142   if (model == NULL)
6143     {
6144       tree_view->priv->tree = NULL;
6145       if (GTK_WIDGET_REALIZED (tree_view))
6146         _gtk_tree_view_update_size (tree_view);
6147     }
6148   else if (GTK_WIDGET_REALIZED (tree_view))
6149     {
6150       gtk_tree_view_setup_model (tree_view);
6151       _gtk_tree_view_update_size (tree_view);
6152     }
6153
6154   g_object_notify (G_OBJECT (tree_view), "model");
6155 }
6156
6157 /**
6158  * gtk_tree_view_get_selection:
6159  * @tree_view: A #GtkTreeView.
6160  *
6161  * Gets the #GtkTreeSelection associated with @tree_view.
6162  *
6163  * Return value: A #GtkTreeSelection object.
6164  **/
6165 GtkTreeSelection *
6166 gtk_tree_view_get_selection (GtkTreeView *tree_view)
6167 {
6168   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6169
6170   return tree_view->priv->selection;
6171 }
6172
6173 /**
6174  * gtk_tree_view_get_hadjustment:
6175  * @tree_view: A #GtkTreeView
6176  *
6177  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
6178  *
6179  * Return value: A #GtkAdjustment object, or NULL if none is currently being
6180  * used.
6181  **/
6182 GtkAdjustment *
6183 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
6184 {
6185   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6186
6187   if (tree_view->priv->hadjustment == NULL)
6188     gtk_tree_view_set_hadjustment (tree_view, NULL);
6189
6190   return tree_view->priv->hadjustment;
6191 }
6192
6193 /**
6194  * gtk_tree_view_set_hadjustment:
6195  * @tree_view: A #GtkTreeView
6196  * @adjustment: The #GtkAdjustment to set, or NULL
6197  *
6198  * Sets the #GtkAdjustment for the current horizontal aspect.
6199  **/
6200 void
6201 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
6202                                GtkAdjustment *adjustment)
6203 {
6204   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6205
6206   gtk_tree_view_set_adjustments (tree_view,
6207                                  adjustment,
6208                                  tree_view->priv->vadjustment);
6209
6210   g_object_notify (G_OBJECT (tree_view), "hadjustment");
6211 }
6212
6213 /**
6214  * gtk_tree_view_get_vadjustment:
6215  * @tree_view: A #GtkTreeView
6216  *
6217  * Gets the #GtkAdjustment currently being used for the vertical aspect.
6218  *
6219  * Return value: A #GtkAdjustment object, or NULL if none is currently being
6220  * used.
6221  **/
6222 GtkAdjustment *
6223 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
6224 {
6225   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6226
6227   if (tree_view->priv->vadjustment == NULL)
6228     gtk_tree_view_set_vadjustment (tree_view, NULL);
6229
6230   return tree_view->priv->vadjustment;
6231 }
6232
6233 /**
6234  * gtk_tree_view_set_vadjustment:
6235  * @tree_view: A #GtkTreeView
6236  * @adjustment: The #GtkAdjustment to set, or NULL
6237  *
6238  * Sets the #GtkAdjustment for the current vertical aspect.
6239  **/
6240 void
6241 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
6242                                GtkAdjustment *adjustment)
6243 {
6244   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6245
6246   gtk_tree_view_set_adjustments (tree_view,
6247                                  tree_view->priv->hadjustment,
6248                                  adjustment);
6249
6250   g_object_notify (G_OBJECT (tree_view), "vadjustment");
6251 }
6252
6253 /* Column and header operations */
6254
6255 /**
6256  * gtk_tree_view_get_headers_visible:
6257  * @tree_view: A #GtkTreeView.
6258  *
6259  * Returns TRUE if the headers on the @tree_view are visible.
6260  *
6261  * Return value: Whether the headers are visible or not.
6262  **/
6263 gboolean
6264 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
6265 {
6266   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
6267
6268   return GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
6269 }
6270
6271 /**
6272  * gtk_tree_view_set_headers_visible:
6273  * @tree_view: A #GtkTreeView.
6274  * @headers_visible: TRUE if the headers are visible
6275  *
6276  * Sets the the visibility state of the headers.
6277  **/
6278 void
6279 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
6280                                    gboolean     headers_visible)
6281 {
6282   gint x, y;
6283   GList *list;
6284   GtkTreeViewColumn *column;
6285
6286   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6287
6288   headers_visible = !! headers_visible;
6289
6290   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) == headers_visible)
6291     return;
6292
6293   if (headers_visible)
6294     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
6295   else
6296     GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
6297
6298   if (GTK_WIDGET_REALIZED (tree_view))
6299     {
6300       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
6301       if (headers_visible)
6302         {
6303           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view));
6304
6305           if (GTK_WIDGET_MAPPED (tree_view))
6306             gtk_tree_view_map_buttons (tree_view);
6307         }
6308       else
6309         {
6310           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
6311
6312           for (list = tree_view->priv->columns; list; list = list->next)
6313             {
6314               column = list->data;
6315               gtk_widget_unmap (column->button);
6316             }
6317           gdk_window_hide (tree_view->priv->header_window);
6318         }
6319     }
6320
6321   tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
6322   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
6323   tree_view->priv->vadjustment->lower = 0;
6324   tree_view->priv->vadjustment->upper = tree_view->priv->height;
6325   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
6326
6327   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6328
6329   g_object_notify (G_OBJECT (tree_view), "headers_visible");
6330 }
6331
6332
6333 /**
6334  * gtk_tree_view_columns_autosize:
6335  * @tree_view: A #GtkTreeView.
6336  *
6337  * Resizes all columns to their optimal width.
6338  **/
6339 void
6340 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
6341 {
6342   gboolean dirty = FALSE;
6343   GList *list;
6344   GtkTreeViewColumn *column;
6345
6346   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6347
6348   for (list = tree_view->priv->columns; list; list = list->next)
6349     {
6350       column = list->data;
6351       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
6352         continue;
6353       column->dirty = TRUE;
6354       dirty = TRUE;
6355     }
6356
6357   if (dirty)
6358     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6359 }
6360
6361 /**
6362  * gtk_tree_view_set_headers_clickable:
6363  * @tree_view: A #GtkTreeView.
6364  * @setting: TRUE if the columns are clickable.
6365  *
6366  * Allow the column title buttons to be clicked.
6367  **/
6368 void
6369 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
6370                                      gboolean   setting)
6371 {
6372   GList *list;
6373
6374   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6375   g_return_if_fail (tree_view->priv->model != NULL);
6376
6377   for (list = tree_view->priv->columns; list; list = list->next)
6378     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
6379
6380   g_object_notify (G_OBJECT (tree_view), "headers_clickable");
6381 }
6382
6383
6384 /**
6385  * gtk_tree_view_set_rules_hint
6386  * @tree_view: a #GtkTreeView
6387  * @setting: %TRUE if the tree requires reading across rows
6388  *
6389  * This function tells GTK+ that the user interface for your
6390  * application requires users to read across tree rows and associate
6391  * cells with one another. By default, GTK+ will then render the tree
6392  * with alternating row colors. <emphasis>DO NOT</emphasis> use it
6393  * just because you prefer the appearance of the ruled tree; that's a
6394  * question for the theme. Some themes will draw tree rows in
6395  * alternating colors even when rules are turned off, and users who
6396  * prefer that appearance all the time can choose those themes. You
6397  * should call this function only as a <emphasis>semantic</emphasis>
6398  * hint to the theme engine that your tree makes alternating colors
6399  * useful from a functional standpoint (since it has lots of columns,
6400  * generally).
6401  *
6402  **/
6403 void
6404 gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
6405                               gboolean      setting)
6406 {
6407   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6408
6409   setting = setting != FALSE;
6410
6411   if (tree_view->priv->has_rules != setting)
6412     {
6413       tree_view->priv->has_rules = setting;
6414       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
6415     }
6416
6417   g_object_notify (G_OBJECT (tree_view), "rules_hint");
6418 }
6419
6420 /**
6421  * gtk_tree_view_get_rules_hint
6422  * @tree_view: a #GtkTreeView
6423  *
6424  * Gets the setting set by gtk_tree_view_set_rules_hint().
6425  *
6426  * Return value: %TRUE if rules are useful for the user of this tree
6427  **/
6428 gboolean
6429 gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
6430 {
6431   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
6432
6433   return tree_view->priv->has_rules;
6434 }
6435
6436 /* Public Column functions
6437  */
6438
6439 /**
6440  * gtk_tree_view_append_column:
6441  * @tree_view: A #GtkTreeView.
6442  * @column: The #GtkTreeViewColumn to add.
6443  *
6444  * Appends @column to the list of columns.
6445  *
6446  * Return value: The number of columns in @tree_view after appending.
6447  **/
6448 gint
6449 gtk_tree_view_append_column (GtkTreeView       *tree_view,
6450                              GtkTreeViewColumn *column)
6451 {
6452   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
6453   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
6454   g_return_val_if_fail (column->tree_view == NULL, -1);
6455
6456   return gtk_tree_view_insert_column (tree_view, column, -1);
6457 }
6458
6459
6460 /**
6461  * gtk_tree_view_remove_column:
6462  * @tree_view: A #GtkTreeView.
6463  * @column: The #GtkTreeViewColumn to remove.
6464  *
6465  * Removes @column from @tree_view.
6466  *
6467  * Return value: The number of columns in @tree_view after removing.
6468  **/
6469 gint
6470 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
6471                              GtkTreeViewColumn *column)
6472 {
6473   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
6474   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
6475   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
6476
6477   _gtk_tree_view_column_unset_tree_view (column);
6478
6479   if (tree_view->priv->focus_column == column)
6480     tree_view->priv->focus_column = NULL;
6481
6482   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
6483   tree_view->priv->n_columns--;
6484
6485   if (GTK_WIDGET_REALIZED (tree_view))
6486     {
6487       GList *list;
6488
6489       _gtk_tree_view_column_unrealize_button (column);
6490       for (list = tree_view->priv->columns; list; list = list->next)
6491         {
6492           column = GTK_TREE_VIEW_COLUMN (list->data);
6493           if (column->visible)
6494             column->dirty = TRUE;
6495         }
6496
6497       if (tree_view->priv->n_columns == 0 &&
6498           gtk_tree_view_get_headers_visible (tree_view))
6499         gdk_window_hide (tree_view->priv->header_window);
6500
6501       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6502     }
6503
6504   g_object_unref (G_OBJECT (column));
6505   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
6506
6507   return tree_view->priv->n_columns;
6508 }
6509
6510 /**
6511  * gtk_tree_view_insert_column:
6512  * @tree_view: A #GtkTreeView.
6513  * @column: The #GtkTreeViewColumn to be inserted.
6514  * @position: The position to insert @column in.
6515  *
6516  * This inserts the @column into the @tree_view at @position.  If @position is
6517  * -1, then the column is inserted at the end.
6518  *
6519  * Return value: The number of columns in @tree_view after insertion.
6520  **/
6521 gint
6522 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
6523                              GtkTreeViewColumn *column,
6524                              gint               position)
6525 {
6526   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
6527   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
6528   g_return_val_if_fail (column->tree_view == NULL, -1);
6529
6530   g_object_ref (G_OBJECT (column));
6531
6532   if (tree_view->priv->n_columns == 0 &&
6533       GTK_WIDGET_REALIZED (tree_view) &&
6534       gtk_tree_view_get_headers_visible (tree_view))
6535     {
6536       gdk_window_show (tree_view->priv->header_window);
6537     }
6538
6539   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
6540                                             column, position);
6541   tree_view->priv->n_columns++;
6542
6543   _gtk_tree_view_column_set_tree_view (column, tree_view);
6544
6545   if (GTK_WIDGET_REALIZED (tree_view))
6546     {
6547       GList *list;
6548
6549       _gtk_tree_view_column_realize_button (column);
6550
6551       for (list = tree_view->priv->columns; list; list = list->next)
6552         {
6553           column = GTK_TREE_VIEW_COLUMN (list->data);
6554           if (column->visible)
6555             column->dirty = TRUE;
6556         }
6557       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6558     }
6559
6560   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
6561
6562   return tree_view->priv->n_columns;
6563 }
6564
6565 /**
6566  * gtk_tree_view_insert_column_with_attributes:
6567  * @tree_view: A #GtkTreeView
6568  * @position: The position to insert the new column in.
6569  * @title: The title to set the header to.
6570  * @cell: The #GtkCellRenderer.
6571  * @Varargs: A NULL terminated list of attributes.
6572  *
6573  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
6574  * @position.  If @position is -1, then the newly created column is inserted at
6575  * the end.  The column is initialized with the attributes given.
6576  *
6577  * Return value: The number of columns in @tree_view after insertion.
6578  **/
6579 gint
6580 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
6581                                              gint             position,
6582                                              gchar           *title,
6583                                              GtkCellRenderer *cell,
6584                                              ...)
6585 {
6586   GtkTreeViewColumn *column;
6587   gchar *attribute;
6588   va_list args;
6589   gint column_id;
6590
6591   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
6592
6593   column = gtk_tree_view_column_new ();
6594
6595   gtk_tree_view_column_set_title (column, title);
6596   gtk_tree_view_column_set_cell_renderer (column, cell);
6597
6598   va_start (args, cell);
6599
6600   attribute = va_arg (args, gchar *);
6601
6602   while (attribute != NULL)
6603     {
6604       column_id = va_arg (args, gint);
6605       gtk_tree_view_column_add_attribute (column, cell, attribute, column_id);
6606       attribute = va_arg (args, gchar *);
6607     }
6608
6609   va_end (args);
6610
6611   gtk_tree_view_insert_column (tree_view, column, position);
6612   g_object_unref (column);
6613
6614   return tree_view->priv->n_columns;
6615 }
6616
6617 /**
6618  * gtk_tree_view_insert_column_with_data_func:
6619  * @tree_view: a #GtkTreeView
6620  * @position: Position to insert, -1 for append
6621  * @title: column title
6622  * @cell: cell renderer for column
6623  * @func: function to set attributes of cell renderer
6624  * @data: data for @func
6625  * @dnotify: destroy notifier for @data
6626  *
6627  * Convenience function that inserts a new column into the #GtkTreeView
6628  * with the given cell renderer and a #GtkCellDataFunc to set cell renderer
6629  * attributes (normally using data from the model). See also
6630  * gtk_tree_view_column_set_cell_data_func(), gtk_tree_view_column_set_cell_renderer().
6631  *
6632  * Return value: number of columns in the tree view post-insert
6633  **/
6634 gint
6635 gtk_tree_view_insert_column_with_data_func  (GtkTreeView               *tree_view,
6636                                              gint                       position,
6637                                              gchar                     *title,
6638                                              GtkCellRenderer           *cell,
6639                                              GtkTreeCellDataFunc        func,
6640                                              gpointer                   data,
6641                                              GDestroyNotify             dnotify)
6642 {
6643   GtkTreeViewColumn *column;
6644
6645   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
6646
6647   column = gtk_tree_view_column_new ();
6648
6649   gtk_tree_view_column_set_title (column, title);
6650   gtk_tree_view_column_set_cell_renderer (column, cell);
6651   gtk_tree_view_column_set_cell_data_func (column, cell, func, data, dnotify);
6652
6653   gtk_tree_view_insert_column (tree_view, column, position);
6654
6655   g_object_unref (column);
6656
6657   return tree_view->priv->n_columns;
6658 }
6659
6660 /**
6661  * gtk_tree_view_get_column:
6662  * @tree_view: A #GtkTreeView.
6663  * @n: The position of the column, counting from 0.
6664  *
6665  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
6666  *
6667  * Return value: The #GtkTreeViewColumn, or NULL if the position is outside the
6668  * range of columns.
6669  **/
6670 GtkTreeViewColumn *
6671 gtk_tree_view_get_column (GtkTreeView *tree_view,
6672                           gint         n)
6673 {
6674   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6675
6676   if (n < 0 || n >= tree_view->priv->n_columns)
6677     return NULL;
6678
6679   if (tree_view->priv->columns == NULL)
6680     return NULL;
6681
6682   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
6683 }
6684
6685 /**
6686  * gtk_tree_view_get_columns:
6687  * @tree_view: A #GtkTreeView
6688  *
6689  * Returns a #GList of all the #GtkTreeViewColumn s currently in @tree_view.
6690  * The returned list must be freed with g_list_free ().
6691  *
6692  * Return value: A list of #GtkTreeViewColumn s
6693  **/
6694 GList *
6695 gtk_tree_view_get_columns (GtkTreeView *tree_view)
6696 {
6697   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6698
6699   return g_list_copy (tree_view->priv->columns);
6700 }
6701
6702 /**
6703  * gtk_tree_view_move_column_after:
6704  * @tree_view: A #GtkTreeView
6705  * @column: The #GtkTreeViewColumn to be moved.
6706  * @base_column: The #GtkTreeViewColumn to be moved relative to.
6707  *
6708  * Moves @column to be after to @base_column.  If @base_column is NULL, then
6709  * @column is placed in the first position.
6710  **/
6711 void
6712 gtk_tree_view_move_column_after (GtkTreeView       *tree_view,
6713                                  GtkTreeViewColumn *column,
6714                                  GtkTreeViewColumn *base_column)
6715 {
6716   GList *column_list_el, *base_el = NULL;
6717
6718   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6719
6720   column_list_el = g_list_find (tree_view->priv->columns, column);
6721   g_return_if_fail (column_list_el != NULL);
6722
6723   if (base_column)
6724     {
6725       base_el = g_list_find (tree_view->priv->columns, base_column);
6726       g_return_if_fail (base_el != NULL);
6727     }
6728
6729   if (column_list_el->prev == base_el)
6730     return;
6731
6732   tree_view->priv->columns = g_list_remove_link (tree_view->priv->columns, column_list_el);
6733   if (base_el == NULL)
6734     {
6735       column_list_el->prev = NULL;
6736       column_list_el->next = tree_view->priv->columns;
6737       if (column_list_el->next)
6738         column_list_el->next->prev = column_list_el;
6739       tree_view->priv->columns = column_list_el;
6740     }
6741   else
6742     {
6743       column_list_el->prev = base_el;
6744       column_list_el->next = base_el->next;
6745       if (column_list_el->next)
6746         column_list_el->next->prev = column_list_el;
6747       base_el->next = column_list_el;
6748     }
6749
6750   if (GTK_WIDGET_REALIZED (tree_view))
6751     {
6752       //gtk_widget_queue_resize (GTK_WIDGET (tree_view));
6753       _gtk_tree_view_update_size (tree_view);
6754       gtk_tree_view_size_allocate_buttons (GTK_WIDGET (tree_view));
6755     }
6756
6757   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[COLUMNS_CHANGED], 0);
6758 }
6759
6760 /**
6761  * gtk_tree_view_set_expander_column:
6762  * @tree_view: A #GtkTreeView
6763  * @column: NULL, or the column to draw the expander arrow at.
6764  * 
6765  * Sets the column to draw the expander arrow at. It must be in @tree_view.  If
6766  * @column is %NULL, then the expander arrow is fixed at the first column.
6767  **/
6768 void
6769 gtk_tree_view_set_expander_column (GtkTreeView       *tree_view,
6770                                    GtkTreeViewColumn *column)
6771 {
6772   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6773   if (column != NULL)
6774     g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
6775
6776   if (tree_view->priv->expander_column != column)
6777     {
6778       GList *list;
6779
6780       if (column)
6781         {
6782           /* Confirm that column is in tree_view */
6783           for (list = tree_view->priv->columns; list; list = list->next)
6784             if (list->data == column)
6785               break;
6786           g_return_if_fail (list != NULL);
6787         }
6788
6789       tree_view->priv->expander_column = column;
6790       g_object_notify (G_OBJECT (tree_view), "expander_column");
6791     }
6792 }
6793
6794 /**
6795  * gtk_tree_view_get_expander_column:
6796  * @tree_view: A #GtkTreeView
6797  *
6798  * Returns the column that is the current expander column.  This
6799  * column has the expander arrow drawn next to it.
6800  *
6801  * Return value: The expander column.
6802  **/
6803 GtkTreeViewColumn *
6804 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
6805 {
6806   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
6807
6808   return tree_view->priv->expander_column;
6809 }
6810
6811
6812 /**
6813  * gtk_tree_view_set_column_drag_function:
6814  * @tree_view: A #GtkTreeView.
6815  * @func: A function to determine which columns are reorderable, or NULL.
6816  * @user_data: User data to be passed to @func, or NULL
6817  * @destroy: Destroy notifier for @user_data, or NULL
6818  *
6819  * Sets a user function for determining where a column may be dropped when
6820  * dragged.  This function is called on every column pair in turn at the
6821  * beginning of a column drag to determine where a drop can take place.  The
6822  * arguments passed to @func are: the @tree_view, the #GtkTreeViewColumn being
6823  * dragged, the two #GtkTreeViewColumn s determining the drop spot, and
6824  * @user_data.  If either of the #GtkTreeViewColumn arguments for the drop spot
6825  * are NULL, then they indicate an edge.  If @func is set to be NULL, then
6826  * @tree_view reverts to the default behavior of allowing all columns to be
6827  * dropped everywhere.
6828  **/
6829 void
6830 gtk_tree_view_set_column_drag_function (GtkTreeView               *tree_view,
6831                                         GtkTreeViewColumnDropFunc  func,
6832                                         gpointer                   user_data,
6833                                         GtkDestroyNotify           destroy)
6834 {
6835   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6836
6837   if (tree_view->priv->column_drop_func_data_destroy)
6838     (* tree_view->priv->column_drop_func_data_destroy) (tree_view->priv->column_drop_func_data);
6839
6840   tree_view->priv->column_drop_func = func;
6841   tree_view->priv->column_drop_func_data = user_data;
6842   tree_view->priv->column_drop_func_data_destroy = destroy;
6843 }
6844
6845 /**
6846  * gtk_tree_view_scroll_to_point:
6847  * @tree_view: a #GtkTreeView
6848  * @tree_x: X coordinate of new top-left pixel of visible area
6849  * @tree_y: Y coordinate of new top-left pixel of visible area
6850  *
6851  * Scrolls the tree view such that the top-left corner of the visible
6852  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
6853  * in tree window coordinates.  The @tree_view must be realized before
6854  * this function is called.  If it isn't, you probably want ot be
6855  * using gtk_tree_view_scroll_to_cell.
6856  **/
6857 void
6858 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
6859                                gint         tree_x,
6860                                gint         tree_y)
6861 {
6862   GtkAdjustment *hadj;
6863   GtkAdjustment *vadj;
6864
6865   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6866   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
6867
6868   hadj = tree_view->priv->hadjustment;
6869   vadj = tree_view->priv->vadjustment;
6870
6871   gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper));
6872   gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper));
6873 }
6874
6875 /**
6876  * gtk_tree_view_scroll_to_cell
6877  * @tree_view: A #GtkTreeView.
6878  * @path: The path of the row to move to.
6879  * @column: The #GtkTreeViewColumn to move horizontally to.
6880  * @row_align: The vertical alignment of the row specified by @path.
6881  * @col_align: The horizontal alignment of the column specified by @column.
6882  *
6883  * Moves the alignments of @tree_view to the position specified by
6884  * @column and @path.  If @column is NULL, then no horizontal
6885  * scrolling occurs.  Likewise, if @path is NULL no vertical scrolling
6886  * occurs.  @row_align determines where the row is placed, and
6887  * @col_align determines where @column is placed.  Both are expected
6888  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
6889  * right/bottom alignment, 0.5 means center.
6890  **/
6891 void
6892 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
6893                               GtkTreePath       *path,
6894                               GtkTreeViewColumn *column,
6895                               gfloat             row_align,
6896                               gfloat             col_align)
6897 {
6898   GdkRectangle cell_rect;
6899   GdkRectangle vis_rect;
6900   gint dest_x, dest_y;
6901
6902   /* FIXME work on unmapped/unrealized trees? maybe implement when
6903    * we do incremental reflow for trees
6904    */
6905
6906   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6907   g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
6908   g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
6909   g_return_if_fail (path != NULL || column != NULL);
6910
6911   row_align = CLAMP (row_align, 0.0, 1.0);
6912   col_align = CLAMP (col_align, 0.0, 1.0);
6913
6914   if (! GTK_WIDGET_REALIZED (tree_view))
6915     {
6916       if (path)
6917         tree_view->priv->scroll_to_path = gtk_tree_path_copy (path);
6918       if (column)
6919         tree_view->priv->scroll_to_column = column;
6920       tree_view->priv->scroll_to_row_align = row_align;
6921       tree_view->priv->scroll_to_col_align = col_align;
6922
6923       return;
6924     }
6925
6926   gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
6927   gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
6928
6929   dest_x = vis_rect.x;
6930   dest_y = vis_rect.y;
6931
6932   if (path)
6933     {
6934       dest_x = cell_rect.x +
6935         cell_rect.width * row_align -
6936         vis_rect.width * row_align;
6937     }
6938
6939   if (column)
6940     {
6941       dest_y = cell_rect.y +
6942         cell_rect.height * col_align -
6943         vis_rect.height * col_align;
6944     }
6945
6946   gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
6947 }
6948
6949
6950 /**
6951  * gtk_tree_view_row_activated:
6952  * @tree_view: A #GtkTreeView
6953  * @path: The #GtkTreePath to be activated.
6954  * @column: The #GtkTreeViewColumn to be activated.
6955  *
6956  * Activates the cell determined by @path and @column.
6957  **/
6958 void
6959 gtk_tree_view_row_activated (GtkTreeView       *tree_view,
6960                              GtkTreePath       *path,
6961                              GtkTreeViewColumn *column)
6962 {
6963   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
6964
6965   /* FIXME: Actually activate the path internally, not just emit the signal */
6966   /*  g_warning ("FIXME: Actually activate the path internally, not just emit the signal\n"); */
6967   g_signal_emit (G_OBJECT(tree_view), tree_view_signals[ROW_ACTIVATED], 0, path, column);
6968 }
6969
6970
6971 static void
6972 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
6973                                  GtkRBNode  *node,
6974                                  gpointer  data)
6975 {
6976   GtkTreeView *tree_view = data;
6977
6978   if (node->children)
6979     _gtk_rbtree_traverse (node->children,
6980                           node->children->root,
6981                           G_PRE_ORDER,
6982                           gtk_tree_view_expand_all_helper,
6983                           data);
6984   else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
6985     {
6986       GtkTreePath *path;
6987       GtkTreeIter iter;
6988       GtkTreeIter child;
6989
6990       node->children = _gtk_rbtree_new ();
6991       node->children->parent_tree = tree;
6992       node->children->parent_node = node;
6993       path = _gtk_tree_view_find_path (tree_view, tree, node);
6994       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
6995       gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
6996       gtk_tree_view_build_tree (tree_view,
6997                                 node->children,
6998                                 &child,
6999                                 gtk_tree_path_get_depth (path) + 1,
7000                                 TRUE,
7001                                 GTK_WIDGET_REALIZED (tree_view));
7002       gtk_tree_path_free (path);
7003     }
7004 }
7005
7006 /**
7007  * gtk_tree_view_expand_all:
7008  * @tree_view: A #GtkTreeView.
7009  *
7010  * Recursively expands all nodes in the @tree_view.
7011  **/
7012 void
7013 gtk_tree_view_expand_all (GtkTreeView *tree_view)
7014 {
7015   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7016   g_return_if_fail (tree_view->priv->tree != NULL);
7017
7018   _gtk_rbtree_traverse (tree_view->priv->tree,
7019                         tree_view->priv->tree->root,
7020                         G_PRE_ORDER,
7021                         gtk_tree_view_expand_all_helper,
7022                         tree_view);
7023
7024   _gtk_tree_view_update_size (tree_view);
7025 }
7026
7027 static void
7028 gtk_tree_view_collapse_all_helper (GtkRBTree  *tree,
7029                                    GtkRBNode  *node,
7030                                    gpointer    data)
7031 {
7032   if (node->children)
7033     {
7034       GtkTreePath *path;
7035       GtkTreeIter iter;
7036
7037       path = _gtk_tree_view_find_path (GTK_TREE_VIEW (data),
7038                                        node->children,
7039                                        node->children->root);
7040       gtk_tree_model_get_iter (GTK_TREE_VIEW (data)->priv->model,
7041                                &iter,
7042                                path);
7043       gtk_tree_view_discover_dirty (GTK_TREE_VIEW (data),
7044                                     node->children,
7045                                     &iter,
7046                                     gtk_tree_path_get_depth (path));
7047
7048       /* Ensure we don't have a dangling pointer to a dead node */
7049       ensure_unprelighted (GTK_TREE_VIEW (data));
7050
7051       _gtk_rbtree_remove (node->children);
7052       gtk_tree_path_free (path);
7053     }
7054 }
7055
7056 /**
7057  * gtk_tree_view_collapse_all:
7058  * @tree_view: A #GtkTreeView.
7059  *
7060  * Recursively collapses all visible, expanded nodes in @tree_view.
7061  **/
7062 void
7063 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
7064 {
7065   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7066   g_return_if_fail (tree_view->priv->tree != NULL);
7067
7068   _gtk_rbtree_traverse (tree_view->priv->tree,
7069                         tree_view->priv->tree->root,
7070                         G_PRE_ORDER,
7071                         gtk_tree_view_collapse_all_helper,
7072                         tree_view);
7073
7074   if (GTK_WIDGET_MAPPED (tree_view))
7075     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
7076 }
7077
7078 /* FIXME the bool return values for expand_row and collapse_row are
7079  * not analagous; they should be TRUE if the row had children and
7080  * was not already in the requested state.
7081  */
7082
7083
7084 static gboolean
7085 gtk_tree_view_real_expand_row (GtkTreeView *tree_view,
7086                                GtkTreePath *path,
7087                                GtkRBTree   *tree,
7088                                GtkRBNode   *node,
7089                                gboolean     open_all)
7090 {
7091   GtkTreeIter iter;
7092   GtkTreeIter temp;
7093   gboolean expand;
7094
7095   if (node->children)
7096     return TRUE;
7097
7098   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
7099   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
7100     return FALSE;
7101
7102   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_EXPAND_ROW], 0, &iter, path, &expand);
7103
7104   if (expand)
7105     return FALSE;
7106
7107   node->children = _gtk_rbtree_new ();
7108   node->children->parent_tree = tree;
7109   node->children->parent_node = node;
7110
7111   gtk_tree_model_iter_children (tree_view->priv->model, &temp, &iter);
7112
7113   gtk_tree_view_build_tree (tree_view,
7114                             node->children,
7115                             &temp,
7116                             gtk_tree_path_get_depth (path) + 1,
7117                             open_all,
7118                             GTK_WIDGET_REALIZED (tree_view));
7119
7120   if (GTK_WIDGET_MAPPED (tree_view))
7121     {
7122       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
7123       _gtk_tree_view_update_size (tree_view);
7124     }
7125
7126   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_EXPANDED], 0, &iter, path);
7127
7128   return TRUE;
7129 }
7130
7131
7132 /**
7133  * gtk_tree_view_expand_row:
7134  * @tree_view: a #GtkTreeView
7135  * @path: path to a row
7136  * @open_all: whether to recursively expand, or just expand immediate children
7137  *
7138  * Opens the row so its children are visible
7139  *
7140  * Return value: %TRUE if the row existed and had children
7141  **/
7142 gboolean
7143 gtk_tree_view_expand_row (GtkTreeView *tree_view,
7144                           GtkTreePath *path,
7145                           gboolean     open_all)
7146 {
7147   GtkRBTree *tree;
7148   GtkRBNode *node;
7149
7150   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
7151   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
7152   g_return_val_if_fail (path != NULL, FALSE);
7153
7154   if (_gtk_tree_view_find_node (tree_view,
7155                                 path,
7156                                 &tree,
7157                                 &node))
7158     return FALSE;
7159
7160   return gtk_tree_view_real_expand_row (tree_view, path, tree, node, open_all);
7161 }
7162
7163 static gboolean
7164 gtk_tree_view_real_collapse_row (GtkTreeView *tree_view,
7165                                  GtkTreePath *path,
7166                                  GtkRBTree   *tree,
7167                                  GtkRBNode   *node)
7168 {
7169   GtkTreeIter iter;
7170   GtkTreeIter children;
7171   gboolean collapse;
7172
7173   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
7174
7175   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[TEST_COLLAPSE_ROW], 0, &iter, path, &collapse);
7176
7177   if (collapse)
7178     return FALSE;
7179
7180   TREE_VIEW_INTERNAL_ASSERT (gtk_tree_model_iter_children (tree_view->priv->model, &children, &iter), FALSE);
7181
7182   gtk_tree_view_discover_dirty (tree_view,
7183                                 node->children,
7184                                 &children,
7185                                 gtk_tree_path_get_depth (path));
7186
7187   /* Ensure we don't have a dangling pointer to a dead node */
7188   ensure_unprelighted (tree_view);
7189
7190   if (tree_view->priv->destroy_count_func)
7191     {
7192       gint child_count = 0;
7193       if (node->children)
7194         _gtk_rbtree_traverse (node->children, node->children->root, G_POST_ORDER, count_children_helper, &child_count);
7195       (* tree_view->priv->destroy_count_func) (tree_view, path, child_count, tree_view->priv->destroy_count_data);
7196     }
7197
7198   if (gtk_tree_view_unref_and_check_selection_tree (tree_view, node->children))
7199     g_signal_emit_by_name (G_OBJECT (tree_view->priv->selection), "changed", 0);
7200   _gtk_rbtree_remove (node->children);
7201
7202   if (GTK_WIDGET_MAPPED (tree_view))
7203     {
7204       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
7205       _gtk_tree_view_update_size (tree_view);
7206     }
7207
7208   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7209     {
7210       GtkTreePath *cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7211
7212       if (gtk_tree_path_is_ancestor (path, cursor_path))
7213         {
7214           gtk_tree_row_reference_free (tree_view->priv->cursor);
7215           tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
7216                                                                       tree_view->priv->model,
7217                                                                       path);
7218         }
7219       gtk_tree_path_free (cursor_path);
7220     }
7221
7222   if (gtk_tree_row_reference_valid (tree_view->priv->anchor))
7223       {
7224       GtkTreePath *anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
7225       if (gtk_tree_path_is_ancestor (path, anchor_path))
7226         {
7227           gtk_tree_row_reference_free (tree_view->priv->anchor);
7228           tree_view->priv->anchor = NULL;
7229         }
7230       gtk_tree_path_free (anchor_path);
7231
7232     }
7233
7234   g_signal_emit (G_OBJECT (tree_view), tree_view_signals[ROW_COLLAPSED], 0, &iter, path);
7235
7236   return TRUE;
7237 }
7238
7239 /**
7240  * gtk_tree_view_collapse_row:
7241  * @tree_view: a #GtkTreeView
7242  * @path: path to a row in the @tree_view
7243  *
7244  * Collapses a row (hides its child rows, if they exist.)
7245  *
7246  * Return value: %TRUE if the row was collapsed.
7247  **/
7248 gboolean
7249 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
7250                             GtkTreePath *path)
7251 {
7252   GtkRBTree *tree;
7253   GtkRBNode *node;
7254
7255   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
7256   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
7257   g_return_val_if_fail (path != NULL, FALSE);
7258
7259   if (_gtk_tree_view_find_node (tree_view,
7260                                 path,
7261                                 &tree,
7262                                 &node))
7263     return FALSE;
7264
7265   if (node->children == NULL)
7266     return FALSE;
7267
7268   return gtk_tree_view_real_collapse_row (tree_view, path, tree, node);
7269 }
7270
7271 static void
7272 gtk_tree_view_map_expanded_rows_helper (GtkTreeView            *tree_view,
7273                                         GtkRBTree              *tree,
7274                                         GtkTreePath            *path,
7275                                         GtkTreeViewMappingFunc  func,
7276                                         gpointer                user_data)
7277 {
7278   GtkRBNode *node;
7279   gint *indices;
7280   gint depth;
7281   gint i = 0;
7282
7283   if (tree == NULL || tree->root == NULL)
7284     return;
7285
7286   node = tree->root;
7287
7288   indices = gtk_tree_path_get_indices (path);
7289   depth = gtk_tree_path_get_depth (path);
7290
7291   while (node && node->left != tree->nil)
7292     node = node->left;
7293
7294   while (node)
7295     {
7296       if (node->children)
7297         {
7298           gtk_tree_path_append_index (path, 0);
7299           gtk_tree_view_map_expanded_rows_helper (tree_view, node->children, path, func, user_data);
7300           gtk_tree_path_up (path);
7301           (* func) (tree_view, path, user_data);
7302         }
7303       i++;
7304       indices[depth -1] = i;
7305       node = _gtk_rbtree_next (tree, node);
7306     }
7307 }
7308
7309 /**
7310  * gtk_tree_view_map_expanded_rows:
7311  * @tree_view: A #GtkTreeView
7312  * @func: A function to be called
7313  * @data: User data to be passed to the function.
7314  *
7315  * Calls @func on all expanded rows.
7316  **/
7317 void
7318 gtk_tree_view_map_expanded_rows (GtkTreeView            *tree_view,
7319                                  GtkTreeViewMappingFunc  func,
7320                                  gpointer                user_data)
7321 {
7322   GtkTreePath *path;
7323
7324   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7325   g_return_if_fail (func != NULL);
7326
7327   path = gtk_tree_path_new_root ();
7328
7329   gtk_tree_view_map_expanded_rows_helper (tree_view,
7330                                           tree_view->priv->tree,
7331                                           path, func, user_data);
7332
7333   gtk_tree_path_free (path);
7334 }
7335
7336 /**
7337  * gtk_tree_view_row_expanded:
7338  * @tree_view: A #GtkTreeView.
7339  * @path: A #GtkTreePath to test expansion state.
7340  * 
7341  * Returns TRUE if the node pointed to by @path is expanded in @tree_view.
7342  * 
7343  * Return value: TRUE if #path is expanded.
7344  **/
7345 gboolean
7346 gtk_tree_view_row_expanded (GtkTreeView *tree_view,
7347                             GtkTreePath *path)
7348 {
7349   GtkRBTree *tree;
7350   GtkRBNode *node;
7351
7352   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
7353   g_return_val_if_fail (path != NULL, FALSE);
7354
7355   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7356
7357   if (node == NULL)
7358     return FALSE;
7359
7360   return (node->children != NULL);
7361 }
7362
7363 static GtkTargetEntry row_targets[] = {
7364   { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
7365 };
7366
7367
7368 /**
7369  * gtk_tree_view_get_reorderable:
7370  * @tree_view: a #GtkTreeView
7371  *
7372  * Retrieves whether the user can reorder the tree via drag-and-drop. See
7373  * gtk_tree_view_set_reorderable().
7374  *
7375  * Return value: %TRUE if the tree can be reordered.
7376  **/
7377 gboolean
7378 gtk_tree_view_get_reorderable (GtkTreeView *tree_view)
7379 {
7380   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
7381
7382   return tree_view->priv->reorderable;
7383 }
7384
7385 /**
7386  * gtk_tree_view_set_reorderable:
7387  * @tree_view: A #GtkTreeView.
7388  * @reorderable: TRUE, if the tree can be reordered.
7389  *
7390  * This function is a convenience function to allow you to reorder models that
7391  * support the #GtkDragSourceIface and the #GtkDragDestIface.  Both
7392  * #GtkTreeStore and #GtkListStore support these.  If @reorderable is TRUE, then
7393  * the user can reorder the model by dragging and dropping columns.  The
7394  * developer will can listen to these changes by connecting to the model's
7395  * signals.
7396  *
7397  * This function does not give you any degree of control over the order -- any
7398  * reorderering is allowed.  If more control is needed, you should probably
7399  * handle drag and drop manually.
7400  **/
7401 void
7402 gtk_tree_view_set_reorderable (GtkTreeView *tree_view,
7403                                gboolean     reorderable)
7404 {
7405   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7406
7407   if (tree_view->priv->reorderable == (reorderable?TRUE:FALSE))
7408     return;
7409
7410   gtk_tree_view_set_rows_drag_source (tree_view,
7411                                       GDK_BUTTON1_MASK,
7412                                       row_targets,
7413                                       G_N_ELEMENTS (row_targets),
7414                                       GDK_ACTION_MOVE,
7415                                       NULL, NULL);
7416   gtk_tree_view_set_rows_drag_dest (tree_view,
7417                                     row_targets,
7418                                     G_N_ELEMENTS (row_targets),
7419                                     GDK_ACTION_MOVE,
7420                                     NULL, NULL);
7421
7422   g_object_notify (G_OBJECT (tree_view), "reorderable");
7423 }
7424
7425 static void
7426 gtk_tree_view_real_set_cursor (GtkTreeView     *tree_view,
7427                                GtkTreePath     *path,
7428                                gboolean         clear_and_select)
7429 {
7430   GtkRBTree *tree = NULL;
7431   GtkRBNode *node = NULL;
7432
7433   if (gtk_tree_row_reference_valid (tree_view->priv->cursor))
7434     {
7435       GtkTreePath *cursor_path;
7436       cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
7437       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
7438       gtk_tree_path_free (cursor_path);
7439     }
7440   gtk_tree_row_reference_free (tree_view->priv->cursor);
7441
7442   tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view),
7443                                                               tree_view->priv->model,
7444                                                               path);
7445   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7446   if (tree == NULL)
7447     return;
7448
7449   if (clear_and_select && !tree_view->priv->in_free_motion)
7450     _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
7451                                               node, tree, path,
7452                                               tree_view->priv->in_extended_selection?GDK_SHIFT_MASK:0);
7453   gtk_tree_view_clamp_node_visible (tree_view, tree, node);
7454   gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
7455 }
7456
7457 /**
7458  * gtk_tree_view_set_cursor:
7459  * @tree_view: A #GtkTreeView
7460  * @path: A #GtkTreePath
7461  *
7462  * Sets the current keyboard focus to be at @path, and selects it.  This is
7463  * useful when you want to focus the user's attention on a particular row.  If
7464  * you want to give the user keyboard focus in the tree_view, you should use
7465  * this function to set the correct path, and gtk_widget_grab_focus (GTK_WIDGET
7466  * (tree_view)) to actually give focus to the @tree_view.
7467  **/
7468 void
7469 gtk_tree_view_set_cursor (GtkTreeView *tree_view,
7470                           GtkTreePath *path)
7471 {
7472   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7473   g_return_if_fail (path != NULL);
7474
7475   gtk_tree_view_real_set_cursor (tree_view, path, TRUE);
7476 }
7477
7478
7479 /**
7480  * gtk_tree_view_get_path_at_pos:
7481  * @tree_view: A #GtkTreeView.
7482  * @window: The #GdkWindow to check against.
7483  * @x: The x position to be identified.
7484  * @y: The y position to be identified.
7485  * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
7486  * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
7487  * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
7488  * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
7489  *
7490  * Finds the path at the point (@x, @y) relative to @window.  If @window is
7491  * NULL, then the point is found relative to the widget coordinates.  This
7492  * function is expected to be called after an event, with event->window being
7493  * passed in as @window.  It is primarily for things like popup menus.  If @path
7494  * is non-NULL, then it will be filled with the #GtkTreePath at that point.
7495  * This path should be freed with #gtk_tree_path_free.  If @column is non-NULL,
7496  * then it will be filled with the column at that point. @cell_x and @cell_y
7497  * return the coordinates relative to the cell background (i.e. the
7498  * background_area passed to gtk_cell_renderer_render()).  This function only
7499  * works if @tree_view is realized.
7500  *
7501  * Return value: TRUE if a row exists at that coordinate.
7502  **/
7503 gboolean
7504 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
7505                                GdkWindow          *window,
7506                                gint                x,
7507                                gint                y,
7508                                GtkTreePath       **path,
7509                                GtkTreeViewColumn **column,
7510                                gint               *cell_x,
7511                                gint               *cell_y)
7512 {
7513   GtkRBTree *tree;
7514   GtkRBNode *node;
7515   gint y_offset;
7516
7517   g_return_val_if_fail (tree_view != NULL, FALSE);
7518   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
7519   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
7520
7521   if (window)
7522     g_return_val_if_fail (window == tree_view->priv->bin_window, FALSE);
7523
7524   if (path)
7525     *path = NULL;
7526   if (column)
7527     *column = NULL;
7528
7529   if (x > tree_view->priv->hadjustment->upper)
7530     return FALSE;
7531
7532   if (x < 0 || y < 0)
7533     return FALSE;
7534
7535   if (column || cell_x)
7536     {
7537       GtkTreeViewColumn *tmp_column;
7538       GtkTreeViewColumn *last_column = NULL;
7539       GList *list;
7540       gint remaining_x = x;
7541       gboolean found = FALSE;
7542
7543       for (list = tree_view->priv->columns; list; list = list->next)
7544         {
7545           tmp_column = list->data;
7546
7547           if (tmp_column->visible == FALSE)
7548             continue;
7549
7550           last_column = tmp_column;
7551           if (remaining_x <= tmp_column->width)
7552             {
7553               found = TRUE;
7554
7555               if (column)
7556                 *column = tmp_column;
7557
7558               if (cell_x)
7559                 *cell_x = remaining_x;
7560
7561               break;
7562             }
7563           remaining_x -= tmp_column->width;
7564         }
7565
7566       if (!found)
7567         {
7568           if (column)
7569             *column = last_column;
7570
7571           if (cell_x)
7572             *cell_x = last_column->width + remaining_x;
7573         }
7574     }
7575
7576   if (window)
7577     {
7578       y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
7579                                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
7580                                           &tree, &node);
7581     }
7582   else
7583     {
7584       if (y < TREE_VIEW_HEADER_HEIGHT (tree_view))
7585         return FALSE;
7586
7587       y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
7588                                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y + tree_view->priv->vadjustment->value),
7589                                           &tree, &node);
7590     }
7591
7592   if (tree == NULL)
7593     return FALSE;
7594
7595   if (cell_y)
7596     *cell_y = y_offset;
7597
7598   if (path)
7599     *path = _gtk_tree_view_find_path (tree_view, tree, node);
7600
7601   return TRUE;
7602 }
7603
7604
7605 /**
7606  * gtk_tree_view_get_cell_area:
7607  * @tree_view: a #GtkTreeView
7608  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
7609  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
7610  * @rect: rectangle to fill with cell rect
7611  *
7612  * Fills the bounding rectangle in tree window coordinates for the cell at the
7613  * row specified by @path and the column specified by @column.  If @path is
7614  * %NULL, the y and height fields of the rectangle will be filled with 0. If
7615  * @column is %NULL, the x and width fields will be filled with 0.  The sum of
7616  * all cell rects does not cover the entire tree; there are extra pixels in
7617  * between rows, for example. The returned rectangle is equivalent to the
7618  * @cell_area passed to gtk_cell_renderer_render().  This function is only valid
7619  * if #tree_view is realized.
7620  **/
7621 void
7622 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
7623                              GtkTreePath        *path,
7624                              GtkTreeViewColumn  *column,
7625                              GdkRectangle       *rect)
7626 {
7627   GtkRBTree *tree = NULL;
7628   GtkRBNode *node = NULL;
7629   gint vertical_separator;
7630
7631   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7632   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
7633   g_return_if_fail (rect != NULL);
7634
7635   gtk_widget_style_get (GTK_WIDGET (tree_view), "vertical_separator", &vertical_separator, NULL);
7636
7637   rect->x = 0;
7638   rect->y = 0;
7639   rect->width = 0;
7640   rect->height = 0;
7641
7642   if (path)
7643     {
7644       /* Get vertical coords */
7645
7646       _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7647
7648       if (tree == NULL)
7649         {
7650           g_warning (G_STRLOC": no row corresponding to path");
7651           return;
7652         }
7653
7654       /* Remember that the rbtree stores node height including the vertical
7655        * separator, see comment at top of file.
7656        */
7657       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node, vertical_separator);
7658
7659       rect->height = CELL_HEIGHT (node, vertical_separator);
7660     }
7661
7662   if (column)
7663     {
7664       gint x2 = 0;
7665
7666       gtk_tree_view_get_cell_xrange (tree_view, tree, column, &rect->x, &x2);
7667       rect->width = x2 - rect->x;
7668     }
7669 }
7670
7671 /**
7672  * gtk_tree_view_get_background_area:
7673  * @tree_view: a #GtkTreeView
7674  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
7675  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
7676  * @rect: rectangle to fill with cell background rect
7677  *
7678  * Fills the bounding rectangle in tree window coordinates for the
7679  * cell at the row specified by @path and the column specified by
7680  * @column.  If @path is %NULL, the y and height fields of the
7681  * rectangle will be filled with 0. If @column is %NULL, the x and
7682  * width fields will be filled with 0.  The returned rectangle is
7683  * equivalent to the @background_area passed to
7684  * gtk_cell_renderer_render().  These background areas tile to cover
7685  * the entire tree window (except for the area used for header
7686  * buttons). Contrast with the cell_area, returned by
7687  * gtk_tree_view_get_cell_area(), which returns only the cell itself,
7688  * excluding surrounding borders and the tree expander area.
7689  *
7690  **/
7691 void
7692 gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
7693                                    GtkTreePath        *path,
7694                                    GtkTreeViewColumn  *column,
7695                                    GdkRectangle       *rect)
7696 {
7697   GtkRBTree *tree = NULL;
7698   GtkRBNode *node = NULL;
7699
7700   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7701   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
7702   g_return_if_fail (rect != NULL);
7703
7704   rect->x = 0;
7705   rect->y = 0;
7706   rect->width = 0;
7707   rect->height = 0;
7708
7709   if (path)
7710     {
7711       /* Get vertical coords */
7712
7713       _gtk_tree_view_find_node (tree_view, path, &tree, &node);
7714
7715       if (tree == NULL)
7716         {
7717           g_warning (G_STRLOC": no row corresponding to path");
7718           return;
7719         }
7720
7721       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
7722
7723       rect->height = BACKGROUND_HEIGHT (node);
7724     }
7725
7726   if (column)
7727     {
7728       gint x2 = 0;
7729
7730       gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
7731       rect->width = x2 - rect->x;
7732     }
7733 }
7734
7735 /**
7736  * gtk_tree_view_get_visible_rect:
7737  * @tree_view: a #GtkTreeView
7738  * @visible_rect: rectangle to fill
7739  *
7740  * Fills @visible_rect with the currently-visible region of the
7741  * buffer, in tree coordinates. Convert to widget coordinates with
7742  * gtk_tree_view_tree_to_widget_coords(). Tree coordinates start at
7743  * 0,0 for row 0 of the tree, and cover the entire scrollable area of
7744  * the tree.
7745  **/
7746 void
7747 gtk_tree_view_get_visible_rect (GtkTreeView  *tree_view,
7748                                 GdkRectangle *visible_rect)
7749 {
7750   GtkWidget *widget;
7751
7752   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7753
7754   widget = GTK_WIDGET (tree_view);
7755
7756   if (visible_rect)
7757     {
7758       visible_rect->x = tree_view->priv->hadjustment->value;
7759       visible_rect->y = tree_view->priv->vadjustment->value;
7760       visible_rect->width = widget->allocation.width;
7761       visible_rect->height = widget->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
7762     }
7763 }
7764
7765 /**
7766  * gtk_tree_view_widget_to_tree_coords:
7767  * @tree_view: a #GtkTreeView
7768  * @wx: widget X coordinate
7769  * @wy: widget Y coordinate
7770  * @tx: return location for tree X coordinate
7771  * @ty: return location for tree Y coordinate
7772  *
7773  * Converts widget coordinates to coordinates for the
7774  * tree window (the full scrollable area of the tree).
7775  *
7776  **/
7777 void
7778 gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
7779                                      gint         wx,
7780                                      gint         wy,
7781                                      gint        *tx,
7782                                      gint        *ty)
7783 {
7784   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7785
7786   if (tx)
7787     {
7788       *tx = wx + tree_view->priv->hadjustment->value;
7789     }
7790
7791   if (ty)
7792     {
7793       *ty = wy + tree_view->priv->vadjustment->value;
7794     }
7795 }
7796
7797 /**
7798  * gtk_tree_view_tree_to_widget_coords:
7799  * @tree_view: a #GtkTreeView
7800  * @tx: tree X coordinate
7801  * @ty: tree Y coordinate
7802  * @wx: return location for widget X coordinate
7803  * @wy: return location for widget Y coordinate
7804  *
7805  * Converts tree coordinates (coordinates in full scrollable area of the tree)
7806  * to widget coordinates.
7807  *
7808  **/
7809 void
7810 gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
7811                                      gint         tx,
7812                                      gint         ty,
7813                                      gint        *wx,
7814                                      gint        *wy)
7815 {
7816   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7817
7818   if (wx)
7819     {
7820       *wx = tx - tree_view->priv->hadjustment->value;
7821     }
7822
7823   if (wy)
7824     {
7825       *wy = ty - tree_view->priv->vadjustment->value;
7826     }
7827 }
7828
7829
7830 void
7831 gtk_tree_view_set_rows_drag_source (GtkTreeView              *tree_view,
7832                                     GdkModifierType           start_button_mask,
7833                                     const GtkTargetEntry     *targets,
7834                                     gint                      n_targets,
7835                                     GdkDragAction             actions,
7836                                     GtkTreeViewDraggableFunc  row_draggable_func,
7837                                     gpointer                  user_data)
7838 {
7839   TreeViewDragInfo *di;
7840
7841   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7842
7843   di = ensure_info (tree_view);
7844   clear_source_info (di);
7845
7846   di->start_button_mask = start_button_mask;
7847   di->source_target_list = gtk_target_list_new (targets, n_targets);
7848   di->source_actions = actions;
7849
7850   if (row_draggable_func)
7851     {
7852       di->row_draggable_closure = g_cclosure_new ((GCallback) row_draggable_func,
7853                                                   user_data, NULL);
7854       g_closure_ref (di->row_draggable_closure);
7855       g_closure_sink (di->row_draggable_closure);
7856     }
7857
7858   di->source_set = TRUE;
7859 }
7860
7861 void
7862 gtk_tree_view_set_rows_drag_dest (GtkTreeView              *tree_view,
7863                                   const GtkTargetEntry     *targets,
7864                                   gint                      n_targets,
7865                                   GdkDragAction             actions,
7866                                   GtkTreeViewDroppableFunc  location_droppable_func,
7867                                   gpointer                  user_data)
7868 {
7869   TreeViewDragInfo *di;
7870
7871   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7872
7873   gtk_drag_dest_set (GTK_WIDGET (tree_view),
7874                      0,
7875                      NULL,
7876                      0,
7877                      actions);
7878
7879   di = ensure_info (tree_view);
7880   clear_dest_info (di);
7881
7882   if (targets)
7883     di->dest_target_list = gtk_target_list_new (targets, n_targets);
7884
7885   if (location_droppable_func)
7886     {
7887       di->location_droppable_closure = g_cclosure_new ((GCallback) location_droppable_func,
7888                                                        user_data, NULL);
7889       g_closure_ref (di->location_droppable_closure);
7890       g_closure_sink (di->location_droppable_closure);
7891     }
7892
7893   di->dest_set = TRUE;
7894 }
7895
7896 void
7897 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
7898 {
7899   TreeViewDragInfo *di;
7900
7901   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7902
7903   di = get_info (tree_view);
7904
7905   if (di)
7906     {
7907       if (di->source_set)
7908         {
7909           clear_source_info (di);
7910           di->source_set = FALSE;
7911         }
7912
7913       if (!di->dest_set && !di->source_set)
7914         remove_info (tree_view);
7915     }
7916 }
7917
7918 void
7919 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
7920 {
7921   TreeViewDragInfo *di;
7922
7923   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7924
7925   di = get_info (tree_view);
7926
7927   if (di)
7928     {
7929       if (di->dest_set)
7930         {
7931           gtk_drag_dest_unset (GTK_WIDGET (tree_view));
7932           clear_dest_info (di);
7933           di->dest_set = FALSE;
7934         }
7935
7936       if (!di->dest_set && !di->source_set)
7937         remove_info (tree_view);
7938     }
7939 }
7940
7941 void
7942 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
7943                                  GtkTreePath            *path,
7944                                  GtkTreeViewDropPosition pos)
7945 {
7946   GtkTreePath *current_dest;
7947   /* Note; this function is exported to allow a custom DND
7948    * implementation, so it can't touch TreeViewDragInfo
7949    */
7950
7951   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7952
7953   current_dest = NULL;
7954
7955   if (tree_view->priv->drag_dest_row)
7956     current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
7957
7958   if (current_dest)
7959     {
7960       gtk_tree_view_queue_draw_path (tree_view, current_dest, NULL);
7961       gtk_tree_path_free (current_dest);
7962     }
7963
7964   if (tree_view->priv->drag_dest_row)
7965     gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
7966
7967   tree_view->priv->drag_dest_pos = pos;
7968
7969   if (path)
7970     {
7971       tree_view->priv->drag_dest_row =
7972         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
7973       gtk_tree_view_queue_draw_path (tree_view, path, NULL);
7974     }
7975   else
7976     tree_view->priv->drag_dest_row = NULL;
7977 }
7978
7979 void
7980 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
7981                                  GtkTreePath             **path,
7982                                  GtkTreeViewDropPosition  *pos)
7983 {
7984   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
7985
7986   if (path)
7987     {
7988       if (tree_view->priv->drag_dest_row)
7989         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
7990       else
7991         *path = NULL;
7992     }
7993
7994   if (pos)
7995     *pos = tree_view->priv->drag_dest_pos;
7996 }
7997
7998 gboolean
7999 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
8000                                    gint                     drag_x,
8001                                    gint                     drag_y,
8002                                    GtkTreePath            **path,
8003                                    GtkTreeViewDropPosition *pos)
8004 {
8005   gint cell_y;
8006   gdouble offset_into_row;
8007   gdouble quarter;
8008   gint x, y;
8009   GdkRectangle cell;
8010   GtkTreeViewColumn *column = NULL;
8011   GtkTreePath *tmp_path = NULL;
8012
8013   /* Note; this function is exported to allow a custom DND
8014    * implementation, so it can't touch TreeViewDragInfo
8015    */
8016
8017   g_return_val_if_fail (tree_view != NULL, FALSE);
8018   g_return_val_if_fail (drag_x >= 0, FALSE);
8019   g_return_val_if_fail (drag_y >= 0, FALSE);
8020   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
8021
8022
8023   if (path)
8024     *path = NULL;
8025
8026   if (tree_view->priv->tree == NULL)
8027     return FALSE;
8028
8029   /* remember that drag_x and drag_y are in widget coords, convert to tree window */
8030
8031   gtk_tree_view_widget_to_tree_coords (tree_view, drag_x, drag_y,
8032                                        &x, &y);
8033
8034   /* If in the top quarter of a row, we drop before that row; if
8035    * in the bottom quarter, drop after that row; if in the middle,
8036    * and the row has children, drop into the row.
8037    */
8038
8039   if (!gtk_tree_view_get_path_at_pos (tree_view,
8040                                       tree_view->priv->bin_window,
8041                                       x, y,
8042                                       &tmp_path,
8043                                       &column,
8044                                       NULL,
8045                                       &cell_y))
8046     return FALSE;
8047
8048   gtk_tree_view_get_background_area (tree_view, tmp_path, column,
8049                                      &cell);
8050
8051   offset_into_row = cell_y;
8052
8053   if (path)
8054     *path = tmp_path;
8055   else
8056     gtk_tree_path_free (tmp_path);
8057
8058   tmp_path = NULL;
8059
8060   quarter = cell.height / 4.0;
8061
8062   if (pos)
8063     {
8064       if (offset_into_row < quarter)
8065         {
8066           *pos = GTK_TREE_VIEW_DROP_BEFORE;
8067         }
8068       else if (offset_into_row < quarter * 2)
8069         {
8070           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
8071         }
8072       else if (offset_into_row < quarter * 3)
8073         {
8074           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
8075         }
8076       else
8077         {
8078           *pos = GTK_TREE_VIEW_DROP_AFTER;
8079         }
8080     }
8081
8082   return TRUE;
8083 }
8084
8085
8086
8087 /* KEEP IN SYNC WITH GTK_TREE_VIEW_BIN_EXPOSE */
8088 /**
8089  * gtk_tree_view_create_row_drag_icon:
8090  * @tree_view: a #GtkTreeView
8091  * @path: a #GtkTreePath in @tree_view
8092  *
8093  * Creates a GdkPixmap representation of the row at @path.  This image is used
8094  * for a drag icon.
8095  *
8096  * Return value: a newly allocatdd pixmap of the drag icon.
8097  **/
8098 GdkPixmap *
8099 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
8100                                     GtkTreePath  *path)
8101 {
8102   GtkTreeIter   iter;
8103   GtkRBTree    *tree;
8104   GtkRBNode    *node;
8105   gint cell_offset;
8106   GList *list;
8107   GdkRectangle background_area;
8108   GtkWidget *widget;
8109   gint depth;
8110   /* start drawing inside the black outline */
8111   gint x = 1, y = 1;
8112   GdkDrawable *drawable;
8113   gint bin_window_width;
8114
8115   widget = GTK_WIDGET (tree_view);
8116
8117   depth = gtk_tree_path_get_depth (path);
8118
8119   _gtk_tree_view_find_node (tree_view,
8120                             path,
8121                             &tree,
8122                             &node);
8123
8124   if (tree == NULL)
8125     return NULL;
8126
8127   if (!gtk_tree_model_get_iter (tree_view->priv->model,
8128                                 &iter,
8129                                 path))
8130     return NULL;
8131
8132   cell_offset = x;
8133
8134   background_area.y = y;
8135   background_area.height = BACKGROUND_HEIGHT (node);
8136
8137   gdk_drawable_get_size (tree_view->priv->bin_window,
8138                          &bin_window_width, NULL);
8139
8140   drawable = gdk_pixmap_new (tree_view->priv->bin_window,
8141                              bin_window_width + 2,
8142                              background_area.height + 2,
8143                              -1);
8144
8145   gdk_draw_rectangle (drawable,
8146                       widget->style->base_gc [GTK_WIDGET_STATE (widget)],
8147                       TRUE,
8148                       0, 0,
8149                       bin_window_width + 2,
8150                       background_area.height + 2);
8151
8152   gdk_draw_rectangle (drawable,
8153                       widget->style->black_gc,
8154                       FALSE,
8155                       0, 0,
8156                       bin_window_width + 1,
8157                       background_area.height + 1);
8158
8159   for (list = tree_view->priv->columns; list; list = list->next)
8160     {
8161       GtkTreeViewColumn *column = list->data;
8162       GdkRectangle cell_area;
8163       gint vertical_separator;
8164
8165       if (!column->visible)
8166         continue;
8167
8168       gtk_tree_view_column_cell_set_cell_data (column, tree_view->priv->model, &iter);
8169
8170       background_area.x = cell_offset;
8171       background_area.width = column->displayed_width;
8172
8173       cell_area = background_area;
8174
8175       gtk_widget_style_get (widget, "vertical_separator", &vertical_separator, NULL);
8176       cell_area.y += vertical_separator / 2;
8177       cell_area.height -= vertical_separator;
8178
8179       if (gtk_tree_view_is_expander_column (tree_view, column) &&
8180           TREE_VIEW_DRAW_EXPANDERS(tree_view))
8181         {
8182           cell_area.x += depth * tree_view->priv->tab_offset;
8183           cell_area.width -= depth * tree_view->priv->tab_offset;
8184         }
8185
8186       if (gtk_tree_view_column_cell_is_visible (column))
8187         gtk_tree_view_column_cell_render (column,
8188                                           drawable,
8189                                           &background_area,
8190                                           &cell_area,
8191                                           NULL,
8192                                           0);
8193
8194       cell_offset += column->displayed_width;
8195     }
8196
8197   return drawable;
8198 }
8199
8200
8201 /**
8202  * gtk_tree_view_set_destroy_count_func:
8203  * @tree_view: A #GtkTreeView
8204  * @func: Function to be called when a view row is destroyed, or NULL
8205  * @data: User data to be passed to @func, or NULL
8206  * @destroy: Destroy notifier for @data, or NULL
8207  * 
8208  * This function should almost never be used.  It is meant for private use by
8209  * ATK for determining the number of visible children that are removed when the
8210  * user collapses a row, or a row is deleted.
8211  **/
8212 void
8213 gtk_tree_view_set_destroy_count_func (GtkTreeView             *tree_view,
8214                                       GtkTreeDestroyCountFunc  func,
8215                                       gpointer                 data,
8216                                       GtkDestroyNotify         destroy)
8217 {
8218   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
8219
8220   if (tree_view->priv->destroy_count_destroy)
8221     (* tree_view->priv->destroy_count_destroy) (tree_view->priv->destroy_count_data);
8222
8223   tree_view->priv->destroy_count_func = func;
8224   tree_view->priv->destroy_count_data = data;
8225   tree_view->priv->destroy_count_destroy = destroy;
8226 }