]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
marshaller fixes.
[~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
35 #include <gdk/gdkkeysyms.h>
36
37
38
39 /* The "background" areas of all rows/cells add up to cover the entire tree.
40  * The background includes all inter-row and inter-cell spacing.
41  * The "cell" areas are the cell_area passed in to gtk_cell_renderer_render(),
42  * i.e. just the cells, no spacing.
43  */
44
45 #define BACKGROUND_FIRST_PIXEL(tree_view,tree,node) (_gtk_rbtree_node_find_offset ((tree), (node)) + TREE_VIEW_HEADER_HEIGHT ((tree_view)))
46 #define CELL_FIRST_PIXEL(tree_view,tree,node) (BACKGROUND_FIRST_PIXEL (tree_view,tree,node) + TREE_VIEW_VERTICAL_SEPARATOR/2)
47
48 #define BACKGROUND_HEIGHT(node) (GTK_RBNODE_GET_HEIGHT (node))
49 #define CELL_HEIGHT(node) (BACKGROUND_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR);
50
51 #define TREE_WINDOW_Y_TO_RBTREE_Y(tree_view,y) ((y) - TREE_VIEW_HEADER_HEIGHT (tree_view))
52 #define RBTREE_Y_TO_TREE_WINDOW_Y(tree_view,y) ((y) + TREE_VIEW_HEADER_HEIGHT (tree_view))
53
54 typedef struct _GtkTreeViewChild GtkTreeViewChild;
55
56 struct _GtkTreeViewChild
57 {
58   GtkWidget *widget;
59   gint x;
60   gint y;
61 };
62
63 enum {
64   PROP_0,
65
66   PROP_MODEL,
67   PROP_HADJUSTMENT,
68   PROP_VADJUSTMENT,
69   PROP_HEADERS_VISIBLE,
70   PROP_HEADERS_CLICKABLE,
71   PROP_EXPANDER_COLUMN,
72   PROP_RULES_HINT
73 };
74
75 static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);
76 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
77 static void     gtk_tree_view_set_property         (GObject         *object,
78                                                     guint            prop_id,
79                                                     const GValue    *value,
80                                                     GParamSpec      *pspec,
81                                                     const gchar     *trailer);
82 static void     gtk_tree_view_get_property         (GObject         *object,
83                                                     guint            prop_id,
84                                                     GValue          *value,
85                                                     GParamSpec      *pspec,
86                                                     const gchar     *trailer);
87 /* object signals */
88 static void     gtk_tree_view_finalize             (GObject          *object);
89
90 /* widget signals */
91 static void     gtk_tree_view_setup_model          (GtkTreeView      *tree_view);
92 static void     gtk_tree_view_realize              (GtkWidget        *widget);
93 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
94 static void     gtk_tree_view_map                  (GtkWidget        *widget);
95 static void     gtk_tree_view_size_request         (GtkWidget        *widget,
96                                                     GtkRequisition   *requisition);
97 static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
98                                                     GtkAllocation    *allocation);
99 static gboolean gtk_tree_view_expose               (GtkWidget        *widget,
100                                                     GdkEventExpose   *event);
101 static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
102                                                     GdkEventMotion   *event);
103 static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
104                                                     GdkEventCrossing *event);
105 static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
106                                                     GdkEventCrossing *event);
107 static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
108                                                     GdkEventButton   *event);
109 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
110                                                     GdkEventButton   *event);
111 static void     gtk_tree_view_draw_focus           (GtkWidget        *widget);
112 static gint     gtk_tree_view_focus_in             (GtkWidget        *widget,
113                                                     GdkEventFocus    *event);
114 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
115                                                     GdkEventFocus    *event);
116 static gint     gtk_tree_view_focus                (GtkContainer     *container,
117                                                     GtkDirectionType  direction);
118
119 /* container signals */
120 static void     gtk_tree_view_remove               (GtkContainer     *container,
121                                                     GtkWidget        *widget);
122 static void     gtk_tree_view_forall               (GtkContainer     *container,
123                                                     gboolean          include_internals,
124                                                     GtkCallback       callback,
125                                                     gpointer          callback_data);
126
127 /* Source side drag signals */
128 static void gtk_tree_view_drag_begin       (GtkWidget        *widget,
129                                             GdkDragContext   *context);
130 static void gtk_tree_view_drag_end         (GtkWidget        *widget,
131                                             GdkDragContext   *context);
132 static void gtk_tree_view_drag_data_get    (GtkWidget        *widget,
133                                             GdkDragContext   *context,
134                                             GtkSelectionData *selection_data,
135                                             guint             info,
136                                             guint             time);
137 static void gtk_tree_view_drag_data_delete (GtkWidget        *widget,
138                                             GdkDragContext   *context);
139
140 /* Target side drag signals */
141 static void     gtk_tree_view_drag_leave         (GtkWidget        *widget,
142                                                   GdkDragContext   *context,
143                                                   guint             time);
144 static gboolean gtk_tree_view_drag_motion        (GtkWidget        *widget,
145                                                   GdkDragContext   *context,
146                                                   gint              x,
147                                                   gint              y,
148                                                   guint             time);
149 static gboolean gtk_tree_view_drag_drop          (GtkWidget        *widget,
150                                                   GdkDragContext   *context,
151                                                   gint              x,
152                                                   gint              y,
153                                                   guint             time);
154 static void     gtk_tree_view_drag_data_received (GtkWidget        *widget,
155                                                   GdkDragContext   *context,
156                                                   gint              x,
157                                                   gint              y,
158                                                   GtkSelectionData *selection_data,
159                                                   guint             info,
160                                                   guint             time);
161
162 /* tree_model signals */
163 static void     gtk_tree_view_set_adjustments      (GtkTreeView      *tree_view,
164                                                     GtkAdjustment    *hadj,
165                                                     GtkAdjustment    *vadj);
166 static void     gtk_tree_view_changed              (GtkTreeModel     *model,
167                                                     GtkTreePath      *path,
168                                                     GtkTreeIter      *iter,
169                                                     gpointer          data);
170 static void     gtk_tree_view_inserted             (GtkTreeModel     *model,
171                                                     GtkTreePath      *path,
172                                                     GtkTreeIter      *iter,
173                                                     gpointer          data);
174 static void     gtk_tree_view_has_child_toggled    (GtkTreeModel     *model,
175                                                     GtkTreePath      *path,
176                                                     GtkTreeIter      *iter,
177                                                     gpointer          data);
178 static void     gtk_tree_view_deleted              (GtkTreeModel     *model,
179                                                     GtkTreePath      *path,
180                                                     gpointer          data);
181
182 /* Internal functions */
183 static void     gtk_tree_view_queue_draw_node      (GtkTreeView      *tree_view,
184                                                     GtkRBTree        *tree,
185                                                     GtkRBNode        *node,
186                                                     GdkRectangle     *clip_rect);
187 static void     gtk_tree_view_queue_draw_path      (GtkTreeView      *tree_view,
188                                                     GtkTreePath      *path,
189                                                     GdkRectangle     *clip_rect);
190 static void     gtk_tree_view_draw_arrow           (GtkTreeView      *tree_view,
191                                                     GtkRBTree        *tree,
192                                                     GtkRBNode        *node,
193                                                     gint              x,
194                                                     gint              y);
195 static void     gtk_tree_view_get_arrow_xrange     (GtkTreeView      *tree_view,
196                                                     gint              *x1,
197                                                     gint              *x2);
198 static gint     gtk_tree_view_new_column_width     (GtkTreeView      *tree_view,
199                                                     gint              i,
200                                                     gint             *x);
201 static void     gtk_tree_view_adjustment_changed   (GtkAdjustment    *adjustment,
202                                                     GtkTreeView      *tree_view);
203 static gint     gtk_tree_view_insert_iter_height   (GtkTreeView      *tree_view,
204                                                     GtkRBTree        *tree,
205                                                     GtkTreeIter      *iter,
206                                                     gint              depth);
207 static void     gtk_tree_view_build_tree           (GtkTreeView      *tree_view,
208                                                     GtkRBTree        *tree,
209                                                     GtkTreeIter      *iter,
210                                                     gint              depth,
211                                                     gboolean          recurse,
212                                                     gboolean          calc_bounds);
213 static void     gtk_tree_view_calc_size            (GtkTreeView      *priv,
214                                                     GtkRBTree        *tree,
215                                                     GtkTreeIter      *iter,
216                                                     gint              depth);
217 static gboolean gtk_tree_view_discover_dirty_iter  (GtkTreeView      *tree_view,
218                                                     GtkTreeIter      *iter,
219                                                     gint              depth,
220                                                     gint             *height);
221 static void     gtk_tree_view_discover_dirty       (GtkTreeView      *tree_view,
222                                                     GtkRBTree        *tree,
223                                                     GtkTreeIter      *iter,
224                                                     gint              depth);
225 static void     gtk_tree_view_check_dirty          (GtkTreeView      *tree_view);
226 #if 0
227 static void     gtk_tree_view_create_button        (GtkTreeView      *tree_view,
228                                                     gint              i);
229 static void     gtk_tree_view_create_buttons       (GtkTreeView      *tree_view);
230 #endif
231 static void     gtk_tree_view_clamp_node_visible   (GtkTreeView      *tree_view,
232                                                     GtkRBTree        *tree,
233                                                     GtkRBNode        *node);
234 static gboolean gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
235                                                         GdkEventMotion   *event);
236 static void     _gtk_tree_view_update_col_width    (GtkTreeView      *tree_view);
237
238
239 static GtkContainerClass *parent_class = NULL;
240
241
242 /* Class Functions */
243 GtkType
244 gtk_tree_view_get_type (void)
245 {
246   static GtkType tree_view_type = 0;
247
248   if (!tree_view_type)
249     {
250       static const GTypeInfo tree_view_info =
251       {
252         sizeof (GtkTreeViewClass),
253         NULL,           /* base_init */
254         NULL,           /* base_finalize */
255         (GClassInitFunc) gtk_tree_view_class_init,
256         NULL,           /* class_finalize */
257         NULL,           /* class_data */
258         sizeof (GtkTreeView),
259         0,              /* n_preallocs */
260         (GInstanceInitFunc) gtk_tree_view_init
261       };
262
263       tree_view_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView", &tree_view_info, 0);
264     }
265
266   return tree_view_type;
267 }
268
269 static void
270 gtk_tree_view_class_init (GtkTreeViewClass *class)
271 {
272   GObjectClass *o_class;
273   GtkObjectClass *object_class;
274   GtkWidgetClass *widget_class;
275   GtkContainerClass *container_class;
276
277   o_class = (GObjectClass *) class;
278   object_class = (GtkObjectClass *) class;
279   widget_class = (GtkWidgetClass *) class;
280   container_class = (GtkContainerClass *) class;
281
282   parent_class = g_type_class_peek_parent (class);
283
284   o_class->finalize = gtk_tree_view_finalize;
285   o_class->set_property = gtk_tree_view_set_property;
286   o_class->get_property = gtk_tree_view_get_property;
287
288   widget_class->realize = gtk_tree_view_realize;
289   widget_class->unrealize = gtk_tree_view_unrealize;
290   widget_class->map = gtk_tree_view_map;
291   widget_class->size_request = gtk_tree_view_size_request;
292   widget_class->size_allocate = gtk_tree_view_size_allocate;
293   widget_class->expose_event = gtk_tree_view_expose;
294   widget_class->motion_notify_event = gtk_tree_view_motion;
295   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
296   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
297   widget_class->button_press_event = gtk_tree_view_button_press;
298   widget_class->button_release_event = gtk_tree_view_button_release;
299   widget_class->focus_in_event = gtk_tree_view_focus_in;
300   widget_class->focus_out_event = gtk_tree_view_focus_out;
301
302   widget_class->drag_begin = gtk_tree_view_drag_begin;
303   widget_class->drag_end = gtk_tree_view_drag_end;
304   widget_class->drag_data_get = gtk_tree_view_drag_data_get;
305   widget_class->drag_data_delete = gtk_tree_view_drag_data_delete;
306
307   widget_class->drag_leave = gtk_tree_view_drag_leave;
308   widget_class->drag_motion = gtk_tree_view_drag_motion;
309   widget_class->drag_drop = gtk_tree_view_drag_drop;
310   widget_class->drag_data_received = gtk_tree_view_drag_data_received;
311   
312   container_class->forall = gtk_tree_view_forall;
313   container_class->remove = gtk_tree_view_remove;
314   container_class->focus = gtk_tree_view_focus;
315
316   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
317
318 #if 0
319   /* FIXME, tim needs to support interface prerequisits in GType */
320   g_object_class_install_property (o_class,
321                                    PROP_MODEL,
322                                    g_param_spec_object ("model",
323                                                         _("TreeView Model"),
324                                                         _("The model for the tree view"),
325                                                         GTK_TYPE_TREE_MODEL,
326                                                         G_PARAM_READWRITE));
327 #endif
328   
329   g_object_class_install_property (o_class,
330                                    PROP_HADJUSTMENT,
331                                    g_param_spec_object ("hadjustment",
332                                                         _("Horizontal Adjustment"),
333                                                         _("Horizontal Adjustment for the widget"),
334                                                         GTK_TYPE_ADJUSTMENT,
335                                                         G_PARAM_READWRITE));
336
337   g_object_class_install_property (o_class,
338                                    PROP_VADJUSTMENT,
339                                    g_param_spec_object ("vadjustment",
340                                                         _("Vertical Adjustment"),
341                                                         _("Vertical Adjustment for the widget"),
342                                                         GTK_TYPE_ADJUSTMENT,
343                                                         G_PARAM_READWRITE));
344
345   g_object_class_install_property (o_class,
346                                    PROP_HEADERS_VISIBLE,
347                                    g_param_spec_boolean ("headers_visible",
348                                                          _("Visible"),
349                                                          _("Show the column header buttons"),
350                                                          FALSE,
351                                                          G_PARAM_READWRITE));
352
353   g_object_class_install_property (o_class,
354                                    PROP_HEADERS_CLICKABLE,
355                                    g_param_spec_boolean ("headers_clickable",
356                                                          _("Headers Clickable"),
357                                                          _("Column headers respond to click events"),
358                                                          FALSE,
359                                                          G_PARAM_READWRITE));
360
361   g_object_class_install_property (o_class,
362                                    PROP_EXPANDER_COLUMN,
363                                    g_param_spec_uint ("expander_column",
364                                                       _("Expand Column"),
365                                                       _("Set the column number for the expander column"),
366                                                       0,
367                                                       G_MAXINT,
368                                                       0,
369                                                       G_PARAM_READWRITE));
370
371   g_object_class_install_property (o_class,
372                                    PROP_RULES_HINT,
373                                    g_param_spec_boolean ("rules_hint",
374                                                          _("Rules Hint"),
375                                                          _("Set a hint to the theme engine to draw rows in alternating colors"),
376                                                          FALSE,
377                                                          G_PARAM_READWRITE));
378
379   widget_class->set_scroll_adjustments_signal =
380     gtk_signal_new ("set_scroll_adjustments",
381                     GTK_RUN_LAST,
382                     GTK_CLASS_TYPE (object_class),
383                     GTK_SIGNAL_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
384                     gtk_marshal_VOID__OBJECT_OBJECT,
385                     GTK_TYPE_NONE, 2,
386                     GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
387 }
388
389 static void
390 gtk_tree_view_init (GtkTreeView *tree_view)
391 {
392   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
393
394   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
395
396   tree_view->priv->model = NULL;
397   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
398   tree_view->priv->tab_offset = TREE_VIEW_EXPANDER_WIDTH;
399   tree_view->priv->n_columns = 0;
400   tree_view->priv->columns = NULL;
401   tree_view->priv->button_pressed_node = NULL;
402   tree_view->priv->button_pressed_tree = NULL;
403   tree_view->priv->prelight_node = NULL;
404   tree_view->priv->header_height = 1;
405   tree_view->priv->x_drag = 0;
406   tree_view->priv->drag_pos = -1;
407   tree_view->priv->selection = NULL;
408   tree_view->priv->anchor = NULL;
409   tree_view->priv->cursor = NULL;
410
411   tree_view->priv->pressed_button = -1;
412   tree_view->priv->press_start_x = -1;
413   tree_view->priv->press_start_y = -1;
414   
415   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
416   _gtk_tree_view_update_size (tree_view);
417 }
418
419
420 /* Object methods
421  */
422
423 static void
424 gtk_tree_view_finalize (GObject *object)
425 {
426   GtkTreeView *tree_view = (GtkTreeView *) object;
427
428   if (tree_view->priv->tree)
429     _gtk_rbtree_free (tree_view->priv->tree);
430
431   if (tree_view->priv->scroll_to_path != NULL)
432     gtk_tree_path_free (tree_view->priv->scroll_to_path);
433
434   if (tree_view->priv->drag_dest_row)
435     gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
436   
437   g_free (tree_view->priv);
438   if (G_OBJECT_CLASS (parent_class)->finalize)
439     (* G_OBJECT_CLASS (parent_class)->finalize) (object);
440 }
441
442 /* Property handlers
443  */
444
445 static void
446 gtk_tree_view_set_property (GObject         *object,
447                             guint            prop_id,
448                             const GValue    *value,
449                             GParamSpec      *pspec,
450                             const gchar     *trailer)
451 {
452   GtkTreeView *tree_view;
453
454   tree_view = GTK_TREE_VIEW (object);
455
456   switch (prop_id)
457     {
458     case PROP_MODEL:
459       gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (g_value_get_object (value)));
460       break;
461     case PROP_HADJUSTMENT:
462       gtk_tree_view_set_hadjustment (tree_view, GTK_ADJUSTMENT (g_value_get_object (value)));
463       break;
464     case PROP_VADJUSTMENT:
465       gtk_tree_view_set_vadjustment (tree_view, GTK_ADJUSTMENT (g_value_get_object (value)));
466       break;
467     case PROP_HEADERS_VISIBLE:
468       gtk_tree_view_set_headers_visible (tree_view, g_value_get_boolean (value));
469       break;
470     case PROP_HEADERS_CLICKABLE:
471       gtk_tree_view_set_headers_clickable (tree_view, g_value_get_boolean (value));
472       break;
473     case PROP_EXPANDER_COLUMN:
474       gtk_tree_view_set_expander_column (tree_view, g_value_get_uint (value));
475       break;
476     case PROP_RULES_HINT:
477       gtk_tree_view_set_rules_hint (tree_view, g_value_get_boolean (value));
478       break;
479     default:
480       break;
481     }
482 }
483
484 static void
485 gtk_tree_view_get_property (GObject         *object,
486                             guint            prop_id,
487                             GValue          *value,
488                             GParamSpec      *pspec,
489                             const gchar     *trailer)
490 {
491   GtkTreeView *tree_view;
492
493   tree_view = GTK_TREE_VIEW (object);
494   
495   switch (prop_id)
496     {
497     case PROP_MODEL:
498       g_value_set_object (value, G_OBJECT (tree_view->priv->model));
499       break;
500     case PROP_HADJUSTMENT:
501       g_value_set_object (value, G_OBJECT (tree_view->priv->hadjustment));
502       break;
503     case PROP_VADJUSTMENT:
504       g_value_set_object (value, G_OBJECT (tree_view->priv->vadjustment));
505       break;
506     case PROP_HEADERS_VISIBLE:
507       g_value_set_boolean (value, gtk_tree_view_get_headers_visible (tree_view));
508       break;
509     case PROP_HEADERS_CLICKABLE:
510       /* g_value_set_boolean (value, gtk_tree_view_get_headers_clickable (tree_view)); */
511       break;
512     case PROP_EXPANDER_COLUMN:
513       g_value_set_uint (value, tree_view->priv->expander_column);
514       break;
515     case PROP_RULES_HINT:
516       g_value_set_boolean (value, tree_view->priv->has_rules);
517       break;
518     default:
519       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
520       break;
521     }
522 }
523
524 /* Widget methods
525  */
526
527 static void
528 gtk_tree_view_realize (GtkWidget *widget)
529 {
530   GList *tmp_list;
531   GtkTreeView *tree_view;
532   GdkGCValues values;
533   GdkWindowAttr attributes;
534   gint attributes_mask;
535
536   g_return_if_fail (widget != NULL);
537   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
538
539   tree_view = GTK_TREE_VIEW (widget);
540
541   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
542   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
543
544   /* Make the main, clipping window */
545   attributes.window_type = GDK_WINDOW_CHILD;
546   attributes.x = widget->allocation.x;
547   attributes.y = widget->allocation.y;
548   attributes.width = widget->allocation.width;
549   attributes.height = widget->allocation.height;
550   attributes.wclass = GDK_INPUT_OUTPUT;
551   attributes.visual = gtk_widget_get_visual (widget);
552   attributes.colormap = gtk_widget_get_colormap (widget);
553   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
554
555   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
556
557   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
558                                    &attributes, attributes_mask);
559   gdk_window_set_user_data (widget->window, widget);
560
561   /* Make the window for the tree */
562   attributes.x = 0;
563   attributes.y = 0;
564   attributes.width = tree_view->priv->width;
565   attributes.height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
566   attributes.event_mask = GDK_EXPOSURE_MASK |
567     GDK_SCROLL_MASK |
568     GDK_POINTER_MOTION_MASK |
569     GDK_ENTER_NOTIFY_MASK |
570     GDK_LEAVE_NOTIFY_MASK |
571     GDK_BUTTON_PRESS_MASK |
572     GDK_BUTTON_RELEASE_MASK |
573     gtk_widget_get_events (widget);
574
575   tree_view->priv->bin_window = gdk_window_new (widget->window,
576                                                 &attributes, attributes_mask);
577   gdk_window_set_user_data (tree_view->priv->bin_window, widget);
578
579   /* Make the column header window */
580   attributes.x = 0;
581   attributes.y = 0;
582   attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
583   attributes.height = tree_view->priv->header_height;
584   attributes.event_mask = (GDK_EXPOSURE_MASK |
585                            GDK_SCROLL_MASK |
586                            GDK_BUTTON_PRESS_MASK |
587                            GDK_BUTTON_RELEASE_MASK |
588                            GDK_KEY_PRESS_MASK |
589                            GDK_KEY_RELEASE_MASK) |
590     gtk_widget_get_events (widget);
591
592   tree_view->priv->header_window = gdk_window_new (widget->window,
593                                                    &attributes, attributes_mask);
594   gdk_window_set_user_data (tree_view->priv->header_window, widget);
595
596
597   values.foreground = (widget->style->white.pixel==0 ?
598                        widget->style->black:widget->style->white);
599   values.function = GDK_XOR;
600   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
601   tree_view->priv->xor_gc = gdk_gc_new_with_values (widget->window,
602                                                     &values,
603                                                     GDK_GC_FOREGROUND |
604                                                     GDK_GC_FUNCTION |
605                                                     GDK_GC_SUBWINDOW);
606   /* Add them all up. */
607   widget->style = gtk_style_attach (widget->style, widget->window);
608   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
609   gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
610   gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
611
612   tmp_list = tree_view->priv->children;
613   while (tmp_list)
614     {
615       GtkTreeViewChild *child = tmp_list->data;
616       tmp_list = tmp_list->next;
617
618       gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
619     }
620
621   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
622     _gtk_tree_view_column_realize_button (GTK_TREE_VIEW_COLUMN (tmp_list->data));
623
624   _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
625
626   if (tree_view->priv->scroll_to_path != NULL ||
627       tree_view->priv->scroll_to_column != NULL)
628     {
629       gtk_tree_view_scroll_to_cell (tree_view,
630                                     tree_view->priv->scroll_to_path,
631                                     tree_view->priv->scroll_to_column,
632                                     tree_view->priv->scroll_to_row_align,
633                                     tree_view->priv->scroll_to_col_align);
634       if (tree_view->priv->scroll_to_path)
635         {
636           gtk_tree_path_free (tree_view->priv->scroll_to_path);
637           tree_view->priv->scroll_to_path = NULL;
638         }
639       tree_view->priv->scroll_to_column = NULL;
640     }
641 }
642
643 static void
644 gtk_tree_view_unrealize (GtkWidget *widget)
645 {
646   GtkTreeView *tree_view;
647   GList *list;
648
649   g_return_if_fail (widget != NULL);
650   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
651
652   tree_view = GTK_TREE_VIEW (widget);
653
654   if (tree_view->priv->scroll_timeout != 0)
655     {
656       gtk_timeout_remove (tree_view->priv->scroll_timeout);
657       tree_view->priv->scroll_timeout = 0;
658     }
659
660   if (tree_view->priv->open_dest_timeout != 0)
661     {
662       gtk_timeout_remove (tree_view->priv->open_dest_timeout);
663       tree_view->priv->open_dest_timeout = 0;
664     }
665
666   for (list = tree_view->priv->columns; list; list = list->next)
667     _gtk_tree_view_column_unrealize_button (GTK_TREE_VIEW_COLUMN (list->data));
668
669   gdk_window_set_user_data (tree_view->priv->bin_window, NULL);
670   gdk_window_destroy (tree_view->priv->bin_window);
671   tree_view->priv->bin_window = NULL;
672
673   gdk_window_set_user_data (tree_view->priv->header_window, NULL);
674   gdk_window_destroy (tree_view->priv->header_window);
675   tree_view->priv->header_window = NULL;
676
677   gdk_cursor_destroy (tree_view->priv->cursor_drag);
678   gdk_gc_destroy (tree_view->priv->xor_gc);  
679   
680   /* GtkWidget::unrealize destroys children and widget->window */
681   
682   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
683     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
684 }
685
686 static void
687 gtk_tree_view_map_buttons (GtkTreeView *tree_view)
688 {
689   GList *list;
690
691   g_return_if_fail (GTK_WIDGET_MAPPED (tree_view));
692   
693   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
694     {
695       GtkTreeViewColumn *column;
696       
697       for (list = tree_view->priv->columns; list; list = list->next)
698         {
699           column = list->data;
700           if (GTK_WIDGET_VISIBLE (column->button) &&
701               !GTK_WIDGET_MAPPED (column->button))
702             gtk_widget_map (column->button);
703         }
704       for (list = tree_view->priv->columns; list; list = list->next)
705         {
706           column = list->data;
707           if (column->visible == FALSE)
708             continue;
709           if (column->column_type == GTK_TREE_VIEW_COLUMN_RESIZEABLE)
710             {
711               gdk_window_raise (column->window);
712               gdk_window_show (column->window);
713             }
714           else
715             gdk_window_hide (column->window);
716         }
717       gdk_window_show (tree_view->priv->header_window);
718     }
719 }
720
721 static void
722 gtk_tree_view_map (GtkWidget *widget)
723 {
724   GList *tmp_list;
725   GtkTreeView *tree_view;
726
727   g_return_if_fail (widget != NULL);
728   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
729
730   tree_view = GTK_TREE_VIEW (widget);
731
732   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
733
734   tmp_list = tree_view->priv->children;
735   while (tmp_list)
736     {
737       GtkTreeViewChild *child = tmp_list->data;
738       tmp_list = tmp_list->next;
739
740       if (GTK_WIDGET_VISIBLE (child->widget))
741         {
742           if (!GTK_WIDGET_MAPPED (child->widget))
743             gtk_widget_map (child->widget);
744         }
745     }
746   gdk_window_show (tree_view->priv->bin_window);
747
748   gtk_tree_view_map_buttons (tree_view);
749   
750   gdk_window_show (widget->window);
751 }
752
753 static void
754 gtk_tree_view_size_request_buttons (GtkTreeView *tree_view)
755 {
756   GList *list;
757   
758   tree_view->priv->header_height = 1;
759
760   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
761     {
762       for (list = tree_view->priv->columns; list; list = list->next)
763         {
764           GtkRequisition requisition;
765           GtkTreeViewColumn *column;
766           
767           column = list->data;
768           
769           gtk_widget_size_request (column->button, &requisition);
770           
771           gtk_tree_view_column_set_width (column, MAX (column->width, requisition.width));
772           tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
773         }
774     }
775 }
776
777 static void
778 gtk_tree_view_size_request (GtkWidget      *widget,
779                             GtkRequisition *requisition)
780 {
781   GtkTreeView *tree_view;
782   GList *tmp_list;
783
784   g_return_if_fail (widget != NULL);
785   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
786
787   tree_view = GTK_TREE_VIEW (widget);
788
789   requisition->width = 200;
790   requisition->height = 200;
791
792   tmp_list = tree_view->priv->children;
793
794   while (tmp_list)
795     {
796       GtkTreeViewChild *child = tmp_list->data;
797       GtkRequisition child_requisition;
798
799       tmp_list = tmp_list->next;
800
801       if (GTK_WIDGET_VISIBLE (child->widget))
802         gtk_widget_size_request (child->widget, &child_requisition);
803     }
804
805   gtk_tree_view_size_request_buttons (tree_view);
806 }
807
808 static void
809 gtk_tree_view_size_allocate_buttons (GtkWidget *widget)
810 {
811   GtkTreeView *tree_view;
812   GList *list;
813   GtkTreeViewColumn *column;
814   GtkAllocation allocation;
815   gint width = 0;
816   
817   tree_view = GTK_TREE_VIEW (widget);
818
819   allocation.y = 0;
820   allocation.height = tree_view->priv->header_height;
821
822   for (list = tree_view->priv->columns; list != NULL; list = list->next)
823     {
824       column = list->data;
825
826       if (!column->visible)
827         continue;
828
829       allocation.x = width;
830       allocation.width = column->displayed_width;
831       width += column->width;
832       gtk_widget_size_allocate (column->button, &allocation);
833
834       if (column->window)
835         gdk_window_move_resize (column->window,
836                                 allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
837                                 allocation.y,
838                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
839     }
840 }
841
842 static void
843 gtk_tree_view_size_allocate (GtkWidget     *widget,
844                              GtkAllocation *allocation)
845 {
846   GList *tmp_list;
847   GtkTreeView *tree_view;
848
849   g_return_if_fail (widget != NULL);
850   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
851
852   widget->allocation = *allocation;
853
854   tree_view = GTK_TREE_VIEW (widget);
855   
856   gtk_tree_view_check_dirty (tree_view);
857   
858   tmp_list = tree_view->priv->children;
859
860   while (tmp_list)
861     {
862       GtkAllocation allocation;
863       GtkRequisition requisition;
864
865       GtkTreeViewChild *child = tmp_list->data;
866       tmp_list = tmp_list->next;
867
868       allocation.x = child->x;
869       allocation.y = child->y;
870       gtk_widget_get_child_requisition (child->widget, &requisition);
871       allocation.width = requisition.width;
872       allocation.height = requisition.height;
873
874       gtk_widget_size_allocate (child->widget, &allocation);
875     }
876
877   if (GTK_WIDGET_REALIZED (widget))
878     {
879       gdk_window_move_resize (widget->window,
880                               allocation->x, allocation->y,
881                               allocation->width, allocation->height);
882
883       gdk_window_move_resize (tree_view->priv->header_window,
884                               0, 0,
885                               MAX (tree_view->priv->width, allocation->width),
886                               tree_view->priv->header_height);
887
888       if (tree_view->priv->width < allocation->width)
889         gdk_window_resize (tree_view->priv->bin_window,
890                            allocation->width,
891                            tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view));
892
893       _gtk_tree_view_update_col_width (tree_view);
894     }
895   
896   gtk_tree_view_size_allocate_buttons (widget);
897
898   tree_view->priv->hadjustment->page_size = allocation->width;
899   tree_view->priv->hadjustment->page_increment = allocation->width / 2;
900   tree_view->priv->hadjustment->lower = 0;
901   tree_view->priv->hadjustment->upper = tree_view->priv->width;
902
903   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
904     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
905   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
906
907   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
908   tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
909   tree_view->priv->vadjustment->lower = 0;
910   tree_view->priv->vadjustment->upper = tree_view->priv->height;
911
912   if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height)
913     gtk_adjustment_set_value (tree_view->priv->vadjustment,
914                               (gfloat) MAX (tree_view->priv->height - allocation->height, 0));
915
916   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
917
918 }
919
920 static void
921 gtk_tree_view_draw_node_focus_rect (GtkWidget   *widget,
922                                     GtkTreePath *path)
923 {
924   GtkTreeView *tree_view;
925   GtkRBTree *tree = NULL;
926   GtkRBNode *node = NULL;
927   gint bin_window_width = 0;
928   
929   g_return_if_fail (widget != NULL);
930   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
931
932   tree_view = GTK_TREE_VIEW (widget);
933
934   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
935
936   if (tree == NULL)
937     return;
938
939   gdk_drawable_get_size (tree_view->priv->bin_window,
940                          &bin_window_width, NULL);
941   
942   /* FIXME need a style function appropriate for this */
943   gdk_draw_rectangle (tree_view->priv->bin_window,
944                       widget->style->fg_gc[GTK_STATE_NORMAL],
945                       FALSE,
946                       0,
947                       BACKGROUND_FIRST_PIXEL (tree_view, tree, node),
948                       bin_window_width - 2,
949                       BACKGROUND_HEIGHT (node) - 1);
950 }
951
952 GdkPixmap*
953 gtk_tree_view_create_row_drag_icon (GtkTreeView  *tree_view,
954                                     GtkTreePath  *path)
955 {
956   GtkTreeIter   iter;
957   GtkRBTree    *tree;
958   GtkRBNode    *node;
959   GtkCellRenderer *cell;
960   gint i;
961   gint cell_offset;
962   GList *list;
963   GdkRectangle background_area;
964   GtkWidget *widget;
965   gint depth;
966   /* start drawing inside the black outline */
967   gint x = 1, y = 1;
968   GdkDrawable *drawable;
969   gint bin_window_width;
970   
971   widget = GTK_WIDGET (tree_view);
972
973   depth = gtk_tree_path_get_depth (path);
974
975   _gtk_tree_view_find_node (tree_view,
976                             path,
977                             &tree,
978                             &node);
979
980   if (tree == NULL)
981     return NULL;
982   
983   if (!gtk_tree_model_get_iter (tree_view->priv->model,
984                                 &iter,
985                                 path))
986     return NULL;
987     
988   cell_offset = x;
989
990   background_area.y = y;
991   background_area.height = BACKGROUND_HEIGHT (node);
992
993   gdk_drawable_get_size (tree_view->priv->bin_window,
994                          &bin_window_width, NULL);
995   
996   drawable = gdk_pixmap_new (tree_view->priv->bin_window,
997                              bin_window_width + 2,
998                              background_area.height + 2,
999                              -1);
1000
1001   gdk_draw_rectangle (drawable,
1002                       widget->style->base_gc[GTK_WIDGET_STATE (widget)],
1003                       TRUE,
1004                       0, 0,
1005                       bin_window_width + 2,
1006                       background_area.height + 2);
1007
1008   gdk_draw_rectangle (drawable,
1009                       widget->style->black_gc,
1010                       FALSE,
1011                       0, 0,
1012                       bin_window_width + 1,
1013                       background_area.height + 1);
1014   
1015   for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
1016     {
1017       GtkTreeViewColumn *column = list->data;
1018       GdkRectangle cell_area;
1019       
1020       if (!column->visible)
1021         continue;
1022
1023       cell = column->cell;
1024       gtk_tree_view_column_set_cell_data (column,
1025                                           tree_view->priv->model,
1026                                           &iter);
1027
1028       background_area.x = cell_offset;
1029       background_area.width = column->displayed_width;
1030
1031       cell_area = background_area;
1032
1033       cell_area.y += TREE_VIEW_VERTICAL_SEPARATOR / 2;
1034       cell_area.height -= TREE_VIEW_VERTICAL_SEPARATOR;
1035       
1036       if (i == tree_view->priv->expander_column &&
1037           TREE_VIEW_DRAW_EXPANDERS(tree_view))
1038         {
1039           cell_area.x += depth * tree_view->priv->tab_offset;
1040           cell_area.width -= depth * tree_view->priv->tab_offset;
1041         }
1042       
1043       gtk_cell_renderer_render (cell,
1044                                 drawable,
1045                                 widget,
1046                                 &background_area,
1047                                 &cell_area,
1048                                 NULL,
1049                                 0);
1050       
1051       cell_offset += column->displayed_width;
1052     }
1053
1054   return drawable;
1055 }
1056
1057 /* Warning: Very scary function.
1058  * Modify at your own risk
1059  */
1060 static gboolean
1061 gtk_tree_view_bin_expose (GtkWidget      *widget,
1062                           GdkEventExpose *event)
1063 {
1064   GtkTreeView *tree_view;
1065   GtkTreePath *path;
1066   GtkRBTree *tree;
1067   GList *list;
1068   GtkRBNode *node;
1069   GtkRBNode *cursor = NULL;
1070   GtkRBTree *cursor_tree = NULL;
1071   GtkRBNode *drag_highlight = NULL;
1072   GtkRBTree *drag_highlight_tree = NULL;
1073   GtkTreeIter iter;
1074   GtkCellRenderer *cell;
1075   gint new_y;
1076   gint y_offset, x_offset, cell_offset;
1077   gint i, max_height;
1078   gint depth;
1079   GdkRectangle background_area;
1080   GdkRectangle cell_area;
1081   guint flags;
1082   gint highlight_x;
1083   gint bin_window_width;
1084   GtkTreePath *cursor_path;
1085   GtkTreePath *drag_dest_path;
1086   GList *last_column;
1087
1088   g_return_val_if_fail (widget != NULL, FALSE);
1089   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1090
1091   tree_view = GTK_TREE_VIEW (widget);
1092
1093   if (tree_view->priv->tree == NULL)
1094     return TRUE;
1095   
1096   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
1097   /* we want to account for a potential HEADER offset.
1098    * That is, if the header exists, we want to offset our event by its
1099    * height to find the right node.
1100    */
1101   new_y = (event->area.y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):event->area.y;
1102
1103   /* y_offset is the */
1104   
1105   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
1106                                        TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
1107                                        &tree,
1108                                        &node) + new_y - event->area.y;
1109   if (node == NULL)
1110     return TRUE;
1111
1112   /* find the path for the node */
1113   path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
1114                                    tree,
1115                                    node);
1116   gtk_tree_model_get_iter (tree_view->priv->model,
1117                            &iter,
1118                            path);
1119   depth = gtk_tree_path_get_depth (path);
1120   gtk_tree_path_free (path);
1121
1122   cursor_path = NULL;
1123   drag_dest_path = NULL;
1124   
1125   if (tree_view->priv->cursor)
1126     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1127
1128   if (cursor_path)
1129     _gtk_tree_view_find_node (tree_view, cursor_path,
1130                               &cursor_tree, &cursor);
1131
1132   if (tree_view->priv->drag_dest_row)
1133     drag_dest_path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
1134
1135   if (drag_dest_path)
1136     _gtk_tree_view_find_node (tree_view, drag_dest_path,
1137                               &drag_highlight_tree, &drag_highlight);
1138
1139   gdk_drawable_get_size (tree_view->priv->bin_window,
1140                          &bin_window_width, NULL);
1141
1142   for (last_column = g_list_last (tree_view->priv->columns);
1143        last_column &&
1144          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
1145          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
1146        last_column = last_column->prev)
1147     ;
1148
1149   /* Actually process the expose event.  To do this, we want to
1150    * start at the first node of the event, and walk the tree in
1151    * order, drawing each successive node.
1152    */
1153
1154   do
1155     {
1156       /* Need to think about this more.
1157          if (tree_view->priv->show_expanders)
1158          max_height = MAX (TREE_VIEW_EXPANDER_MIN_HEIGHT, GTK_RBNODE_GET_HEIGHT (node));
1159          else
1160       */
1161       gboolean parity;
1162       
1163       max_height = BACKGROUND_HEIGHT (node);
1164
1165       x_offset = -event->area.x;
1166       cell_offset = 0;
1167       highlight_x = 0; /* should match x coord of first cell */
1168       
1169       background_area.y = y_offset + event->area.y;
1170       background_area.height = max_height;
1171       flags = 0;
1172
1173       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
1174         flags |= GTK_CELL_RENDERER_PRELIT;
1175
1176       parity = _gtk_rbtree_node_find_parity (tree, node);
1177       
1178       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
1179         flags |= GTK_CELL_RENDERER_SELECTED;
1180       
1181       for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
1182         {
1183           GtkTreeViewColumn *column = list->data;
1184           const gchar *detail = NULL;
1185           
1186           if (!column->visible)
1187             continue;
1188
1189           if (cell_offset > event->area.x + event->area.width ||
1190               cell_offset + column->displayed_width < event->area.x)
1191             {
1192               cell_offset += column->displayed_width;
1193               continue;
1194             }
1195
1196           if (column->show_sort_indicator)
1197             flags |= GTK_CELL_RENDERER_SORTED;
1198           else
1199             flags &= ~GTK_CELL_RENDERER_SORTED;
1200
1201           cell = column->cell;
1202           gtk_tree_view_column_set_cell_data (column,
1203                                               tree_view->priv->model,
1204                                               &iter);
1205
1206           background_area.x = cell_offset;
1207           background_area.width = column->displayed_width;
1208
1209           cell_area = background_area;
1210           cell_area.y += TREE_VIEW_VERTICAL_SEPARATOR / 2;
1211           cell_area.height -= TREE_VIEW_VERTICAL_SEPARATOR;
1212
1213           /* Select the detail for drawing the cell.  relevant
1214            * factors are parity, sortedness, and whether to
1215            * display rules.
1216            */
1217
1218           /* FIXME when we have style properties, clean this up.
1219            */
1220
1221           if (tree_view->priv->has_rules)
1222             {
1223               if (flags & GTK_CELL_RENDERER_SORTED)
1224                 {
1225                   if (parity)
1226                     detail = "cell_odd_ruled_sorted";
1227                   else
1228                     detail = "cell_even_ruled_sorted";
1229                 }
1230               else
1231                 {
1232                   if (parity)
1233                     detail = "cell_odd_ruled";
1234                   else
1235                     detail = "cell_even_ruled";
1236                 }
1237             }
1238           else
1239             {
1240               if (flags & GTK_CELL_RENDERER_SORTED)
1241                 {
1242                   if (parity)
1243                     detail = "cell_odd_sorted";
1244                   else
1245                     detail = "cell_even_sorted";
1246                 }
1247               else
1248                 {
1249                   if (parity)
1250                     detail = "cell_odd";
1251                   else
1252                     detail = "cell_even";
1253                 }
1254             }
1255
1256           g_assert (detail);
1257
1258           /* Draw background */
1259           gtk_paint_flat_box (widget->style,
1260                               event->window,
1261                               (flags & GTK_CELL_RENDERER_SELECTED) ?
1262                               GTK_STATE_SELECTED : GTK_STATE_NORMAL,
1263                               GTK_SHADOW_NONE,
1264                               &event->area,
1265                               widget,
1266                               detail,
1267                               background_area.x,
1268                               background_area.y,
1269                               background_area.width,
1270                               background_area.height);
1271           
1272           if (i == tree_view->priv->expander_column &&
1273               TREE_VIEW_DRAW_EXPANDERS(tree_view))
1274             {
1275               cell_area.x += depth*tree_view->priv->tab_offset;
1276               cell_area.width -= depth*tree_view->priv->tab_offset;
1277
1278               /* If we have an expander column, the highlight underline
1279                * starts with that column, so that it indicates which
1280                * level of the tree we're dropping at.
1281                */
1282               highlight_x = cell_area.x;
1283                 
1284               gtk_cell_renderer_render (cell,
1285                                         event->window,
1286                                         widget,
1287                                         &background_area,
1288                                         &cell_area,
1289                                         &event->area,
1290                                         flags);
1291
1292               if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
1293                 {
1294                   gint x, y;
1295                   gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, 0);
1296                   gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
1297                                             tree,
1298                                             node,
1299                                             x, y);
1300                 }
1301             }
1302           else
1303             {              
1304               gtk_cell_renderer_render (cell,
1305                                         event->window,
1306                                         widget,
1307                                         &background_area,
1308                                         &cell_area,
1309                                         &event->area,
1310                                         flags);
1311             }
1312           cell_offset += column->displayed_width;
1313         }
1314
1315       if (node == cursor &&
1316           GTK_WIDGET_HAS_FOCUS (widget))
1317         gtk_tree_view_draw_focus (widget);
1318
1319       if (node == drag_highlight)
1320         {
1321           /* Draw indicator for the drop
1322            */
1323           gint highlight_y = -1;
1324
1325           switch (tree_view->priv->drag_dest_pos)
1326             {
1327             case GTK_TREE_VIEW_DROP_BEFORE:
1328               highlight_y = background_area.y - TREE_VIEW_VERTICAL_SEPARATOR/2;
1329               break;
1330               
1331             case GTK_TREE_VIEW_DROP_AFTER:
1332               highlight_y = background_area.y + background_area.height + TREE_VIEW_VERTICAL_SEPARATOR/2;
1333               break;
1334               
1335             case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
1336             case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
1337               gtk_tree_view_draw_node_focus_rect (widget,
1338                                                   drag_dest_path);
1339               break;
1340             }
1341
1342           if (highlight_y >= 0)
1343             {
1344               gdk_draw_line (event->window,
1345                              widget->style->black_gc,
1346                              highlight_x,
1347                              highlight_y,
1348                              bin_window_width - highlight_x,
1349                              highlight_y);
1350             }
1351         }
1352       
1353       y_offset += max_height;
1354       if (node->children)
1355         {
1356           GtkTreeIter parent = iter;
1357           gboolean has_child;
1358
1359           tree = node->children;
1360           node = tree->root;
1361
1362           g_assert (node != tree->nil);
1363           
1364           while (node->left != tree->nil)
1365             node = node->left;
1366           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
1367                                                     &iter,
1368                                                     &parent);
1369           cell = gtk_tree_view_get_column (tree_view, 0)->cell;
1370           depth++;
1371
1372           /* Sanity Check! */
1373           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
1374         }
1375       else
1376         {
1377           gboolean done = FALSE;
1378           do
1379             {
1380               node = _gtk_rbtree_next (tree, node);
1381               if (node != NULL)
1382                 {
1383                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
1384                   cell = gtk_tree_view_get_column (tree_view, 0)->cell;
1385                   done = TRUE;
1386
1387                   /* Sanity Check! */
1388                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
1389                 }
1390               else
1391                 {
1392                   GtkTreeIter parent_iter = iter;
1393                   gboolean has_parent;
1394
1395                   node = tree->parent_node;
1396                   tree = tree->parent_tree;
1397                   if (tree == NULL)
1398                     /* we've run out of tree.  It's okay to return though, as
1399                      * we'd only break out of the while loop below. */
1400                     return TRUE;
1401                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
1402                                                            &iter,
1403                                                            &parent_iter);
1404                   depth--;
1405
1406                   /* Sanity check */
1407                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
1408                 }
1409             }
1410           while (!done);
1411         }
1412     }
1413   while (y_offset < event->area.height);
1414   
1415   if (cursor_path)
1416     gtk_tree_path_free (cursor_path);
1417
1418   if (drag_dest_path)
1419     gtk_tree_path_free (drag_dest_path);
1420   
1421   return TRUE;
1422 }
1423
1424 static gboolean
1425 gtk_tree_view_expose (GtkWidget      *widget,
1426                       GdkEventExpose *event)
1427 {
1428   GtkTreeView *tree_view;
1429
1430   g_return_val_if_fail (widget != NULL, FALSE);
1431   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1432
1433   tree_view = GTK_TREE_VIEW (widget);
1434
1435   if (event->window == tree_view->priv->bin_window)
1436     return gtk_tree_view_bin_expose (widget, event);
1437
1438   return TRUE;
1439 }
1440
1441 static gboolean
1442 coords_are_over_arrow (GtkTreeView *tree_view,
1443                        GtkRBTree   *tree,
1444                        GtkRBNode   *node,
1445                        /* these are in tree window coords */
1446                        gint         x,
1447                        gint         y)
1448 {
1449   GdkRectangle arrow;
1450   gint x2;
1451
1452   if (!GTK_WIDGET_REALIZED (tree_view))
1453     return FALSE;
1454   
1455   if ((node->flags & GTK_RBNODE_IS_PARENT) == 0)
1456     return FALSE;
1457   
1458   arrow.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
1459       
1460   arrow.height = BACKGROUND_HEIGHT (node);
1461
1462   gtk_tree_view_get_arrow_xrange (tree_view, &arrow.x, &x2);
1463
1464   arrow.width = x2 - arrow.x;
1465
1466   return (x >= arrow.x &&
1467           x < (arrow.x + arrow.height) &&
1468           y >= arrow.y &&
1469           y < (arrow.y + arrow.height));  
1470 }
1471
1472 static void
1473 do_unprelight (GtkTreeView *tree_view,
1474                /* these are in tree window coords */
1475                gint x,
1476                gint y)
1477 {
1478   if (tree_view->priv->prelight_node == NULL)
1479     return;
1480   
1481   GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
1482   
1483   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT) &&
1484       !coords_are_over_arrow (tree_view,
1485                               tree_view->priv->prelight_tree,
1486                               tree_view->priv->prelight_node,
1487                               x,
1488                               y))
1489     /* We need to unprelight the old arrow. */
1490     {
1491       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1492       
1493       gtk_tree_view_draw_arrow (tree_view,
1494                                 tree_view->priv->prelight_tree,
1495                                 tree_view->priv->prelight_node,
1496                                 x,
1497                                 y);  
1498
1499     }
1500   
1501   tree_view->priv->prelight_node = NULL;
1502   tree_view->priv->prelight_tree = NULL;
1503 }
1504
1505 static void
1506 do_prelight (GtkTreeView *tree_view,
1507              GtkRBTree   *tree,
1508              GtkRBNode   *node,
1509              /* these are in tree window coords */
1510              gint         x,
1511              gint         y)
1512 {
1513   if (coords_are_over_arrow (tree_view, tree, node, x, y))
1514     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1515
1516   tree_view->priv->prelight_node = node;
1517   tree_view->priv->prelight_tree = tree;
1518
1519   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
1520 }
1521
1522 static void
1523 ensure_unprelighted (GtkTreeView *tree_view)
1524 {
1525   do_unprelight (tree_view, -1000, -1000); /* coords not possibly over an arrow */
1526 }
1527
1528 static gboolean
1529 gtk_tree_view_motion (GtkWidget      *widget,
1530                       GdkEventMotion *event)
1531 {
1532   GtkTreeView *tree_view;
1533   GtkRBTree *tree;
1534   GtkRBNode *node;
1535   gint new_y;
1536   GtkRBTree *old_prelight_tree;
1537   GtkRBNode *old_prelight_node;
1538   
1539   tree_view = (GtkTreeView *) widget;
1540   
1541   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
1542     {
1543       gint x;
1544       gint new_width;
1545
1546       if (event->is_hint || event->window != widget->window)
1547         gtk_widget_get_pointer (widget, &x, NULL);
1548       else
1549         x = event->x;
1550
1551       new_width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), tree_view->priv->drag_pos, &x);
1552       if (x != tree_view->priv->x_drag)
1553         {
1554           gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), tree_view->priv->drag_pos), new_width);
1555         }
1556
1557       /* FIXME: Do we need to scroll */
1558       _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
1559       return FALSE;
1560     }
1561
1562   /* Sanity check it */
1563   if (event->window != tree_view->priv->bin_window)
1564     return FALSE;
1565
1566   if (tree_view->priv->tree == NULL)
1567     return FALSE;
1568
1569   gtk_tree_view_maybe_begin_dragging_row (tree_view, event);
1570
1571   old_prelight_tree = tree_view->priv->prelight_tree;
1572   old_prelight_node = tree_view->priv->prelight_node;
1573   
1574   do_unprelight (tree_view, event->x, event->y);  
1575   
1576   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1577
1578   _gtk_rbtree_find_offset (tree_view->priv->tree,
1579                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
1580                            &tree,
1581                            &node);
1582
1583   if (tree == NULL)
1584     return TRUE;
1585
1586   /* If we are currently pressing down a button, we don't want to prelight anything else. */
1587   if ((tree_view->priv->button_pressed_node != NULL) &&
1588       (tree_view->priv->button_pressed_node != node))
1589     return TRUE;
1590
1591
1592   do_prelight (tree_view, tree, node, event->x, new_y);
1593
1594   if (old_prelight_node != tree_view->priv->prelight_node)
1595     {
1596       if (old_prelight_node)
1597         gtk_tree_view_queue_draw_node (tree_view,
1598                                        old_prelight_tree,
1599                                        old_prelight_node,
1600                                        NULL);
1601
1602       if (tree_view->priv->prelight_node)
1603         gtk_tree_view_queue_draw_node (tree_view,
1604                                        tree_view->priv->prelight_tree,
1605                                        tree_view->priv->prelight_node,
1606                                        NULL);
1607     }
1608   
1609   return TRUE;
1610 }
1611
1612 /* FIXME Is this function necessary? Can I get an enter_notify event
1613  * w/o either an expose event or a mouse motion event?
1614  */
1615 static gboolean
1616 gtk_tree_view_enter_notify (GtkWidget        *widget,
1617                             GdkEventCrossing *event)
1618 {
1619   GtkTreeView *tree_view;
1620   GtkRBTree *tree;
1621   GtkRBNode *node;
1622   gint new_y;
1623
1624   g_return_val_if_fail (widget != NULL, FALSE);
1625   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1626
1627   tree_view = GTK_TREE_VIEW (widget);
1628
1629   /* Sanity check it */
1630   if (event->window != tree_view->priv->bin_window)
1631     return FALSE;
1632
1633   if (tree_view->priv->tree == NULL)
1634     return FALSE;
1635
1636   if ((tree_view->priv->button_pressed_node != NULL) &&
1637       (tree_view->priv->button_pressed_node != node))
1638     return TRUE;
1639
1640   /* find the node internally */
1641   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1642
1643   _gtk_rbtree_find_offset (tree_view->priv->tree,
1644                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
1645                            &tree,
1646                            &node);
1647   
1648   if (node == NULL)
1649     return FALSE;
1650
1651   do_prelight (tree_view, tree, node, event->x, new_y);
1652
1653   if (tree_view->priv->prelight_node)
1654     gtk_tree_view_queue_draw_node (tree_view,
1655                                    tree_view->priv->prelight_tree,
1656                                    tree_view->priv->prelight_node,
1657                                    NULL);
1658   
1659   return TRUE;
1660 }
1661
1662 static gboolean
1663 gtk_tree_view_leave_notify (GtkWidget        *widget,
1664                             GdkEventCrossing *event)
1665 {
1666   GtkTreeView *tree_view;
1667
1668   g_return_val_if_fail (widget != NULL, FALSE);
1669   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1670
1671   tree_view = GTK_TREE_VIEW (widget);
1672
1673   if (tree_view->priv->prelight_node)
1674     gtk_tree_view_queue_draw_node (tree_view,
1675                                    tree_view->priv->prelight_tree,
1676                                    tree_view->priv->prelight_node,
1677                                    NULL);
1678   
1679   ensure_unprelighted (tree_view);
1680
1681   return TRUE;
1682 }
1683
1684 static gboolean
1685 gtk_tree_view_button_press (GtkWidget      *widget,
1686                             GdkEventButton *event)
1687 {
1688   GtkTreeView *tree_view;
1689   GList *list;
1690   GtkTreeViewColumn *column;
1691   gint i;
1692   GdkRectangle background_area;
1693   GdkRectangle cell_area;
1694
1695   g_return_val_if_fail (widget != NULL, FALSE);
1696   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1697   g_return_val_if_fail (event != NULL, FALSE);
1698
1699   tree_view = GTK_TREE_VIEW (widget);
1700
1701   if (event->window == tree_view->priv->bin_window)
1702     {
1703       GtkRBNode *node;
1704       GtkRBTree *tree;
1705       GtkTreePath *path;
1706       gchar *path_string;
1707       gint depth;
1708       gint new_y;
1709       gint y_offset;
1710
1711       if (!GTK_WIDGET_HAS_FOCUS (widget))
1712         gtk_widget_grab_focus (widget);
1713       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1714
1715       /* are we in an arrow? */
1716       if (tree_view->priv->prelight_node &&
1717           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1718         {
1719           if (event->button == 1)
1720             {
1721               gtk_grab_add (widget);
1722               tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
1723               tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
1724               gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
1725                                         tree_view->priv->prelight_tree,
1726                                         tree_view->priv->prelight_node,
1727                                         event->x,
1728                                         event->y);
1729             }
1730           return TRUE;
1731         }
1732
1733       /* find the node that was clicked */
1734       new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1735       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
1736                                            TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, new_y),
1737                                            &tree,
1738                                            &node) + new_y - (gint)event->y;
1739
1740       if (node == NULL)
1741         /* We clicked in dead space */
1742         return TRUE;
1743
1744       /* Get the path and the node */
1745       path = _gtk_tree_view_find_path (tree_view, tree, node);
1746       depth = gtk_tree_path_get_depth (path);
1747       background_area.y = y_offset + event->y + TREE_VIEW_VERTICAL_SEPARATOR;
1748       background_area.height = GTK_RBNODE_GET_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR;
1749       background_area.x = 0;
1750       /* Let the cell have a chance at selecting it. */
1751
1752       for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
1753         {
1754           GtkTreeViewColumn *column = list->data;
1755           GtkCellRenderer *cell;
1756           GtkTreeIter iter;
1757
1758           if (!column->visible)
1759             continue;
1760
1761           background_area.width = column->displayed_width;
1762           if (i == tree_view->priv->expander_column &&
1763               TREE_VIEW_DRAW_EXPANDERS(tree_view))
1764             {
1765               cell_area = background_area;
1766               cell_area.x += depth*tree_view->priv->tab_offset;
1767               cell_area.width -= depth*tree_view->priv->tab_offset;
1768             }
1769           else
1770             {
1771               cell_area = background_area;
1772             }
1773
1774           cell = column->cell;
1775
1776           if ((background_area.x > (gint) event->x) ||
1777               (background_area.y > (gint) event->y) ||
1778               (background_area.x + background_area.width <= (gint) event->x) ||
1779               (background_area.y + background_area.height <= (gint) event->y))
1780             {
1781               background_area.x += background_area.width;
1782               continue;
1783             }
1784
1785           gtk_tree_model_get_iter (tree_view->priv->model,
1786                                    &iter,
1787                                    path);
1788           gtk_tree_view_column_set_cell_data (column,
1789                                               tree_view->priv->model,
1790                                               &iter);
1791
1792           path_string = gtk_tree_path_to_string (path);
1793           if (gtk_cell_renderer_event (cell,
1794                                        (GdkEvent *)event,
1795                                        widget,
1796                                        path_string,
1797                                        &background_area,
1798                                        &cell_area,
1799                                        0))
1800
1801             {
1802               g_free (path_string);
1803               gtk_tree_path_free (path);
1804               return TRUE;
1805             }
1806           else
1807             {
1808               g_free (path_string);
1809               break;
1810             }
1811         }
1812
1813       /* Save press to possibly begin a drag
1814        */
1815       if (tree_view->priv->pressed_button < 0)
1816         {
1817           tree_view->priv->pressed_button = event->button;
1818           tree_view->priv->press_start_x = event->x;
1819           tree_view->priv->press_start_y = event->y;
1820         }      
1821       
1822       /* Handle the selection */
1823       if (tree_view->priv->selection == NULL)
1824         tree_view->priv->selection =
1825           _gtk_tree_selection_new_with_tree_view (tree_view);
1826
1827       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
1828                                                 node,
1829                                                 tree,
1830                                                 path,
1831                                                 event->state);
1832       gtk_tree_path_free (path);
1833       return TRUE;
1834     }
1835
1836   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
1837     {
1838       column = list->data;
1839       if (event->window == column->window &&
1840           column->column_type == GTK_TREE_VIEW_COLUMN_RESIZEABLE &&
1841           column->window)
1842         {
1843           gpointer drag_data;
1844
1845           if (gdk_pointer_grab (column->window, FALSE,
1846                                 GDK_POINTER_MOTION_HINT_MASK |
1847                                 GDK_BUTTON1_MOTION_MASK |
1848                                 GDK_BUTTON_RELEASE_MASK,
1849                                 NULL, NULL, event->time))
1850             return FALSE;
1851
1852           gtk_grab_add (widget);
1853           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1854
1855           /* block attached dnd signal handler */
1856           drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1857           if (drag_data)
1858             gtk_signal_handler_block_by_data (GTK_OBJECT (widget), drag_data);
1859
1860           if (!GTK_WIDGET_HAS_FOCUS (widget))
1861             gtk_widget_grab_focus (widget);
1862
1863           tree_view->priv->drag_pos = i;
1864           tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
1865         }
1866     }
1867   return TRUE;
1868 }
1869
1870 static gboolean
1871 gtk_tree_view_button_release (GtkWidget      *widget,
1872                               GdkEventButton *event)
1873 {
1874   GtkTreeView *tree_view;
1875
1876   g_return_val_if_fail (widget != NULL, FALSE);
1877   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1878   g_return_val_if_fail (event != NULL, FALSE);
1879
1880   tree_view = GTK_TREE_VIEW (widget);
1881
1882   if (tree_view->priv->pressed_button == event->button)
1883     tree_view->priv->pressed_button = -1;
1884   
1885   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
1886     {
1887       gpointer drag_data;
1888       gint width;
1889       gint x;
1890       gint i;
1891
1892       i = tree_view->priv->drag_pos;
1893       tree_view->priv->drag_pos = -1;
1894
1895       /* unblock attached dnd signal handler */
1896       drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1897       if (drag_data)
1898         gtk_signal_handler_unblock_by_data (GTK_OBJECT (widget), drag_data);
1899
1900       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1901       gtk_widget_get_pointer (widget, &x, NULL);
1902       gtk_grab_remove (widget);
1903       gdk_pointer_ungrab (event->time);
1904
1905       width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), i, &x);
1906       gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i), width);
1907       return FALSE;
1908     }
1909
1910   if (tree_view->priv->button_pressed_node == NULL)
1911     return FALSE;
1912
1913   if (event->button == 1)
1914     {
1915       gtk_grab_remove (widget);
1916       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node &&
1917           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1918         {
1919           GtkTreePath *path;
1920           GtkTreeIter iter;
1921
1922           /* Actually activate the node */
1923           if (tree_view->priv->button_pressed_node->children == NULL)
1924             {
1925               GtkTreeIter child;
1926               path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
1927                                                tree_view->priv->button_pressed_tree,
1928                                                tree_view->priv->button_pressed_node);
1929               tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
1930               tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
1931               tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
1932               gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
1933               
1934               if (gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter))
1935                 gtk_tree_view_build_tree (tree_view,
1936                                           tree_view->priv->button_pressed_node->children,
1937                                           &child,
1938                                           gtk_tree_path_get_depth (path) + 1,
1939                                           FALSE,
1940                                           GTK_WIDGET_REALIZED (widget));
1941             }
1942           else
1943             {
1944               path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
1945                                                tree_view->priv->button_pressed_node->children,
1946                                                tree_view->priv->button_pressed_node->children->root);
1947               gtk_tree_model_get_iter (tree_view->priv->model,
1948                                        &iter,
1949                                        path);
1950
1951               gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
1952                                             tree_view->priv->button_pressed_node->children,
1953                                             &iter,
1954                                             gtk_tree_path_get_depth (path));
1955               _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
1956             }
1957           gtk_tree_path_free (path);
1958
1959           _gtk_tree_view_update_size (GTK_TREE_VIEW (widget));
1960         }
1961
1962       tree_view->priv->button_pressed_node = NULL;
1963     }
1964
1965   return TRUE;
1966 }
1967
1968
1969 static void
1970 gtk_tree_view_draw_focus (GtkWidget *widget)
1971 {
1972   GtkTreeView *tree_view;
1973   GtkTreePath *cursor_path;
1974   
1975   g_return_if_fail (widget != NULL);
1976   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1977
1978   tree_view = GTK_TREE_VIEW (widget);
1979
1980   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
1981     return;
1982
1983   if (tree_view->priv->cursor == NULL)
1984     return;
1985
1986   cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
1987   if (cursor_path == NULL)
1988     return;
1989   
1990   gtk_tree_view_draw_node_focus_rect (widget, cursor_path);
1991 }
1992
1993
1994 static gint
1995 gtk_tree_view_focus_in (GtkWidget     *widget,
1996                         GdkEventFocus *event)
1997 {
1998   GtkTreeView *tree_view;
1999
2000   g_return_val_if_fail (widget != NULL, FALSE);
2001   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2002   g_return_val_if_fail (event != NULL, FALSE);
2003
2004   tree_view = GTK_TREE_VIEW (widget);
2005
2006   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2007
2008   /* FIXME don't redraw so much */
2009   gtk_widget_queue_draw (widget);
2010
2011   return FALSE;
2012 }
2013
2014
2015 static gint
2016 gtk_tree_view_focus_out (GtkWidget     *widget,
2017                          GdkEventFocus *event)
2018 {
2019   g_return_val_if_fail (widget != NULL, FALSE);
2020   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
2021   g_return_val_if_fail (event != NULL, FALSE);
2022
2023   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2024
2025   /* FIXME don't redraw so much */
2026   gtk_widget_queue_draw (widget);
2027
2028   return FALSE;
2029 }
2030
2031 /* FIXME: It would be neat to someday make the headers a seperate widget that
2032  * can be shared between various apps.  Wishful thinking, though...
2033  */
2034 /* Returns TRUE if the focus is within the headers, after the focus operation is
2035  * done
2036  */
2037 static gboolean
2038 gtk_tree_view_header_focus (GtkTreeView        *tree_view,
2039                             GtkDirectionType  dir)
2040 {
2041   GtkWidget *focus_child;
2042   GtkContainer *container;
2043
2044   GList *last_column, *first_column;
2045   GList *tmp_list;
2046
2047   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
2048     return FALSE;
2049
2050   focus_child = GTK_CONTAINER (tree_view)->focus_child;
2051   container = GTK_CONTAINER (tree_view);
2052
2053   for (last_column = g_list_last (tree_view->priv->columns);
2054        last_column &&
2055          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
2056          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
2057        last_column = last_column->prev)
2058     ;
2059
2060   for (first_column = tree_view->priv->columns;
2061        first_column &&
2062          !(GTK_TREE_VIEW_COLUMN (first_column->data)->visible) &&
2063          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button);
2064        first_column = first_column->next)
2065     ;
2066
2067   /* no headers are visible, or are focussable.  We can't focus in or out.
2068    * I wonder if focussable is a real word...
2069    */
2070   if (last_column == NULL)
2071     return FALSE;
2072
2073   /* First thing we want to handle is entering and leaving the headers.
2074    */
2075   switch (dir)
2076     {
2077     case GTK_DIR_TAB_BACKWARD:
2078       if (!focus_child)
2079         {
2080           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
2081           gtk_widget_grab_focus (focus_child);
2082           goto cleanup;
2083         }
2084       if (focus_child == GTK_TREE_VIEW_COLUMN (first_column->data)->button)
2085         {
2086           focus_child = NULL;
2087           goto cleanup;
2088         }
2089       break;
2090
2091     case GTK_DIR_TAB_FORWARD:
2092       if (!focus_child)
2093         {
2094           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
2095           gtk_widget_grab_focus (focus_child);
2096           goto cleanup;
2097         }
2098       if (focus_child == GTK_TREE_VIEW_COLUMN (last_column->data)->button)
2099         {
2100           focus_child = NULL;
2101           goto cleanup;
2102         }
2103       break;
2104
2105     case GTK_DIR_LEFT:
2106       if (!focus_child)
2107         {
2108           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
2109           gtk_widget_grab_focus (focus_child);
2110           goto cleanup;
2111         }
2112       if (focus_child == GTK_TREE_VIEW_COLUMN (first_column->data)->button)
2113         {
2114           focus_child = NULL;
2115           goto cleanup;
2116         }
2117       break;
2118
2119     case GTK_DIR_RIGHT:
2120       if (!focus_child)
2121         {
2122           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
2123           gtk_widget_grab_focus (focus_child);
2124           goto cleanup;
2125         }
2126       if (focus_child == GTK_TREE_VIEW_COLUMN (last_column->data)->button)
2127         {
2128           focus_child = NULL;
2129           goto cleanup;
2130         }
2131       break;
2132
2133     case GTK_DIR_UP:
2134       if (!focus_child)
2135         {
2136           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
2137           gtk_widget_grab_focus (focus_child);
2138         }
2139       else
2140         {
2141           focus_child = NULL;
2142         }
2143       goto cleanup;
2144
2145     case GTK_DIR_DOWN:
2146       if (!focus_child)
2147         {
2148           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
2149           gtk_widget_grab_focus (focus_child);
2150         }
2151       else
2152         {
2153           focus_child = NULL;
2154         }
2155       goto cleanup;
2156     }
2157
2158   /* We need to move the focus to the next button. */
2159   if (focus_child)
2160     {
2161       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
2162         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
2163           {
2164             if (gtk_container_focus (GTK_CONTAINER (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button), dir))
2165               {
2166                 /* The focus moves inside the button. */
2167                 /* This is probably a great example of bad UI */
2168                 goto cleanup;
2169               }
2170             break;
2171           }
2172
2173       /* We need to move the focus among the row of buttons. */
2174       while (tmp_list)
2175         {
2176           GtkTreeViewColumn *column;
2177
2178           if (dir == GTK_DIR_RIGHT || dir == GTK_DIR_TAB_FORWARD)
2179             tmp_list = tmp_list->next;
2180           else
2181             tmp_list = tmp_list->prev;
2182
2183           if (tmp_list == NULL)
2184             {
2185               g_warning ("Internal button not found");
2186               goto cleanup;
2187             }
2188           column = tmp_list->data;
2189           if (column->button &&
2190               column->visible &&
2191               GTK_WIDGET_CAN_FOCUS (column->button))
2192             {
2193               focus_child = column->button;
2194               gtk_widget_grab_focus (column->button);
2195               break;
2196             }
2197         }
2198     }
2199
2200  cleanup:
2201   /* if focus child is non-null, we assume it's been set to the current focus child
2202    */
2203   if (focus_child)
2204     {
2205       /* If the following isn't true, then the view is smaller then the scrollpane.
2206        */
2207       if ((focus_child->allocation.x + focus_child->allocation.width) <=
2208           (tree_view->priv->hadjustment->upper))
2209         {
2210           /* Scroll to the button, if needed */
2211           if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
2212               (focus_child->allocation.x + focus_child->allocation.width))
2213             gtk_adjustment_set_value (tree_view->priv->hadjustment,
2214                                       focus_child->allocation.x + focus_child->allocation.width -
2215                                       tree_view->priv->hadjustment->page_size);
2216           else if (tree_view->priv->hadjustment->value > focus_child->allocation.x)
2217             gtk_adjustment_set_value (tree_view->priv->hadjustment,
2218                                       focus_child->allocation.x);
2219         }
2220     }
2221
2222   return (focus_child != NULL);
2223 }
2224
2225 /* WARNING: Scary function */
2226 static gint
2227 gtk_tree_view_focus (GtkContainer     *container,
2228                      GtkDirectionType  direction)
2229 {
2230   GtkTreeView *tree_view;
2231   GtkWidget *focus_child;
2232   GdkEvent *event;
2233   GtkRBTree *cursor_tree;
2234   GtkRBNode *cursor_node;
2235   GtkTreePath *cursor_path;
2236   
2237   g_return_val_if_fail (container != NULL, FALSE);
2238   g_return_val_if_fail (GTK_IS_TREE_VIEW (container), FALSE);
2239   g_return_val_if_fail (GTK_WIDGET_VISIBLE (container), FALSE);
2240
2241   tree_view = GTK_TREE_VIEW (container);
2242
2243   if (!GTK_WIDGET_IS_SENSITIVE (container))
2244     return FALSE;
2245   if (tree_view->priv->tree == NULL)
2246     return FALSE;
2247
2248   focus_child = container->focus_child;
2249
2250   /* Case 1.  Headers have focus. */
2251   if (focus_child)
2252     {
2253       switch (direction)
2254         {
2255         case GTK_DIR_LEFT:
2256         case GTK_DIR_TAB_BACKWARD:
2257           return (gtk_tree_view_header_focus (tree_view, direction));
2258         case GTK_DIR_UP:
2259           return FALSE;
2260         case GTK_DIR_TAB_FORWARD:
2261         case GTK_DIR_RIGHT:
2262         case GTK_DIR_DOWN:
2263           if (direction != GTK_DIR_DOWN)
2264             {
2265               if (gtk_tree_view_header_focus (tree_view, direction))
2266                 return TRUE;
2267             }
2268           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
2269           gtk_widget_grab_focus (GTK_WIDGET (container));
2270
2271           if (tree_view->priv->selection == NULL)
2272             tree_view->priv->selection =
2273               _gtk_tree_selection_new_with_tree_view (tree_view);
2274
2275           /* if there is no keyboard focus yet, we select the first node
2276            */
2277
2278           cursor_path = NULL;
2279
2280           if (tree_view->priv->cursor)
2281             cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2282           
2283           if (cursor_path == NULL)
2284             {
2285               GtkTreePath *tmp_path = gtk_tree_path_new_root ();
2286
2287               if (tree_view->priv->cursor)
2288                 gtk_tree_row_reference_free (tree_view->priv->cursor);
2289               
2290               tree_view->priv->cursor =
2291                 gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path);
2292               cursor_path = tmp_path;
2293             }
2294           
2295           gtk_tree_selection_select_path (tree_view->priv->selection,
2296                                           cursor_path);
2297
2298           gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);          
2299
2300           gtk_tree_path_free (cursor_path);
2301           
2302           return TRUE;
2303         }
2304     }
2305
2306   /* Case 2. We don't have focus at all. */
2307   if (!GTK_WIDGET_HAS_FOCUS (container))
2308     {
2309       if ((direction == GTK_DIR_TAB_FORWARD) ||
2310           (direction == GTK_DIR_RIGHT) ||
2311           (direction == GTK_DIR_DOWN))
2312         {
2313           if (gtk_tree_view_header_focus (tree_view, direction))
2314             return TRUE;
2315         }
2316
2317       /* The headers didn't want the focus, so we take it. */
2318       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
2319       gtk_widget_grab_focus (GTK_WIDGET (container));
2320
2321       if (tree_view->priv->selection == NULL)
2322         tree_view->priv->selection =
2323           _gtk_tree_selection_new_with_tree_view (tree_view);
2324
2325       cursor_path = NULL;
2326       if (tree_view->priv->cursor)
2327         cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2328       
2329       if (cursor_path == NULL)
2330         {
2331           GtkTreePath *tmp_path = gtk_tree_path_new_root ();
2332           
2333           if (tree_view->priv->cursor)
2334             gtk_tree_row_reference_free (tree_view->priv->cursor);
2335           
2336           tree_view->priv->cursor =
2337             gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path);
2338           cursor_path = tmp_path;
2339         }        
2340
2341       gtk_tree_selection_select_path (tree_view->priv->selection,
2342                                       cursor_path);
2343
2344       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
2345
2346       gtk_tree_path_free (cursor_path);      
2347
2348       return TRUE;
2349     }
2350
2351   cursor_path = NULL;
2352   if (tree_view->priv->cursor)
2353     cursor_path = gtk_tree_row_reference_get_path (tree_view->priv->cursor);
2354
2355   /* Case 3. We have focus already, but no cursor.  We pick the first one
2356    * and run with it.
2357    */
2358   
2359   if (cursor_path == NULL)
2360     {
2361       GtkTreePath *tmp_path = gtk_tree_path_new_root ();
2362       
2363       if (tree_view->priv->cursor)
2364         gtk_tree_row_reference_free (tree_view->priv->cursor);
2365       
2366       tree_view->priv->cursor =
2367         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, tmp_path);
2368       cursor_path = tmp_path;
2369       
2370       gtk_tree_selection_select_path (tree_view->priv->selection,
2371                                       cursor_path);
2372       
2373       gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
2374       
2375       gtk_tree_path_free (cursor_path);      
2376       
2377       return TRUE;
2378     }
2379
2380   /* Case 4. We have focus already.  Move the cursor. */
2381   if (direction == GTK_DIR_LEFT)
2382     {
2383       gfloat val;
2384       val = tree_view->priv->hadjustment->value - tree_view->priv->hadjustment->page_size/2;
2385       val = MAX (val, 0.0);
2386       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
2387       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
2388
2389       gtk_tree_path_free (cursor_path);
2390       
2391       return TRUE;
2392     }
2393   if (direction == GTK_DIR_RIGHT)
2394     {
2395       gfloat val;
2396       val = tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size/2;
2397       val = MIN (tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size, val);
2398       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
2399       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
2400
2401       gtk_tree_path_free (cursor_path);
2402       
2403       return TRUE;
2404     }
2405
2406   cursor_tree = NULL;
2407   cursor_node = NULL;
2408
2409   _gtk_tree_view_find_node (tree_view, cursor_path,
2410                             &cursor_tree,
2411                             &cursor_node);
2412
2413   /* undraw the old row */
2414   gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
2415   
2416   gtk_tree_path_free (cursor_path);
2417   cursor_path = NULL;
2418
2419   if (tree_view->priv->cursor)
2420     {
2421       gtk_tree_row_reference_free (tree_view->priv->cursor);
2422       tree_view->priv->cursor = NULL;
2423     }
2424   
2425   switch (direction)
2426     {
2427     case GTK_DIR_TAB_BACKWARD:
2428     case GTK_DIR_UP:
2429       _gtk_rbtree_prev_full (cursor_tree,
2430                              cursor_node,
2431                              &cursor_tree,
2432                              &cursor_node);
2433       break;
2434     case GTK_DIR_TAB_FORWARD:
2435     case GTK_DIR_DOWN:
2436       _gtk_rbtree_next_full (cursor_tree,
2437                              cursor_node,
2438                              &cursor_tree,
2439                              &cursor_node);
2440       break;
2441     default:
2442       break;
2443     }
2444
2445   if (cursor_node)
2446     {
2447       GdkModifierType state = 0;
2448
2449       event = gtk_get_current_event ();
2450       if (event)
2451         gdk_event_get_state (event, &state);
2452
2453       if (event)
2454         gdk_event_free (event);
2455       
2456       cursor_path = _gtk_tree_view_find_path (tree_view,
2457                                               cursor_tree,
2458                                               cursor_node);
2459
2460       if (cursor_path)
2461         {
2462           _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
2463                                                     cursor_node,
2464                                                     cursor_tree,
2465                                                     cursor_path,
2466                                                     state);
2467
2468           tree_view->priv->cursor = gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, cursor_path);
2469
2470
2471           /* draw the newly-selected row */
2472           gtk_tree_view_queue_draw_path (tree_view, cursor_path, NULL);
2473           
2474           gtk_tree_path_free (cursor_path);
2475         }
2476           
2477       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
2478       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
2479
2480       return TRUE;
2481     }
2482
2483   /* At this point, we've progressed beyond the edge of the rows. */
2484
2485   if ((direction == GTK_DIR_LEFT) ||
2486       (direction == GTK_DIR_TAB_BACKWARD) ||
2487       (direction == GTK_DIR_UP))
2488     /* We can't go back anymore.  Try the headers */
2489     return (gtk_tree_view_header_focus (tree_view, direction));
2490
2491   /* we've reached the end of the tree.  Go on. */
2492   return FALSE;
2493 }
2494
2495 /* Container method
2496  */
2497 static void
2498 gtk_tree_view_remove (GtkContainer *container,
2499                       GtkWidget    *widget)
2500 {
2501   GtkTreeView *tree_view;
2502   GtkTreeViewChild *child = NULL;
2503   GList *tmp_list;
2504
2505   g_return_if_fail (container != NULL);
2506   g_return_if_fail (GTK_IS_TREE_VIEW (container));
2507
2508   tree_view = GTK_TREE_VIEW (container);
2509
2510   tmp_list = tree_view->priv->children;
2511   while (tmp_list)
2512     {
2513       child = tmp_list->data;
2514       if (child->widget == widget)
2515         {
2516           gtk_widget_unparent (widget);
2517
2518           tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
2519           g_list_free_1 (tmp_list);
2520           g_free (child);
2521           return;
2522         }
2523
2524       tmp_list = tmp_list->next;
2525     }
2526
2527   tmp_list = tree_view->priv->columns;
2528
2529   while (tmp_list)
2530     {
2531       GtkTreeViewColumn *column;
2532       column = tmp_list->data;      
2533       if (column->button == widget)
2534         {
2535           gtk_widget_unparent (widget);
2536           return;
2537         }
2538       tmp_list = tmp_list->next;
2539     }
2540
2541 }
2542
2543 static void
2544 gtk_tree_view_forall (GtkContainer *container,
2545                       gboolean      include_internals,
2546                       GtkCallback   callback,
2547                       gpointer      callback_data)
2548 {
2549   GtkTreeView *tree_view;
2550   GtkTreeViewChild *child = NULL;
2551   GtkTreeViewColumn *column;
2552   GList *tmp_list;
2553
2554   g_return_if_fail (container != NULL);
2555   g_return_if_fail (GTK_IS_TREE_VIEW (container));
2556   g_return_if_fail (callback != NULL);
2557
2558   tree_view = GTK_TREE_VIEW (container);
2559
2560   tmp_list = tree_view->priv->children;
2561   while (tmp_list)
2562     {
2563       child = tmp_list->data;
2564       tmp_list = tmp_list->next;
2565
2566       (* callback) (child->widget, callback_data);
2567     }
2568   if (include_internals == FALSE)
2569     return;
2570
2571   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
2572     {
2573       column = tmp_list->data;      
2574       
2575       if (column->button)
2576         (* callback) (column->button, callback_data);
2577     }
2578 }
2579
2580 /* TreeModel Callbacks
2581  */
2582
2583 static void
2584 gtk_tree_view_changed (GtkTreeModel *model,
2585                        GtkTreePath  *path,
2586                        GtkTreeIter  *iter,
2587                        gpointer      data)
2588 {
2589   GtkTreeView *tree_view = (GtkTreeView *)data;
2590   GtkRBTree *tree;
2591   GtkRBNode *node;
2592   gint height;
2593   gboolean dirty_marked;
2594   gboolean free_path = FALSE;
2595
2596   g_return_if_fail (path != NULL || iter != NULL);
2597
2598   if (path == NULL)
2599     {
2600       path = gtk_tree_model_get_path (model, iter);
2601       free_path = TRUE;
2602     }
2603   else if (iter == NULL)
2604     gtk_tree_model_get_iter (model, iter, path);
2605
2606   if (_gtk_tree_view_find_node (tree_view,
2607                                 path,
2608                                 &tree,
2609                                 &node))
2610     /* We aren't actually showing the node */
2611     goto done;
2612
2613   if (tree == NULL)
2614     goto done;
2615   
2616   dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view,
2617                                                     iter,
2618                                                     gtk_tree_path_get_depth (path),
2619                                                     &height);
2620
2621   if (GTK_RBNODE_GET_HEIGHT (node) != height + TREE_VIEW_VERTICAL_SEPARATOR)
2622     {
2623       _gtk_rbtree_node_set_height (tree, node, height + TREE_VIEW_VERTICAL_SEPARATOR);
2624       gtk_widget_queue_resize (GTK_WIDGET (data));
2625       goto done;
2626     }
2627   if (dirty_marked)
2628     gtk_widget_queue_resize (GTK_WIDGET (data));
2629   else
2630     {
2631       gtk_tree_view_queue_draw_node (tree_view, tree, node, NULL);
2632     }
2633
2634  done:
2635   if (free_path)
2636     gtk_tree_path_free (path);
2637 }
2638
2639 static void
2640 gtk_tree_view_inserted (GtkTreeModel *model,
2641                         GtkTreePath  *path,
2642                         GtkTreeIter  *iter,
2643                         gpointer      data)
2644 {
2645   GtkTreeView *tree_view = (GtkTreeView *) data;
2646   gint *indices;
2647   GtkRBTree *tmptree, *tree;
2648   GtkRBNode *tmpnode = NULL;
2649   gint max_height;
2650   gint depth;
2651   gint i = 0;
2652   gboolean free_path = FALSE;
2653
2654   tmptree = tree = tree_view->priv->tree;
2655   g_return_if_fail (path != NULL || iter != NULL);
2656
2657   if (path == NULL)
2658     {
2659       path = gtk_tree_model_get_path (model, iter);
2660       free_path = TRUE;
2661     }
2662   else if (iter == NULL)
2663     gtk_tree_model_get_iter (model, iter, path);
2664   
2665   /* Update all row-references */
2666   gtk_tree_row_reference_inserted (G_OBJECT (data), path);
2667
2668   depth = gtk_tree_path_get_depth (path);
2669   indices = gtk_tree_path_get_indices (path);
2670
2671   /* First, find the parent tree */
2672   while (i < depth - 1)
2673     {
2674       if (tmptree == NULL)
2675         {
2676           /* We aren't showing the node */
2677           goto done;
2678         }
2679
2680       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
2681       if (tmpnode == NULL)
2682         {
2683           g_warning ("A node was inserted with a parent that's not in the tree.\n" \
2684                      "This possibly means that a GtkTreeModel inserted a child node\n" \
2685                      "before the parent was inserted.");
2686           goto done;
2687         }
2688       else if (!GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_IS_PARENT))
2689         {
2690           /* FIXME enforce correct behavior on model, probably */
2691           /* In theory, the model should have emitted has_child_toggled here.  We
2692            * try to catch it anyway, just to be safe, in case the model hasn't.
2693            */
2694           GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
2695                                                            tree,
2696                                                            tmpnode);
2697           gtk_tree_view_has_child_toggled (model, tmppath, NULL, data);
2698           gtk_tree_path_free (tmppath);
2699           goto done;
2700         }
2701
2702       tmptree = tmpnode->children;
2703       tree = tmptree;
2704       i++;
2705     }
2706
2707   if (tree == NULL)
2708     goto done;
2709
2710   /* ref the node */
2711   gtk_tree_model_ref_iter (tree_view->priv->model, iter);
2712   max_height = gtk_tree_view_insert_iter_height (tree_view,
2713                                                  tree,
2714                                                  iter,
2715                                                  depth);
2716   if (indices[depth - 1] == 0)
2717     {
2718       tmpnode = _gtk_rbtree_find_count (tree, 1);
2719       _gtk_rbtree_insert_before (tree, tmpnode, max_height);
2720     }
2721   else
2722     {
2723       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
2724       _gtk_rbtree_insert_after (tree, tmpnode, max_height);
2725     }
2726
2727   _gtk_tree_view_update_size (tree_view);
2728
2729  done:
2730   if (free_path)
2731     gtk_tree_path_free (path);
2732 }
2733
2734 static void
2735 gtk_tree_view_has_child_toggled (GtkTreeModel *model,
2736                                  GtkTreePath  *path,
2737                                  GtkTreeIter  *iter,
2738                                  gpointer      data)
2739 {
2740   GtkTreeView *tree_view = (GtkTreeView *)data;
2741   GtkTreeIter real_iter;
2742   gboolean has_child;
2743   GtkRBTree *tree;
2744   GtkRBNode *node;
2745   gboolean free_path = FALSE;
2746
2747   g_return_if_fail (path != NULL || iter != NULL);
2748
2749   if (iter)
2750     real_iter = *iter;
2751
2752   if (path == NULL)
2753     {
2754       path = gtk_tree_model_get_path (model, iter);
2755       free_path = TRUE;
2756     }
2757   else if (iter == NULL)
2758     gtk_tree_model_get_iter (model, &real_iter, path);
2759
2760   if (_gtk_tree_view_find_node (tree_view,
2761                                 path,
2762                                 &tree,
2763                                 &node))
2764     /* We aren't actually showing the node */
2765     goto done;
2766
2767   if (tree == NULL)
2768     goto done;
2769   
2770   has_child = gtk_tree_model_iter_has_child (model, &real_iter);
2771   /* Sanity check.
2772    */
2773   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT) == has_child)
2774     goto done;
2775
2776   if (has_child)
2777     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PARENT);
2778   else
2779     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_PARENT);
2780
2781   if (has_child && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
2782     {
2783       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
2784       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
2785         {
2786           GList *list;
2787           for (list = tree_view->priv->columns; list; list = list->next)
2788             if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
2789               {
2790                 GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
2791                 break;
2792               }
2793         }
2794       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
2795     }
2796   else
2797     {
2798       /* FIXME: Just redraw the node */
2799       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2800     }
2801
2802  done:
2803   if (free_path)
2804     gtk_tree_path_free (path);
2805 }
2806
2807 static void
2808 gtk_tree_view_deleted (GtkTreeModel *model,
2809                        GtkTreePath  *path,
2810                        gpointer      data)
2811 {
2812   GtkTreeView *tree_view = (GtkTreeView *)data;
2813   GtkRBTree *tree;
2814   GtkRBNode *node;
2815   GList *list;
2816   
2817   g_return_if_fail (path != NULL);
2818
2819   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
2820     return;
2821
2822   if (tree == NULL)
2823     return;
2824
2825   gtk_tree_row_reference_deleted (G_OBJECT (data), path);
2826
2827   /* next, update the selection */
2828   if (tree_view->priv->anchor)
2829     {
2830       GtkTreePath *anchor_path;
2831
2832       /* the row reference may not have been updated yet. If it has not,
2833        * then anchor_path and path being equal indicates that the anchor
2834        * row was deleted. If it has, then anchor_path == NULL indicates the
2835        * the anchor row was deleted.
2836        */
2837       
2838       anchor_path = gtk_tree_row_reference_get_path (tree_view->priv->anchor);
2839
2840       if (anchor_path == NULL ||
2841           gtk_tree_path_compare (path, anchor_path) == 0)
2842         {
2843           if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) &&
2844               tree_view->priv->selection)
2845             gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->selection),
2846                                      "selection_changed");
2847         }
2848
2849       if (anchor_path)
2850         gtk_tree_path_free (anchor_path);
2851     }
2852
2853   for (list = tree_view->priv->columns; list; list = list->next)
2854     if (((GtkTreeViewColumn *)list->data)->visible &&
2855         ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2856       ((GtkTreeViewColumn *)list->data)->dirty = TRUE;
2857
2858   /* Ensure we don't have a dangling pointer to a dead node */
2859   ensure_unprelighted (tree_view);
2860
2861   g_assert (tree_view->priv->prelight_node == NULL);
2862   
2863   if ((tree->root->count == 1) &&
2864       (tree_view->priv->tree != tree))
2865     {
2866       _gtk_rbtree_remove (tree);
2867     }
2868   else
2869     {      
2870       _gtk_rbtree_remove_node (tree, node);
2871     }
2872   
2873   _gtk_tree_view_update_size (GTK_TREE_VIEW (data));
2874 }
2875
2876 /* Internal tree functions */
2877 static gint
2878 gtk_tree_view_insert_iter_height (GtkTreeView *tree_view,
2879                                   GtkRBTree   *tree,
2880                                   GtkTreeIter *iter,
2881                                   gint         depth)
2882 {
2883   GtkTreeViewColumn *column;
2884   GtkCellRenderer *cell;
2885   GList *list;
2886   gint max_height = 0;
2887   gint i;
2888
2889   i = 0;
2890   
2891   /* do stuff with node */
2892   for (list = tree_view->priv->columns; list; list = list->next)
2893     {
2894       gint height = 0, width = 0;
2895       column = list->data;
2896
2897       if (!column->visible)
2898         continue;
2899
2900       if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2901         {
2902           ++i;
2903           continue;
2904         }
2905
2906       cell = column->cell;
2907       gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
2908
2909       gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &height);
2910       max_height = MAX (max_height, TREE_VIEW_VERTICAL_SEPARATOR + height);
2911
2912       if (i == tree_view->priv->expander_column &&
2913           TREE_VIEW_DRAW_EXPANDERS (tree_view))
2914         gtk_tree_view_column_set_width (column,
2915                                         MAX (column->width, depth * tree_view->priv->tab_offset + width));
2916       else
2917         gtk_tree_view_column_set_width (column,
2918                                         MAX (column->width, width));
2919
2920       ++i;
2921     }
2922   return max_height;
2923 }
2924
2925 static void
2926 gtk_tree_view_build_tree (GtkTreeView *tree_view,
2927                           GtkRBTree   *tree,
2928                           GtkTreeIter *iter,
2929                           gint         depth,
2930                           gboolean     recurse,
2931                           gboolean     calc_bounds)
2932 {
2933   GtkRBNode *temp = NULL;
2934   gint max_height;
2935
2936   do
2937     {
2938       max_height = 0;
2939       if (calc_bounds)
2940         max_height = gtk_tree_view_insert_iter_height (tree_view,
2941                                                        tree,
2942                                                        iter,
2943                                                        depth);
2944
2945       gtk_tree_model_ref_iter (tree_view->priv->model, iter);
2946       temp = _gtk_rbtree_insert_after (tree, temp, max_height);
2947       if (recurse)
2948         {
2949           GtkTreeIter child;
2950
2951           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
2952             {
2953               temp->children = _gtk_rbtree_new ();
2954               temp->children->parent_tree = tree;
2955               temp->children->parent_node = temp;
2956               gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse, calc_bounds);
2957             }
2958         }
2959       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
2960         {
2961           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
2962             temp->flags ^= GTK_RBNODE_IS_PARENT;
2963           GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
2964         }
2965     }
2966   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
2967 }
2968
2969 static void
2970 gtk_tree_view_calc_size (GtkTreeView *tree_view,
2971                          GtkRBTree   *tree,
2972                          GtkTreeIter *iter,
2973                          gint         depth)
2974 {
2975   GtkRBNode *temp;
2976   GtkTreeIter child;
2977   GtkCellRenderer *cell;
2978   GList *list;
2979   GtkTreeViewColumn *column;
2980   gint max_height;
2981   gint i;
2982
2983   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
2984
2985   temp = tree->root;
2986   while (temp->left != tree->nil)
2987     temp = temp->left;
2988
2989   do
2990     {
2991       max_height = 0;
2992       /* Do stuff with node */
2993       for (list = tree_view->priv->columns, i = 0; i < tree_view->priv->n_columns; list = list->next, i++)
2994         {
2995           gint height = 0, width = 0;
2996           column = list->data;
2997
2998           if (!column->visible)
2999             continue;
3000
3001           gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
3002           cell = column->cell;
3003           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &height);
3004           max_height = MAX (max_height, TREE_VIEW_VERTICAL_SEPARATOR + height);
3005
3006           /* FIXME: I'm getting the width of all nodes here. )-: */
3007           if (column->dirty == FALSE)
3008             continue;
3009
3010           if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
3011             {
3012               continue;
3013             }
3014           if (i == tree_view->priv->expander_column &&
3015               TREE_VIEW_DRAW_EXPANDERS (tree_view))
3016             gtk_tree_view_column_set_width (column,
3017                                             MAX (column->width, depth * tree_view->priv->tab_offset + width));
3018           else
3019             gtk_tree_view_column_set_width (column, MAX (column->width, width));
3020         }
3021       _gtk_rbtree_node_set_height (tree, temp, max_height);
3022       if (temp->children != NULL &&
3023           gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
3024         gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
3025       temp = _gtk_rbtree_next (tree, temp);
3026     }
3027   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
3028 }
3029
3030 static gboolean
3031 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
3032                                    GtkTreeIter *iter,
3033                                    gint         depth,
3034                                    gint        *height)
3035 {
3036   GtkCellRenderer *cell;
3037   GtkTreeViewColumn *column;
3038   GList *list;
3039   gint i;
3040   gint retval = FALSE;
3041   gint tmpheight;
3042
3043   if (height)
3044     *height = 0;
3045
3046   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
3047     {
3048       gint width;
3049       column = list->data;
3050       if (column->dirty == TRUE || column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
3051         continue;
3052       if (!column->visible)
3053         continue;
3054
3055       cell = column->cell;
3056       gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
3057
3058       if (height)
3059         {
3060           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &tmpheight);
3061           *height = MAX (*height, tmpheight);
3062         }
3063       else
3064         {
3065           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, NULL);
3066         }
3067       if (i == tree_view->priv->expander_column &&
3068           TREE_VIEW_DRAW_EXPANDERS (tree_view))
3069         {
3070           if (depth * tree_view->priv->tab_offset + width > column->width)
3071             {
3072               column->dirty = TRUE;
3073               retval = TRUE;
3074             }
3075         }
3076       else
3077         {
3078           if (width > column->width)
3079             {
3080               column->dirty = TRUE;
3081               retval = TRUE;
3082             }
3083         }
3084     }
3085
3086   return retval;
3087 }
3088
3089 static void
3090 gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
3091                               GtkRBTree   *tree,
3092                               GtkTreeIter *iter,
3093                               gint         depth)
3094 {
3095   GtkRBNode *temp = tree->root;
3096   GtkTreeViewColumn *column;
3097   GList *list;
3098   GtkTreeIter child;
3099   gboolean is_all_dirty;
3100
3101   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
3102
3103   while (temp->left != tree->nil)
3104     temp = temp->left;
3105
3106   do
3107     {
3108       is_all_dirty = TRUE;
3109       for (list = tree_view->priv->columns; list; list = list->next)
3110         {
3111           column = list->data;
3112           if (column->dirty == FALSE)
3113             {
3114               is_all_dirty = FALSE;
3115               break;
3116             }
3117         }
3118
3119       if (is_all_dirty)
3120         return;
3121
3122       gtk_tree_view_discover_dirty_iter (tree_view,
3123                                          iter,
3124                                          depth,
3125                                          FALSE);
3126       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
3127           temp->children != NULL)
3128         gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
3129       temp = _gtk_rbtree_next (tree, temp);
3130     }
3131   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
3132 }
3133
3134
3135 static void
3136 gtk_tree_view_check_dirty (GtkTreeView *tree_view)
3137 {
3138   GtkTreePath *path;
3139   gboolean dirty = FALSE;
3140   GList *list;
3141   GtkTreeViewColumn *column;
3142   GtkTreeIter iter;
3143   
3144   if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) &&
3145       tree_view->priv->model)
3146     gtk_tree_view_setup_model (tree_view);
3147   
3148   for (list = tree_view->priv->columns; list; list = list->next)
3149     {
3150       column = list->data;
3151       if (column->dirty)
3152         {
3153           dirty = TRUE;
3154           if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
3155             {
3156               gint w = 1;
3157
3158               if (column->button)
3159                 w = MAX (w, column->button->requisition.width);
3160               
3161               gtk_tree_view_column_set_width (column, w);
3162             }
3163         }
3164     }
3165
3166   if (dirty == FALSE)
3167     return;
3168
3169   if (tree_view->priv->model == NULL)
3170     return;
3171   
3172   path = gtk_tree_path_new_root ();
3173   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
3174     {
3175       gtk_tree_view_calc_size (tree_view, tree_view->priv->tree, &iter, 1);
3176       _gtk_tree_view_update_size (tree_view);
3177     }
3178       
3179   gtk_tree_path_free (path);
3180   
3181   for (list = tree_view->priv->columns; list; list = list->next)
3182     {
3183       column = list->data;
3184       column->dirty = FALSE;
3185     }
3186 }
3187 #if 0
3188 static void
3189 gtk_tree_view_create_buttons (GtkTreeView *tree_view)
3190 {
3191   GtkWidget *alignment;
3192   GtkWidget *label;
3193   GList *list;
3194   GtkTreeViewColumn *column;
3195   gint i;
3196   GtkWidget *hbox;
3197   GtkWidget *arrow;
3198
3199   /* FIXME this has to be merged with update_button_contents() in
3200    * gtktreeviewcolumn.c
3201    */
3202   
3203   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
3204     {
3205       column = list->data;
3206       
3207       if (column->button != NULL)
3208         continue;
3209
3210       gtk_tree_view_create_button (tree_view, i);
3211       alignment = gtk_alignment_new (column->xalign, 0.5, 0.0, 0.0);
3212
3213       hbox = gtk_hbox_new (FALSE, 2);
3214       arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
3215
3216       column->arrow = arrow;
3217       column->alignment = alignment;
3218       
3219       if (column->child)
3220         label = column->child;
3221       else
3222         {
3223           label = gtk_label_new (column->title);
3224           gtk_widget_show (label);
3225         }
3226
3227       if (column->xalign <= 0.5)
3228         gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
3229       else
3230         gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
3231       
3232       gtk_box_pack_start (GTK_BOX (hbox), alignment, TRUE, TRUE, 0);
3233         
3234       gtk_container_add (GTK_CONTAINER (alignment), label);
3235       gtk_container_add (GTK_CONTAINER (column->button), hbox);
3236
3237       gtk_widget_show (hbox);
3238       gtk_widget_show (alignment);
3239       /* don't show the arrow yet */
3240     }
3241
3242   gtk_tree_view_size_request_buttons (tree_view);
3243   
3244   if (GTK_WIDGET_REALIZED (tree_view))
3245     gtk_tree_view_realize_buttons (tree_view);
3246
3247   if (GTK_WIDGET_MAPPED (tree_view))
3248     gtk_tree_view_map_buttons (tree_view);  
3249 }
3250 #endif
3251
3252 /* Make sure the node is visible vertically */
3253 static void
3254 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
3255                                   GtkRBTree   *tree,
3256                                   GtkRBNode   *node)
3257 {
3258   gint offset;
3259
3260   offset = _gtk_rbtree_node_find_offset (tree, node);
3261
3262   /* we reverse the order, b/c in the unusual case of the
3263    * node's height being taller then the visible area, we'd rather
3264    * have the node flush to the top
3265    */
3266   if (offset + GTK_RBNODE_GET_HEIGHT (node) >
3267       tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size)
3268     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
3269                               offset + GTK_RBNODE_GET_HEIGHT (node) -
3270                               tree_view->priv->vadjustment->page_size);
3271   if (offset < tree_view->priv->vadjustment->value)
3272     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
3273                               offset);
3274 }
3275
3276 /* This function could be more efficient.
3277  * I'll optimize it if profiling seems to imply that
3278  * it's important
3279  */
3280 GtkTreePath *
3281 _gtk_tree_view_find_path (GtkTreeView *tree_view,
3282                           GtkRBTree   *tree,
3283                           GtkRBNode   *node)
3284 {
3285   GtkTreePath *path;
3286   GtkRBTree *tmp_tree;
3287   GtkRBNode *tmp_node, *last;
3288   gint count;
3289
3290   path = gtk_tree_path_new ();
3291
3292   g_return_val_if_fail (node != NULL, path);
3293   g_return_val_if_fail (node != tree->nil, path);
3294
3295   count = 1 + node->left->count;
3296
3297   last = node;
3298   tmp_node = node->parent;
3299   tmp_tree = tree;
3300   while (tmp_tree)
3301     {
3302       while (tmp_node != tmp_tree->nil)
3303         {
3304           if (tmp_node->right == last)
3305             count += 1 + tmp_node->left->count;
3306           last = tmp_node;
3307           tmp_node = tmp_node->parent;
3308         }
3309       gtk_tree_path_prepend_index (path, count - 1);
3310       last = tmp_tree->parent_node;
3311       tmp_tree = tmp_tree->parent_tree;
3312       if (last)
3313         {
3314           count = 1 + last->left->count;
3315           tmp_node = last->parent;
3316         }
3317     }
3318   return path;
3319 }
3320
3321 /* Returns TRUE if we ran out of tree before finding the node,
3322  * so the returned node is the last node we saw and the returned
3323  * tree is NULL
3324  */
3325 gboolean
3326 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
3327                           GtkTreePath  *path,
3328                           GtkRBTree   **tree,
3329                           GtkRBNode   **node)
3330 {
3331   GtkRBNode *tmpnode = NULL;
3332   GtkRBTree *tmptree = tree_view->priv->tree;
3333   gint *indices = gtk_tree_path_get_indices (path);
3334   gint depth = gtk_tree_path_get_depth (path);
3335   gint i = 0;
3336
3337   *node = NULL;
3338   *tree = NULL;
3339
3340   do
3341     {
3342       if (tmptree == NULL)
3343         {
3344           *node = tmpnode;
3345           *tree = tmptree;
3346           return TRUE;
3347         }
3348       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
3349       ++i;
3350       if (i >= depth)
3351         {
3352           *node = tmpnode;
3353           *tree = tmptree;
3354           return FALSE;
3355         }
3356       tmptree = tmpnode->children;
3357     }
3358   while (1);
3359 }
3360
3361 static void
3362 gtk_tree_view_queue_draw_node (GtkTreeView  *tree_view,
3363                                GtkRBTree    *tree,
3364                                GtkRBNode    *node,
3365                                GdkRectangle *clip_rect)
3366 {
3367   GdkRectangle rect;
3368
3369   if (!GTK_WIDGET_REALIZED (tree_view))
3370     return;
3371   
3372   rect.x = 0;
3373   rect.width = tree_view->priv->width;
3374
3375   rect.y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
3376   rect.height = BACKGROUND_HEIGHT (node);
3377
3378   if (clip_rect)
3379     {
3380       GdkRectangle new_rect;
3381
3382       gdk_rectangle_intersect (clip_rect, &rect, &new_rect);
3383
3384       gdk_window_invalidate_rect (tree_view->priv->bin_window, &new_rect, TRUE);
3385     }
3386   else
3387     {
3388       gdk_window_invalidate_rect (tree_view->priv->bin_window, &rect, TRUE);
3389     }
3390 }
3391
3392 static void
3393 gtk_tree_view_queue_draw_path (GtkTreeView      *tree_view,
3394                                GtkTreePath      *path,
3395                                GdkRectangle     *clip_rect)
3396 {
3397   GtkRBTree *tree = NULL;
3398   GtkRBNode *node = NULL;
3399   
3400   _gtk_tree_view_find_node (tree_view, path, &tree, &node);
3401
3402   if (tree)
3403     gtk_tree_view_queue_draw_node (tree_view, tree, node, clip_rect);
3404 }
3405
3406 /* x and y are the mouse position
3407  */
3408 static void
3409 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
3410                           GtkRBTree   *tree,
3411                           GtkRBNode   *node,
3412                           gint         x,
3413                           gint         y)
3414 {
3415   GdkRectangle area;
3416   GtkStateType state;
3417   GtkWidget *widget;
3418   gint x_offset = 0;
3419   
3420   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
3421     return;
3422
3423   widget = GTK_WIDGET (tree_view);
3424
3425   gtk_tree_view_get_arrow_xrange (tree_view, &x_offset, NULL);
3426   
3427   area.x = x_offset;
3428   area.y = CELL_FIRST_PIXEL (tree_view, tree, node);
3429   area.width = tree_view->priv->tab_offset - 2;
3430   area.height = CELL_HEIGHT (node);
3431
3432   if (node == tree_view->priv->button_pressed_node)
3433     {
3434       if (x >= area.x && x <= (area.x + area.width) &&
3435           y >= area.y && y <= (area.y + area.height))
3436         state = GTK_STATE_ACTIVE;
3437       else
3438         state = GTK_STATE_NORMAL;
3439     }
3440   else
3441     {
3442       if (node == tree_view->priv->prelight_node &&
3443           GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
3444         state = GTK_STATE_PRELIGHT;
3445       else
3446         state = GTK_STATE_NORMAL;
3447     }
3448
3449   /* FIXME expander size should come from a style property */
3450 #define EXPANDER_SIZE 8
3451   gtk_paint_expander (widget->style,
3452                       tree_view->priv->bin_window,
3453                       state,
3454                       &area,
3455                       widget,
3456                       "treeview",
3457                       area.x,
3458                       (area.y + (area.height - EXPANDER_SIZE) / 2 - (area.height + 1) % 2),
3459                       node->children != NULL);
3460 #undef EXPANDER_SIZE
3461 }
3462
3463
3464 static void
3465 _gtk_tree_view_update_col_width (GtkTreeView *tree_view)
3466 {
3467   GList *list, *last_column;
3468   GtkTreeViewColumn *column;
3469   gint width = 0;
3470
3471   for (last_column = g_list_last (tree_view->priv->columns);
3472        last_column &&
3473          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
3474          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
3475        last_column = last_column->prev)
3476     ;
3477
3478   if (last_column == NULL)
3479     return;
3480
3481   for (list = tree_view->priv->columns; list != last_column; list = list->next)
3482     {
3483       column = GTK_TREE_VIEW_COLUMN (list->data);
3484       if (! column->visible)
3485         continue;
3486
3487       width += column->width;
3488       column->displayed_width = (CLAMP (column->width, (column->min_width!=-1)?column->min_width:column->width, (column->max_width!=-1)?column->max_width:column->width));
3489     }
3490   column = GTK_TREE_VIEW_COLUMN (last_column->data);
3491   column->displayed_width = MAX (GTK_WIDGET (tree_view)->allocation.width, tree_view->priv->width) - width;
3492 }
3493
3494 void
3495 _gtk_tree_view_update_size (GtkTreeView *tree_view)
3496 {
3497   gint width, height;
3498   GList *list;
3499   GtkTreeViewColumn *column;
3500   gint i;
3501
3502   if (tree_view->priv->model == NULL)
3503     {
3504       tree_view->priv->width = 0;
3505       tree_view->priv->height = 0;
3506       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3507       return;
3508     }
3509
3510   width = 0;
3511   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
3512     {
3513       column = list->data;
3514       if (!column->visible)
3515         continue;
3516       width += TREE_VIEW_COLUMN_WIDTH (column);
3517     }
3518
3519   if (tree_view->priv->tree == NULL)
3520     height = 0;
3521   else
3522     height = tree_view->priv->tree->root->offset + TREE_VIEW_VERTICAL_SEPARATOR;
3523
3524   if (tree_view->priv->width != width)
3525     {
3526       tree_view->priv->width = width;
3527       tree_view->priv->hadjustment->upper = width;
3528       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
3529     }
3530
3531   if (tree_view->priv->height != height)
3532     {
3533       tree_view->priv->height = height;
3534       tree_view->priv->vadjustment->upper = tree_view->priv->height;
3535       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
3536     }
3537
3538   if (GTK_WIDGET_REALIZED (tree_view))
3539     {
3540       gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view));
3541       gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height);
3542
3543       _gtk_tree_view_update_col_width (tree_view);
3544     }
3545   
3546   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
3547 }
3548
3549 /* this function returns the new width of the column being resized given
3550  * the column and x position of the cursor; the x cursor position is passed
3551  * in as a pointer and automagicly corrected if it's beyond min/max limits
3552  */
3553 static gint
3554 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
3555                                 gint       i,
3556                                 gint      *x)
3557 {
3558   GtkTreeViewColumn *column;
3559   gint width;
3560
3561   /* first translate the x position from widget->window
3562    * to clist->clist_window
3563    */
3564
3565   column = g_list_nth (tree_view->priv->columns, i)->data;
3566   width = *x - column->button->allocation.x;
3567
3568   /* Clamp down the value */
3569   if (column->min_width == -1)
3570     width = MAX (column->button->requisition.width,
3571                  width);
3572   else
3573     width = MAX (column->min_width,
3574                  width);
3575   if (column->max_width != -1)
3576     width = MIN (width, column->max_width != -1);
3577   *x = column->button->allocation.x + width;
3578
3579   return width;
3580 }
3581
3582 /* Callbacks */
3583 static void
3584 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
3585                                   GtkTreeView     *tree_view)
3586 {
3587   if (GTK_WIDGET_REALIZED (tree_view))
3588     {
3589       gdk_window_move (tree_view->priv->bin_window,
3590                        - tree_view->priv->hadjustment->value,
3591                        - tree_view->priv->vadjustment->value);
3592       gdk_window_move (tree_view->priv->header_window,
3593                        - tree_view->priv->hadjustment->value,
3594                        0);
3595
3596       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
3597       gdk_window_process_updates (tree_view->priv->header_window, TRUE);
3598     }
3599 }
3600
3601 \f
3602
3603 /* Public methods
3604  */
3605
3606 /**
3607  * gtk_tree_view_new:
3608  * 
3609  * Creates a new #GtkTreeView widget.
3610  * 
3611  * Return value: A newly created #GtkTreeView widget.
3612  **/
3613 GtkWidget *
3614 gtk_tree_view_new (void)
3615 {
3616   GtkTreeView *tree_view;
3617
3618   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
3619
3620   return GTK_WIDGET (tree_view);
3621 }
3622
3623 /**
3624  * gtk_tree_view_new_with_model:
3625  * @model: the model.
3626  * 
3627  * Creates a new #GtkTreeView widget with the model initialized to @model.
3628  * 
3629  * Return value: A newly created #GtkTreeView widget.
3630  **/
3631 GtkWidget *
3632 gtk_tree_view_new_with_model (GtkTreeModel *model)
3633 {
3634   GtkTreeView *tree_view;
3635
3636   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
3637   gtk_tree_view_set_model (tree_view, model);
3638
3639   return GTK_WIDGET (tree_view);
3640 }
3641
3642 /**
3643  * gtk_tree_view_get_model:
3644  * @tree_view: a #GtkTreeView
3645  * 
3646  * Returns the model the the #GtkTreeView is based on.  Returns NULL if the
3647  * model is unset.
3648  * 
3649  * Return value: A #GtkTreeModel, or NULL if none is currently being used.
3650  **/
3651 GtkTreeModel *
3652 gtk_tree_view_get_model (GtkTreeView *tree_view)
3653 {
3654   g_return_val_if_fail (tree_view != NULL, NULL);
3655   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3656
3657   return tree_view->priv->model;
3658 }
3659
3660 static void
3661 gtk_tree_view_setup_model (GtkTreeView *tree_view)
3662 {
3663   GtkTreePath *path;
3664   GtkTreeIter iter;
3665
3666   tree_view->priv->tree = _gtk_rbtree_new ();
3667
3668   g_signal_connect (tree_view->priv->model,
3669                     "changed",
3670                     gtk_tree_view_changed,
3671                     tree_view);
3672   g_signal_connect (tree_view->priv->model,
3673                     "inserted",
3674                     gtk_tree_view_inserted,
3675                     tree_view);
3676   g_signal_connect (tree_view->priv->model,
3677                     "has_child_toggled",
3678                     gtk_tree_view_has_child_toggled,
3679                     tree_view);
3680   g_signal_connect (tree_view->priv->model,
3681                     "deleted",
3682                     gtk_tree_view_deleted,
3683                     tree_view);
3684
3685   if (tree_view->priv->columns == NULL)
3686     return;
3687
3688   path = gtk_tree_path_new_root ();
3689
3690   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
3691     {
3692       gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE, GTK_WIDGET_REALIZED (tree_view));
3693     }
3694   
3695   gtk_tree_path_free (path);
3696
3697   //  gtk_tree_view_create_buttons (tree_view);
3698
3699   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
3700 }
3701
3702 /**
3703  * gtk_tree_view_set_model:
3704  * @tree_view: A #GtkTreeNode.
3705  * @model: The model.
3706  * 
3707  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
3708  * set, it will remove it before setting the new model.  If @model is NULL, then
3709  * it will unset the old model.
3710  **/
3711 void
3712 gtk_tree_view_set_model (GtkTreeView  *tree_view,
3713                          GtkTreeModel *model)
3714 {
3715   g_return_if_fail (tree_view != NULL);
3716   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3717
3718   if (tree_view->priv->model != NULL)
3719     {
3720       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
3721         {
3722           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
3723                                                 G_SIGNAL_MATCH_FUNC,
3724                                                 0, 0, NULL,
3725                                                 gtk_tree_view_changed, NULL);
3726           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
3727                                                 G_SIGNAL_MATCH_FUNC,
3728                                                 0, 0, NULL,
3729                                                 gtk_tree_view_inserted, NULL);
3730           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
3731                                                 G_SIGNAL_MATCH_FUNC,
3732                                                 0, 0, NULL,
3733                                                 gtk_tree_view_has_child_toggled, NULL);
3734           g_signal_handlers_disconnect_matched (G_OBJECT (tree_view->priv->model),
3735                                                 G_SIGNAL_MATCH_FUNC,
3736                                                 0, 0, NULL,
3737                                                 gtk_tree_view_deleted, NULL);
3738           _gtk_rbtree_free (tree_view->priv->tree);
3739         }
3740
3741       if (tree_view->priv->drag_dest_row)
3742         gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
3743       
3744       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
3745     }
3746
3747   tree_view->priv->model = model;
3748   if (model == NULL)
3749     {
3750       tree_view->priv->tree = NULL;
3751       if (GTK_WIDGET_REALIZED (tree_view))
3752         _gtk_tree_view_update_size (tree_view);
3753       return;
3754     }
3755   else if (GTK_WIDGET_REALIZED (tree_view))
3756     {
3757       gtk_tree_view_setup_model (tree_view);
3758       _gtk_tree_view_update_size (tree_view);
3759     }
3760
3761   g_object_notify (G_OBJECT (tree_view), "model");
3762 }
3763
3764 /**
3765  * gtk_tree_view_get_selection:
3766  * @tree_view: A #GtkTreeView.
3767  * 
3768  * Gets the #GtkTreeSelection associated with @tree_view.
3769  * 
3770  * Return value: A #GtkTreeSelection object.
3771  **/
3772 GtkTreeSelection *
3773 gtk_tree_view_get_selection (GtkTreeView *tree_view)
3774 {
3775   g_return_val_if_fail (tree_view != NULL, NULL);
3776   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3777
3778   if (tree_view->priv->selection == NULL)
3779     tree_view->priv->selection =
3780       _gtk_tree_selection_new_with_tree_view (tree_view);
3781
3782   return tree_view->priv->selection;
3783 }
3784
3785 /**
3786  * gtk_tree_view_get_hadjustment:
3787  * @tree_view: A #GtkTreeView
3788  * 
3789  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
3790  * 
3791  * Return value: A #GtkAdjustment object, or NULL if none is currently being
3792  * used.
3793  **/
3794 GtkAdjustment *
3795 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
3796 {
3797   g_return_val_if_fail (tree_view != NULL, NULL);
3798   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3799
3800   if (tree_view->priv->hadjustment == NULL)
3801     gtk_tree_view_set_hadjustment (tree_view, NULL);
3802   
3803   return tree_view->priv->hadjustment;
3804 }
3805
3806 /**
3807  * gtk_tree_view_set_hadjustment:
3808  * @tree_view: A #GtkTreeView
3809  * @adjustment: The #GtkAdjustment to set, or NULL
3810  * 
3811  * Sets the #GtkAdjustment for the current horizontal aspect.
3812  **/
3813 void
3814 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
3815                                GtkAdjustment *adjustment)
3816 {
3817   g_return_if_fail (tree_view != NULL);
3818   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3819
3820   gtk_tree_view_set_adjustments (tree_view,
3821                                  adjustment,
3822                                  tree_view->priv->vadjustment);
3823
3824   g_object_notify (G_OBJECT (tree_view), "hadjustment");
3825 }
3826
3827 /**
3828  * gtk_tree_view_get_vadjustment:
3829  * @tree_view: A #GtkTreeView
3830  * 
3831  * Gets the #GtkAdjustment currently being used for the vertical aspect.
3832  * 
3833  * Return value: A #GtkAdjustment object, or NULL if none is currently being
3834  * used.
3835  **/
3836 GtkAdjustment *
3837 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
3838 {
3839   g_return_val_if_fail (tree_view != NULL, NULL);
3840   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3841
3842   if (tree_view->priv->vadjustment == NULL)
3843     gtk_tree_view_set_vadjustment (tree_view, NULL);
3844   
3845   return tree_view->priv->vadjustment;
3846 }
3847
3848 /**
3849  * gtk_tree_view_set_vadjustment:
3850  * @tree_view: A #GtkTreeView
3851  * @adjustment: The #GtkAdjustment to set, or NULL
3852  * 
3853  * Sets the #GtkAdjustment for the current vertical aspect.
3854  **/
3855 void
3856 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
3857                                GtkAdjustment *adjustment)
3858 {
3859   g_return_if_fail (tree_view != NULL);
3860   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3861
3862   gtk_tree_view_set_adjustments (tree_view,
3863                                  tree_view->priv->hadjustment,
3864                                  adjustment);
3865
3866   g_object_notify (G_OBJECT (tree_view), "vadjustment");
3867 }
3868
3869 /**
3870  * gtk_tree_view_set_adjustments:
3871  * @tree_view: A #GtkTreeView
3872  * @hadj: The horizontal #GtkAdjustment to set, or NULL
3873  * @vadj: The vertical #GtkAdjustment to set, or NULL
3874  * 
3875  * Sets the horizonal and or vertical #GtkAdjustment.
3876  **/
3877 static void
3878 gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
3879                                GtkAdjustment *hadj,
3880                                GtkAdjustment *vadj)
3881 {
3882   gboolean need_adjust = FALSE;
3883
3884   g_return_if_fail (tree_view != NULL);
3885   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3886
3887   if (hadj)
3888     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
3889   else
3890     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
3891   if (vadj)
3892     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
3893   else
3894     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
3895
3896   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
3897     {
3898       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->hadjustment), tree_view);
3899       gtk_object_unref (GTK_OBJECT (tree_view->priv->hadjustment));
3900     }
3901
3902   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
3903     {
3904       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->vadjustment), tree_view);
3905       gtk_object_unref (GTK_OBJECT (tree_view->priv->vadjustment));
3906     }
3907
3908   if (tree_view->priv->hadjustment != hadj)
3909     {
3910       tree_view->priv->hadjustment = hadj;
3911       gtk_object_ref (GTK_OBJECT (tree_view->priv->hadjustment));
3912       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
3913
3914       gtk_signal_connect (GTK_OBJECT (tree_view->priv->hadjustment), "value_changed",
3915                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
3916                           tree_view);
3917       need_adjust = TRUE;
3918     }
3919
3920   if (tree_view->priv->vadjustment != vadj)
3921     {
3922       tree_view->priv->vadjustment = vadj;
3923       gtk_object_ref (GTK_OBJECT (tree_view->priv->vadjustment));
3924       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
3925
3926       gtk_signal_connect (GTK_OBJECT (tree_view->priv->vadjustment), "value_changed",
3927                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
3928                           tree_view);
3929       need_adjust = TRUE;
3930     }
3931
3932   if (need_adjust)
3933     gtk_tree_view_adjustment_changed (NULL, tree_view);
3934 }
3935
3936
3937 /* Column and header operations */
3938
3939 /**
3940  * gtk_tree_view_get_headers_visible:
3941  * @tree_view: A #GtkTreeView.
3942  * 
3943  * Returns TRUE if the headers on the @tree_view are visible.
3944  * 
3945  * Return value: Whether the headers are visible or not.
3946  **/
3947 gboolean
3948 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
3949 {
3950   g_return_val_if_fail (tree_view != NULL, FALSE);
3951   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
3952
3953   return GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3954 }
3955
3956 /**
3957  * gtk_tree_view_set_headers_visible:
3958  * @tree_view: A #GtkTreeView.
3959  * @headers_visible: TRUE if the headers are visible
3960  * 
3961  * Sets the the visibility state of the headers.
3962  **/
3963 void
3964 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
3965                                    gboolean     headers_visible)
3966 {
3967   gint x, y;
3968   GList *list;
3969   GtkTreeViewColumn *column;
3970
3971   g_return_if_fail (tree_view != NULL);
3972   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3973
3974   headers_visible = !! headers_visible;
3975   
3976   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) == headers_visible)
3977     return;
3978
3979   if (headers_visible)
3980     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3981   else
3982     GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3983
3984   if (GTK_WIDGET_REALIZED (tree_view))
3985     {
3986       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
3987       if (headers_visible)
3988         {
3989           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));
3990           
3991           if (GTK_WIDGET_MAPPED (tree_view))
3992             gtk_tree_view_map_buttons (tree_view);
3993         }
3994       else
3995         {
3996           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
3997
3998           for (list = tree_view->priv->columns; list; list = list->next)
3999             {
4000               column = list->data;
4001               gtk_widget_unmap (column->button);
4002             }
4003           gdk_window_hide (tree_view->priv->header_window);
4004         }
4005     }
4006
4007   tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
4008   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
4009   tree_view->priv->vadjustment->lower = 0;
4010   tree_view->priv->vadjustment->upper = tree_view->priv->height;
4011   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
4012
4013   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4014
4015   g_object_notify (G_OBJECT (tree_view), "headers_visible");
4016 }
4017
4018
4019 /**
4020  * gtk_tree_view_columns_autosize:
4021  * @tree_view: A #GtkTreeView.
4022  * 
4023  * Resizes all columns to their optimal width.
4024  **/
4025 void
4026 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
4027 {
4028   gboolean dirty = FALSE;
4029   GList *list;
4030   GtkTreeViewColumn *column;
4031
4032   g_return_if_fail (tree_view != NULL);
4033   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4034
4035   for (list = tree_view->priv->columns; list; list = list->next)
4036     {
4037       column = list->data;
4038       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
4039         continue;
4040       column->dirty = TRUE;
4041       dirty = TRUE;
4042     }
4043
4044   if (dirty)
4045     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4046 }
4047
4048 /**
4049  * gtk_tree_view_set_headers_clickable:
4050  * @tree_view: A #GtkTreeView.
4051  * @setting: TRUE if the columns are clickable.
4052  * 
4053  * Allow the column title buttons to be clicked.
4054  **/
4055 void
4056 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
4057                                      gboolean   setting)
4058 {
4059   GList *list;
4060
4061   g_return_if_fail (tree_view != NULL);
4062   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4063   g_return_if_fail (tree_view->priv->model != NULL);
4064
4065   for (list = tree_view->priv->columns; list; list = list->next)
4066     gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
4067
4068   g_object_notify (G_OBJECT (tree_view), "headers_clickable");
4069 }
4070
4071 /**
4072  * gtk_tree_view_append_column:
4073  * @tree_view: A #GtkTreeView.
4074  * @column: The #GtkTreeViewColumn to add.
4075  * 
4076  * Appends @column to the list of columns.
4077  * 
4078  * Return value: The number of columns in @tree_view after appending.
4079  **/
4080 gint
4081 gtk_tree_view_append_column (GtkTreeView       *tree_view,
4082                              GtkTreeViewColumn *column)
4083 {
4084   g_return_val_if_fail (tree_view != NULL, -1);
4085   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
4086   g_return_val_if_fail (column != NULL, -1);
4087   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
4088   g_return_val_if_fail (column->tree_view == NULL, -1);
4089
4090   return gtk_tree_view_insert_column (tree_view, column, -1);
4091 }
4092
4093
4094 /**
4095  * gtk_tree_view_remove_column:
4096  * @tree_view: A #GtkTreeView.
4097  * @column: The #GtkTreeViewColumn to remove.
4098  * 
4099  * Removes @column from @tree_view.
4100  * 
4101  * Return value: The number of columns in @tree_view after removing.
4102  **/
4103 gint
4104 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
4105                              GtkTreeViewColumn *column)
4106 {
4107   g_return_val_if_fail (tree_view != NULL, -1);
4108   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
4109   g_return_val_if_fail (column != NULL, -1);
4110   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
4111   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
4112
4113   _gtk_tree_view_column_unset_tree_view (column);
4114
4115   tree_view->priv->columns = g_list_remove (tree_view->priv->columns, column);
4116
4117   g_object_unref (G_OBJECT (column));
4118
4119   tree_view->priv->n_columns--;
4120
4121   if (GTK_WIDGET_REALIZED (tree_view))
4122     {
4123       GList *list;
4124
4125       for (list = tree_view->priv->columns; list; list = list->next)
4126         {
4127           column = GTK_TREE_VIEW_COLUMN (list->data);
4128           if (column->visible)
4129             column->dirty = TRUE;
4130         }
4131
4132       if (tree_view->priv->n_columns == 0 &&
4133           gtk_tree_view_get_headers_visible (tree_view))
4134         gdk_window_hide (tree_view->priv->header_window);
4135
4136       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4137     }
4138
4139   
4140   return tree_view->priv->n_columns;
4141 }
4142
4143 /**
4144  * gtk_tree_view_insert_column:
4145  * @tree_view: A #GtkTreeView.
4146  * @column: The #GtkTreeViewColumn to be inserted.
4147  * @position: The position to insert @column in.
4148  * 
4149  * This inserts the @column into the @tree_view at @position.  If @position is
4150  * -1, then the column is inserted at the end.
4151  * 
4152  * Return value: The number of columns in @tree_view after insertion.
4153  **/
4154 gint
4155 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
4156                              GtkTreeViewColumn *column,
4157                              gint               position)
4158 {
4159   g_return_val_if_fail (tree_view != NULL, -1);
4160   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
4161   g_return_val_if_fail (column != NULL, -1);
4162   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
4163   g_return_val_if_fail (column->tree_view == NULL, -1);
4164
4165   g_object_ref (G_OBJECT (column));
4166
4167   if (tree_view->priv->n_columns == 0 &&
4168       GTK_WIDGET_REALIZED (tree_view) &&
4169       gtk_tree_view_get_headers_visible (tree_view))
4170     {
4171       gdk_window_show (tree_view->priv->header_window);
4172     }
4173
4174   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
4175                                             column, position);
4176   _gtk_tree_view_column_set_tree_view (column, tree_view);
4177   _gtk_tree_view_column_create_button (column);
4178
4179   tree_view->priv->n_columns++;
4180
4181
4182   if (GTK_WIDGET_REALIZED (tree_view))
4183     {
4184       GList *list;
4185
4186       for (list = tree_view->priv->columns; list; list = list->next)
4187         {
4188           column = GTK_TREE_VIEW_COLUMN (list->data);
4189           if (column->visible)
4190             column->dirty = TRUE;
4191         }
4192       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
4193     }
4194
4195   return tree_view->priv->n_columns;
4196 }
4197
4198 /**
4199  * gtk_tree_view_insert_column_with_attributes:
4200  * @tree_view: A #GtkTreeView
4201  * @position: The position to insert the new column in.
4202  * @title: The title to set the header to.
4203  * @cell: The #GtkCellRenderer.
4204  * @Varargs: A NULL terminated list of attributes.
4205  * 
4206  * Creates a new #GtkTreeViewColumn and inserts it into the @tree_view at
4207  * @position.  If @position is -1, then the newly created column is inserted at
4208  * the end.  The column is initialized with the attributes given.
4209  * 
4210  * Return value: The number of columns in @tree_view after insertion.
4211  **/
4212 gint
4213 gtk_tree_view_insert_column_with_attributes (GtkTreeView     *tree_view,
4214                                              gint             position,
4215                                              gchar           *title,
4216                                              GtkCellRenderer *cell,
4217                                              ...)
4218 {
4219   GtkTreeViewColumn *column;
4220   gchar *attribute;
4221   va_list args;
4222   gint column_id;
4223
4224   g_return_val_if_fail (tree_view != NULL, -1);
4225   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
4226
4227   column = gtk_tree_view_column_new ();
4228
4229   gtk_tree_view_column_set_title (column, title);
4230   gtk_tree_view_column_set_cell_renderer (column, cell);
4231
4232   va_start (args, cell);
4233
4234   attribute = va_arg (args, gchar *);
4235   
4236   while (attribute != NULL)
4237     {
4238       column_id = va_arg (args, gint);
4239       gtk_tree_view_column_add_attribute (column, attribute, column_id);
4240       attribute = va_arg (args, gchar *);
4241     }
4242
4243   va_end (args);
4244
4245   gtk_tree_view_insert_column (tree_view, column, position);
4246   g_object_unref (column);
4247
4248   return tree_view->priv->n_columns;
4249 }
4250
4251 /**
4252  * gtk_tree_view_get_column:
4253  * @tree_view: A #GtkTreeView.
4254  * @n: The position of the column, counting from 0.
4255  * 
4256  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
4257  * 
4258  * Return value: The #GtkTreeViewColumn, or NULL if the position is outside the
4259  * range of columns.
4260  **/
4261 GtkTreeViewColumn *
4262 gtk_tree_view_get_column (GtkTreeView *tree_view,
4263                           gint         n)
4264 {
4265   g_return_val_if_fail (tree_view != NULL, NULL);
4266   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
4267   g_return_val_if_fail (tree_view->priv->model != NULL, NULL);
4268
4269   if (n < 0 || n >= tree_view->priv->n_columns)
4270     return NULL;
4271   
4272   if (tree_view->priv->columns == NULL)
4273     return NULL;
4274
4275   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
4276 }
4277
4278 void
4279 gtk_tree_view_set_expander_column (GtkTreeView *tree_view,
4280                                    gint         col)
4281 {
4282   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4283
4284   if (tree_view->priv->expander_column != col)
4285     {
4286       tree_view->priv->expander_column = col;
4287
4288       g_object_notify (G_OBJECT (tree_view), "expander_column");
4289     }
4290 }
4291
4292 gint
4293 gtk_tree_view_get_expander_column (GtkTreeView *tree_view)
4294 {
4295   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
4296
4297   return tree_view->priv->expander_column;
4298 }
4299
4300 /**
4301  * gtk_tree_view_scroll_to_point:
4302  * @tree_view: a #GtkTreeView
4303  * @tree_x: X coordinate of new top-left pixel of visible area
4304  * @tree_y: Y coordinate of new top-left pixel of visible area
4305  * 
4306  * Scrolls the tree view such that the top-left corner of the visible
4307  * area is @tree_x, @tree_y, where @tree_x and @tree_y are specified
4308  * in tree window coordinates.  The @tree_view must be realized before
4309  * this function is called.  If it isn't, you probably want ot be
4310  * using gtk_tree_view_scroll_to_cell.
4311  **/
4312 void
4313 gtk_tree_view_scroll_to_point (GtkTreeView *tree_view,
4314                                gint         tree_x,
4315                                gint         tree_y)
4316 {
4317   GtkAdjustment *hadj;
4318   GtkAdjustment *vadj;
4319
4320   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4321   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
4322
4323   hadj = tree_view->priv->hadjustment;
4324   vadj = tree_view->priv->vadjustment;
4325
4326   gtk_adjustment_set_value (hadj, CLAMP (tree_x, hadj->lower, hadj->upper));
4327   gtk_adjustment_set_value (vadj, CLAMP (tree_y, vadj->lower, vadj->upper));  
4328 }
4329
4330 /**
4331  * gtk_tree_view_scroll_to_cell
4332  * @tree_view: A #GtkTreeView.
4333  * @path: The path of the row to move to.
4334  * @column: The #GtkTreeViewColumn to move horizontally to.
4335  * @row_align: The vertical alignment of the row specified by @path.
4336  * @col_align: The horizontal alignment of the column specified by @column.
4337  * 
4338  * Moves the alignments of @tree_view to the position specified by
4339  * @column and @path.  If @column is NULL, then no horizontal
4340  * scrolling occurs.  Likewise, if @path is NULL no vertical scrolling
4341  * occurs.  @row_align determines where the row is placed, and
4342  * @col_align determines where @column is placed.  Both are expected
4343  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
4344  * right/bottom alignment, 0.5 means center.
4345  **/
4346 void
4347 gtk_tree_view_scroll_to_cell (GtkTreeView       *tree_view,
4348                               GtkTreePath       *path,
4349                               GtkTreeViewColumn *column,
4350                               gfloat             row_align,
4351                               gfloat             col_align)
4352 {
4353   GdkRectangle cell_rect;
4354   GdkRectangle vis_rect;
4355   gint dest_x, dest_y;
4356   
4357   /* FIXME work on unmapped/unrealized trees? maybe implement when
4358    * we do incremental reflow for trees
4359    */
4360   
4361   g_return_if_fail (tree_view != NULL);
4362   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4363   g_return_if_fail (row_align >= 0.0);
4364   g_return_if_fail (row_align <= 1.0);
4365   g_return_if_fail (col_align >= 0.0);
4366   g_return_if_fail (col_align <= 1.0);
4367   g_return_if_fail (path != NULL || column != NULL);
4368
4369   row_align = CLAMP (row_align, 0.0, 1.0);
4370   col_align = CLAMP (col_align, 0.0, 1.0);
4371
4372   if (! GTK_WIDGET_REALIZED (tree_view))
4373     {
4374       if (path)
4375         tree_view->priv->scroll_to_path = gtk_tree_path_copy (path);
4376       if (column)
4377         tree_view->priv->scroll_to_column = column;
4378       tree_view->priv->scroll_to_row_align = row_align;
4379       tree_view->priv->scroll_to_col_align = col_align;
4380
4381       return;
4382     }
4383
4384   gtk_tree_view_get_cell_area (tree_view, path, column, &cell_rect);
4385   gtk_tree_view_get_visible_rect (tree_view, &vis_rect);
4386
4387   dest_x = vis_rect.x;
4388   dest_y = vis_rect.y;
4389   
4390   if (path)
4391     {
4392       dest_x = cell_rect.x +
4393         cell_rect.width * row_align -
4394         vis_rect.width * row_align;
4395     }
4396
4397   if (column)
4398     {
4399       dest_y = cell_rect.y +
4400         cell_rect.height * col_align -
4401         vis_rect.height * col_align;
4402     }
4403
4404   gtk_tree_view_scroll_to_point (tree_view, dest_x, dest_y);
4405 }
4406
4407 /**
4408  * gtk_tree_view_get_path_at_pos:
4409  * @tree_view: A #GtkTreeView.
4410  * @window: The #GdkWindow to check against.
4411  * @x: The x position to be identified.
4412  * @y: The y position to be identified.
4413  * @path: A pointer to a #GtkTreePath pointer to be filled in, or %NULL
4414  * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or %NULL
4415  * @cell_x: A pointer where the X coordinate relative to the cell can be placed, or %NULL
4416  * @cell_y: A pointer where the Y coordinate relative to the cell can be placed, or %NULL
4417  * 
4418  * Finds the path at the point (@x, @y) relative to @window.  If
4419  * @window is NULL, then the point is found relative to the widget
4420  * coordinates.  This function is expected to be called after an
4421  * event, with event->window being passed in as @window.  It is
4422  * primarily for things like popup menus.  If @path is non-NULL, then
4423  * it will be filled with the #GtkTreePath at that point.  This path
4424  * should be freed with #gtk_tree_path_free.  If @column is non-NULL,
4425  * then it will be filled with the column at that point. @cell_x and
4426  * @cell_y return the coordinates relative to the cell background
4427  * (i.e. the background_area passed to gtk_cell_renderer_render()).
4428  * 
4429  * Return value: TRUE if a row exists at that coordinate.
4430  **/
4431 gboolean
4432 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
4433                                GdkWindow          *window,
4434                                gint                x,
4435                                gint                y,
4436                                GtkTreePath       **path,
4437                                GtkTreeViewColumn **column,
4438                                gint               *cell_x,
4439                                gint               *cell_y)
4440 {
4441   GtkRBTree *tree;
4442   GtkRBNode *node;
4443   gint y_offset;
4444   
4445   g_return_val_if_fail (tree_view != NULL, FALSE);
4446   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
4447   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
4448
4449   if (window)
4450     g_return_val_if_fail (window == tree_view->priv->bin_window, FALSE);
4451
4452   if (path)
4453     *path = NULL;
4454   if (column)
4455     *column = NULL;
4456
4457   if (x > tree_view->priv->hadjustment->upper)
4458     return FALSE;
4459
4460   if (x < 0 || y < 0)
4461     return FALSE;
4462   
4463   if (column || cell_x)
4464     {
4465       GtkTreeViewColumn *tmp_column;
4466       GtkTreeViewColumn *last_column = NULL;
4467       GList *list;
4468       gint remaining_x = x;
4469       gboolean found = FALSE;
4470       
4471       for (list = tree_view->priv->columns; list; list = list->next)
4472         {
4473           tmp_column = list->data;
4474
4475           if (tmp_column->visible == FALSE)
4476             continue;
4477
4478           last_column = tmp_column;
4479           if (remaining_x <= tmp_column->width)
4480             {
4481               found = TRUE;
4482               
4483               if (column)
4484                 *column = tmp_column;
4485
4486               if (cell_x)
4487                 *cell_x = remaining_x;
4488               
4489               break;
4490             }
4491           remaining_x -= tmp_column->width;
4492         }
4493
4494       if (!found)
4495         {
4496           if (column)
4497             *column = last_column;
4498
4499           if (cell_x)
4500             *cell_x = last_column->width + remaining_x;
4501         }
4502     }
4503
4504   if (window)
4505     {
4506       y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
4507                                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y),
4508                                           &tree, &node);
4509     }
4510   else
4511     {
4512       if (y < TREE_VIEW_HEADER_HEIGHT (tree_view))
4513         return FALSE;
4514
4515       y_offset = _gtk_rbtree_find_offset (tree_view->priv->tree,
4516                                           TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y + tree_view->priv->vadjustment->value),
4517                                           &tree, &node);
4518     }
4519   
4520   if (tree == NULL)
4521     return FALSE;
4522
4523   if (cell_y)
4524     *cell_y = y_offset;
4525   
4526   if (path)
4527     *path = _gtk_tree_view_find_path (tree_view, tree, node);
4528
4529   return TRUE;
4530 }
4531
4532
4533 static void
4534 gtk_tree_view_get_background_xrange (GtkTreeView       *tree_view,
4535                                      GtkRBTree         *tree,
4536                                      GtkTreeViewColumn *column,
4537                                      gint              *x1,
4538                                      gint              *x2)
4539 {
4540   GtkTreeViewColumn *tmp_column = NULL;
4541   gint total_width;
4542   GList *list;
4543   
4544   if (x1)
4545     *x1 = 0;
4546
4547   if (x2)
4548     *x2 = 0;
4549
4550   total_width = 0;
4551   for (list = tree_view->priv->columns; list; list = list->next)
4552     {
4553       tmp_column = list->data;
4554       
4555       if (tmp_column == column)
4556         break;
4557       
4558       if (tmp_column->visible)
4559         total_width += tmp_column->width;
4560     }
4561   
4562   if (tmp_column != column)
4563     {
4564       g_warning (G_STRLOC": passed-in column isn't in the tree");
4565       return;
4566     }
4567   
4568   if (x1)
4569     *x1 = total_width;
4570   
4571   if (x2)
4572     {
4573       if (column->visible)
4574         *x2 = total_width + column->width;
4575       else
4576         *x2 = total_width; /* width of 0 */
4577     }
4578 }
4579
4580 static void
4581 gtk_tree_view_get_cell_xrange (GtkTreeView       *tree_view,
4582                                GtkRBTree         *tree,
4583                                GtkTreeViewColumn *column,
4584                                gint              *x1,
4585                                gint              *x2)
4586 {
4587   GtkTreeViewColumn *tmp_column = NULL;
4588   gint total_width;
4589   GList *list;
4590   gint i;
4591   
4592   if (x1)
4593     *x1 = 0;
4594
4595   if (x2)
4596     *x2 = 0;
4597
4598   i = 0;
4599   total_width = 0;
4600   for (list = tree_view->priv->columns; list; list = list->next)
4601     {
4602       tmp_column = list->data;
4603       
4604       if (tmp_column == column)
4605         break;
4606       
4607       if (tmp_column->visible)
4608         total_width += tmp_column->width;
4609
4610       ++i;
4611     }
4612   
4613   if (tmp_column != column)
4614     {
4615       g_warning (G_STRLOC": passed-in column isn't in the tree");
4616       return;
4617     }
4618
4619   /* Remember we're getting the cell range, i.e. the cell_area passed
4620    * to the cell renderer.
4621    */
4622
4623   if (i == tree_view->priv->expander_column)
4624     total_width += tree_view->priv->tab_offset * _gtk_rbtree_get_depth (tree);
4625   
4626   if (x1)
4627     *x1 = total_width;
4628   
4629   if (x2)
4630     {
4631       if (column->visible)
4632         *x2 = total_width + column->displayed_width;
4633       else
4634         *x2 = total_width; /* width of 0 */
4635     }
4636 }
4637
4638 static void
4639 gtk_tree_view_get_arrow_xrange (GtkTreeView *tree_view,
4640                                 gint        *x1,
4641                                 gint        *x2)
4642 {
4643   gint x_offset = 0;
4644   GList *list;
4645   GtkTreeViewColumn *tmp_column = NULL;
4646   gint total_width;
4647   gint i;
4648   
4649   i = 0;
4650   total_width = 0;
4651   for (list = tree_view->priv->columns; list; list = list->next)
4652     {
4653       tmp_column = list->data;
4654
4655       if (i == tree_view->priv->expander_column)
4656         {
4657           x_offset = total_width;
4658           break;
4659         }
4660           
4661       if (tmp_column->visible)
4662         total_width += tmp_column->width;
4663
4664       ++i;
4665     }
4666
4667   if (x1)
4668     *x1 = x_offset;
4669   
4670   if (tmp_column && tmp_column->visible)
4671     {
4672       /* +1 because x2 isn't included in the range. */
4673       if (x2)
4674         *x2 = x_offset + tree_view->priv->tab_offset + 1;
4675     }
4676   else
4677     {
4678       /* return an empty range, the expander column is hidden */
4679       if (x2)
4680         *x2 = x_offset;
4681     }
4682 }
4683
4684
4685 /**
4686  * gtk_tree_view_get_cell_area:
4687  * @tree_view: a #GtkTreeView
4688  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
4689  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
4690  * @rect: rectangle to fill with cell rect
4691  * 
4692  * Fills the bounding rectangle in tree window coordinates for the
4693  * cell at the row specified by @path and the column specified by
4694  * @column.  If @path is %NULL, the y and height fields of the
4695  * rectangle will be filled with 0. If @column is %NULL, the x and
4696  * width fields will be filled with 0.  The sum of all cell rects does
4697  * not cover the entire tree; there are extra pixels in between rows,
4698  * for example. The returned rectangle is equivalent to the @cell_area
4699  * passed to gtk_cell_renderer_render().
4700  * 
4701  **/
4702 void
4703 gtk_tree_view_get_cell_area (GtkTreeView        *tree_view,
4704                              GtkTreePath        *path,
4705                              GtkTreeViewColumn  *column,
4706                              GdkRectangle       *rect)
4707 {
4708   GtkRBTree *tree = NULL;
4709   GtkRBNode *node = NULL;
4710   
4711   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4712   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
4713   g_return_if_fail (rect != NULL);
4714
4715   rect->x = 0;
4716   rect->y = 0;
4717   rect->width = 0;
4718   rect->height = 0;
4719   
4720   if (path)
4721     {
4722       /* Get vertical coords */
4723       
4724       _gtk_tree_view_find_node (tree_view, path, &tree, &node);
4725       
4726       if (tree == NULL)
4727         {
4728           g_warning (G_STRLOC": no row corresponding to path");
4729           return;
4730         }
4731
4732       /* Remember that the rbtree stores node height including the vertical
4733        * separator, see comment at top of file.
4734        */
4735       rect->y = CELL_FIRST_PIXEL (tree_view, tree, node);
4736
4737       rect->height = CELL_HEIGHT (node);
4738     }
4739
4740   if (column)
4741     {
4742       gint x2 = 0;
4743       
4744       gtk_tree_view_get_cell_xrange (tree_view, tree, column, &rect->x, &x2);
4745       rect->width = x2 - rect->x;
4746     }
4747 }
4748
4749
4750 /**
4751  * gtk_tree_view_get_background_area:
4752  * @tree_view: a #GtkTreeView
4753  * @path: a #GtkTreePath for the row, or %NULL to get only horizontal coordinates
4754  * @column: a #GtkTreeViewColumn for the column, or %NULL to get only vertical coordiantes
4755  * @rect: rectangle to fill with cell background rect
4756  * 
4757  * Fills the bounding rectangle in tree window coordinates for the
4758  * cell at the row specified by @path and the column specified by
4759  * @column.  If @path is %NULL, the y and height fields of the
4760  * rectangle will be filled with 0. If @column is %NULL, the x and
4761  * width fields will be filled with 0.  The returned rectangle is
4762  * equivalent to the @background_area passed to
4763  * gtk_cell_renderer_render().  These background areas tile to cover
4764  * the entire tree window (except for the area used for header
4765  * buttons). Contrast with the cell_area, returned by
4766  * gtk_tree_view_get_cell_area(), which returns only the cell itself,
4767  * excluding surrounding borders and the tree expander area.
4768  * 
4769  **/
4770 void
4771 gtk_tree_view_get_background_area (GtkTreeView        *tree_view,
4772                                    GtkTreePath        *path,
4773                                    GtkTreeViewColumn  *column,
4774                                    GdkRectangle       *rect)
4775 {
4776   GtkRBTree *tree = NULL;
4777   GtkRBNode *node = NULL;
4778   
4779   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4780   g_return_if_fail (column == NULL || GTK_IS_TREE_VIEW_COLUMN (column));
4781   g_return_if_fail (rect != NULL);
4782
4783   rect->x = 0;
4784   rect->y = 0;
4785   rect->width = 0;
4786   rect->height = 0;
4787   
4788   if (path)
4789     {
4790       /* Get vertical coords */
4791       
4792       _gtk_tree_view_find_node (tree_view, path, &tree, &node);
4793       
4794       if (tree == NULL)
4795         {
4796           g_warning (G_STRLOC": no row corresponding to path");
4797           return;
4798         }
4799
4800       rect->y = BACKGROUND_FIRST_PIXEL (tree_view, tree, node);
4801
4802       rect->height = BACKGROUND_HEIGHT (node);
4803     }
4804
4805   if (column)
4806     {
4807       gint x2 = 0;
4808       
4809       gtk_tree_view_get_background_xrange (tree_view, tree, column, &rect->x, &x2);
4810       rect->width = x2 - rect->x;
4811     }
4812 }
4813
4814 static void
4815 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
4816                                  GtkRBNode  *node,
4817                                  gpointer  data)
4818 {
4819   GtkTreeView *tree_view = data;
4820
4821   if (node->children)
4822     _gtk_rbtree_traverse (node->children,
4823                           node->children->root,
4824                           G_PRE_ORDER,
4825                           gtk_tree_view_expand_all_helper,
4826                           data);
4827   else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
4828     {
4829       GtkTreePath *path;
4830       GtkTreeIter iter;
4831       GtkTreeIter child;
4832
4833       node->children = _gtk_rbtree_new ();
4834       node->children->parent_tree = tree;
4835       node->children->parent_node = node;
4836       path = _gtk_tree_view_find_path (tree_view, tree, node);
4837       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
4838       gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
4839       gtk_tree_view_build_tree (tree_view,
4840                                 node->children,
4841                                 &child,
4842                                 gtk_tree_path_get_depth (path) + 1,
4843                                 TRUE,
4844                                 GTK_WIDGET_REALIZED (tree_view));
4845       gtk_tree_path_free (path);
4846     }
4847 }
4848
4849 /**
4850  * gtk_tree_view_expand_all:
4851  * @tree_view: A #GtkTreeView.
4852  * 
4853  * Recursively expands all nodes in the @tree_view.
4854  **/
4855 void
4856 gtk_tree_view_expand_all (GtkTreeView *tree_view)
4857 {
4858   g_return_if_fail (tree_view != NULL);
4859   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4860   g_return_if_fail (tree_view->priv->tree != NULL);
4861
4862   _gtk_rbtree_traverse (tree_view->priv->tree,
4863                         tree_view->priv->tree->root,
4864                         G_PRE_ORDER,
4865                         gtk_tree_view_expand_all_helper,
4866                         tree_view);
4867
4868   _gtk_tree_view_update_size (tree_view);
4869 }
4870
4871 static void
4872 gtk_tree_view_collapse_all_helper (GtkRBTree  *tree,
4873                                    GtkRBNode  *node,
4874                                    gpointer    data)
4875 {
4876   if (node->children)
4877     {
4878       GtkTreePath *path;
4879       GtkTreeIter iter;
4880
4881       path = _gtk_tree_view_find_path (GTK_TREE_VIEW (data),
4882                                        node->children,
4883                                        node->children->root);
4884       gtk_tree_model_get_iter (GTK_TREE_VIEW (data)->priv->model,
4885                                &iter,
4886                                path);
4887       gtk_tree_view_discover_dirty (GTK_TREE_VIEW (data),
4888                                     node->children,
4889                                     &iter,
4890                                     gtk_tree_path_get_depth (path));
4891
4892       /* Ensure we don't have a dangling pointer to a dead node */
4893       ensure_unprelighted (GTK_TREE_VIEW (data));
4894       
4895       _gtk_rbtree_remove (node->children);
4896       gtk_tree_path_free (path);
4897     }
4898 }
4899
4900 /**
4901  * gtk_tree_view_collapse_all:
4902  * @tree_view: A #GtkTreeView.
4903  * 
4904  * Recursively collapses all visible, expanded nodes in @tree_view.
4905  **/
4906 void
4907 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
4908 {
4909   g_return_if_fail (tree_view != NULL);
4910   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
4911   g_return_if_fail (tree_view->priv->tree != NULL);
4912
4913   _gtk_rbtree_traverse (tree_view->priv->tree,
4914                         tree_view->priv->tree->root,
4915                         G_PRE_ORDER,
4916                         gtk_tree_view_collapse_all_helper,
4917                         tree_view);
4918
4919   if (GTK_WIDGET_MAPPED (tree_view))
4920     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4921 }
4922
4923 /* FIXME the bool return values for expand_row and collapse_row are
4924  * not analagous; they should be TRUE if the row had children and
4925  * was not already in the requested state.
4926  */
4927
4928 /**
4929  * gtk_tree_view_expand_row:
4930  * @tree_view: a #GtkTreeView
4931  * @path: path to a row
4932  * @open_all: whether to recursively expand, or just expand immediate children
4933  * 
4934  * Opens the row so its children are visible
4935  * 
4936  * Return value: %TRUE if the row existed and had children
4937  **/
4938 gboolean
4939 gtk_tree_view_expand_row (GtkTreeView *tree_view,
4940                           GtkTreePath *path,
4941                           gboolean     open_all)
4942 {
4943   GtkTreeIter iter;
4944   GtkTreeIter child;
4945   GtkRBTree *tree;
4946   GtkRBNode *node;
4947
4948   g_return_val_if_fail (tree_view != NULL, FALSE);
4949   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
4950   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
4951   g_return_val_if_fail (path != NULL, FALSE);
4952
4953   if (_gtk_tree_view_find_node (tree_view,
4954                                 path,
4955                                 &tree,
4956                                 &node))
4957     return FALSE;
4958   
4959   if (node->children)
4960     return TRUE;
4961   
4962   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
4963   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
4964     return FALSE;
4965   
4966   node->children = _gtk_rbtree_new ();
4967   node->children->parent_tree = tree;
4968   node->children->parent_node = node;
4969
4970   gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
4971   gtk_tree_view_build_tree (tree_view,
4972                             node->children,
4973                             &child,
4974                             gtk_tree_path_get_depth (path) + 1,
4975                             open_all,
4976                             GTK_WIDGET_REALIZED (tree_view));
4977
4978   if (GTK_WIDGET_MAPPED (tree_view))
4979     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
4980
4981   return TRUE;
4982 }
4983
4984 /**
4985  * gtk_tree_view_collapse_row:
4986  * @tree_view: a #GtkTreeView
4987  * @path: path to a row in the @tree_view
4988  * 
4989  * Collapses a row (hides its child rows).
4990  * 
4991  * Return value: %TRUE if the row was expanded
4992  **/
4993 gboolean
4994 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
4995                             GtkTreePath *path)
4996 {
4997   GtkRBTree *tree;
4998   GtkRBNode *node;
4999   GtkTreeIter iter;
5000
5001   g_return_val_if_fail (tree_view != NULL, FALSE);
5002   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
5003   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
5004   g_return_val_if_fail (path != NULL, FALSE);
5005
5006   if (_gtk_tree_view_find_node (tree_view,
5007                                 path,
5008                                 &tree,
5009                                 &node))
5010     return FALSE;
5011
5012   if (node->children == NULL)
5013     return FALSE;
5014
5015   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
5016   gtk_tree_view_discover_dirty (tree_view,
5017                                 node->children,
5018                                 &iter,
5019                                 gtk_tree_path_get_depth (path));
5020
5021   /* Ensure we don't have a dangling pointer to a dead node */
5022   ensure_unprelighted (tree_view);
5023   
5024   g_assert (tree_view->priv->prelight_node == NULL);
5025   
5026   _gtk_rbtree_remove (node->children);
5027
5028   if (GTK_WIDGET_MAPPED (tree_view))
5029     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
5030
5031   return TRUE;
5032 }
5033
5034 /**
5035  * gtk_tree_view_get_visible_rect:
5036  * @tree_view: a #GtkTreeView
5037  * @visible_rect: rectangle to fill
5038  *
5039  * Fills @visible_rect with the currently-visible region of the
5040  * buffer, in tree coordinates. Convert to widget coordinates with
5041  * gtk_tree_view_tree_to_widget_coords(). Tree coordinates start at
5042  * 0,0 for row 0 of the tree, and cover the entire scrollable area of
5043  * the tree.
5044  **/
5045 void
5046 gtk_tree_view_get_visible_rect (GtkTreeView  *tree_view,
5047                                 GdkRectangle *visible_rect)
5048 {
5049   GtkWidget *widget;
5050
5051   g_return_if_fail (tree_view != NULL);
5052   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5053
5054   widget = GTK_WIDGET (tree_view);
5055
5056   if (visible_rect)
5057     {
5058       visible_rect->x = tree_view->priv->hadjustment->value;
5059       visible_rect->y = tree_view->priv->vadjustment->value;
5060       visible_rect->width = widget->allocation.width;
5061       visible_rect->height = widget->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
5062     }
5063 }
5064
5065 /**
5066  * gtk_tree_view_widget_to_tree_coords:
5067  * @tree_view: a #GtkTreeView
5068  * @wx: widget X coordinate
5069  * @wy: widget Y coordinate
5070  * @tx: return location for tree X coordinate
5071  * @ty: return location for tree Y coordinate
5072  *
5073  * Converts widget coordinates to coordinates for the
5074  * tree window (the full scrollable area of the tree).
5075  * 
5076  **/
5077 void
5078 gtk_tree_view_widget_to_tree_coords (GtkTreeView *tree_view,
5079                                      gint         wx,
5080                                      gint         wy,
5081                                      gint        *tx,
5082                                      gint        *ty)
5083 {
5084   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5085   
5086   if (tx)
5087     {
5088       *tx = wx + tree_view->priv->hadjustment->value;
5089     }
5090
5091   if (ty)
5092     {
5093       *ty = wy + tree_view->priv->vadjustment->value;
5094     }
5095 }
5096
5097 /**
5098  * gtk_tree_view_tree_to_widget_coords:
5099  * @tree_view: a #GtkTreeView
5100  * @tx: tree X coordinate
5101  * @ty: tree Y coordinate
5102  * @wx: return location for widget X coordinate
5103  * @wy: return location for widget Y coordinate
5104  *
5105  * Converts tree coordinates (coordinates in full scrollable
5106  * area of the tree) to widget coordinates.
5107  * 
5108  **/
5109 void
5110 gtk_tree_view_tree_to_widget_coords (GtkTreeView *tree_view,
5111                                      gint         tx,
5112                                      gint         ty,
5113                                      gint        *wx,
5114                                      gint        *wy)
5115 {
5116   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5117
5118   if (wx)
5119     {
5120       *wx = tx - tree_view->priv->hadjustment->value;
5121     }
5122
5123   if (wy)
5124     {
5125       *wy = ty - tree_view->priv->vadjustment->value;
5126     }
5127 }
5128
5129 /**
5130  * gtk_tree_view_set_rules_hint
5131  * @tree_view: a #GtkTreeView
5132  * @setting: %TRUE if the tree requires reading across rows
5133  * 
5134  * This function tells GTK+ that the user interface for your
5135  * application requires users to read across tree rows and associate
5136  * cells with one another. By default, GTK+ will then render the tree
5137  * with alternating row colors. <emphasis>DO NOT</emphasis> use it
5138  * just because you prefer the appearance of the ruled tree; that's a
5139  * question for the theme. Some themes will draw tree rows in
5140  * alternating colors even when rules are turned off, and users who
5141  * prefer that appearance all the time can choose those themes. You
5142  * should call this function only as a <emphasis>semantic</emphasis>
5143  * hint to the theme engine that your tree makes alternating colors
5144  * useful from a functional standpoint (since it has lots of columns,
5145  * generally).
5146  * 
5147  **/
5148 void
5149 gtk_tree_view_set_rules_hint (GtkTreeView  *tree_view,
5150                               gboolean      setting)
5151 {
5152   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5153   
5154   setting = setting != FALSE;
5155
5156   if (tree_view->priv->has_rules != setting)
5157     {
5158       tree_view->priv->has_rules = setting;
5159       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
5160     }
5161
5162   g_object_notify (G_OBJECT (tree_view), "rules_hint");
5163 }
5164
5165 /**
5166  * gtk_tree_view_get_rules_hint
5167  * @tree_view: a #GtkTreeView
5168  * 
5169  * Gets the setting set by gtk_tree_view_set_rules_hint().
5170  * 
5171  * Return value: %TRUE if rules are useful for the user of this tree
5172  **/
5173 gboolean
5174 gtk_tree_view_get_rules_hint (GtkTreeView  *tree_view)
5175 {
5176   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
5177   
5178   return tree_view->priv->has_rules;
5179 }
5180
5181 /* Drag-and-drop */
5182
5183 static void
5184 set_source_row (GdkDragContext *context,
5185                 GtkTreeModel   *model,
5186                 GtkTreePath    *source_row)
5187 {
5188   g_object_set_data_full (G_OBJECT (context),
5189                           "gtk-tree-view-source-row",
5190                           source_row ? gtk_tree_row_reference_new (model, source_row) : NULL,
5191                           (GDestroyNotify) (source_row ? gtk_tree_row_reference_free : NULL));
5192 }
5193
5194 static GtkTreePath*
5195 get_source_row (GdkDragContext *context)
5196 {
5197   GtkTreeRowReference *ref =
5198     g_object_get_data (G_OBJECT (context), "gtk-tree-view-source-row");
5199
5200   if (ref)
5201     return gtk_tree_row_reference_get_path (ref);
5202   else
5203     return NULL;
5204 }
5205
5206
5207 static void
5208 set_dest_row (GdkDragContext *context,
5209               GtkTreeModel   *model,
5210               GtkTreePath    *dest_row)
5211 {
5212   g_object_set_data_full (G_OBJECT (context),
5213                           "gtk-tree-view-dest-row",
5214                           dest_row ? gtk_tree_row_reference_new (model, dest_row) : NULL,
5215                           (GDestroyNotify) (dest_row ? gtk_tree_row_reference_free : NULL));
5216 }
5217
5218 static GtkTreePath*
5219 get_dest_row (GdkDragContext *context)
5220 {
5221   GtkTreeRowReference *ref =
5222     g_object_get_data (G_OBJECT (context), "gtk-tree-view-dest-row");
5223
5224   if (ref)
5225     return gtk_tree_row_reference_get_path (ref);
5226   else
5227     return NULL;
5228 }
5229
5230 /* Get/set whether drag_motion requested the drag data and
5231  * drag_data_received should thus not actually insert the data,
5232  * since the data doesn't result from a drop.
5233  */
5234 static void
5235 set_status_pending (GdkDragContext *context,
5236                     GdkDragAction   suggested_action)
5237 {
5238   g_object_set_data (G_OBJECT (context),
5239                      "gtk-tree-view-status-pending",
5240                      GINT_TO_POINTER (suggested_action));
5241 }
5242
5243 static GdkDragAction
5244 get_status_pending (GdkDragContext *context)
5245 {
5246   return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
5247                                              "gtk-tree-view-status-pending"));
5248 }
5249
5250 typedef struct _TreeViewDragInfo TreeViewDragInfo;
5251
5252 struct _TreeViewDragInfo
5253 {
5254   GdkModifierType start_button_mask;
5255   GtkTargetList *source_target_list;
5256   GdkDragAction source_actions;
5257   GClosure *row_draggable_closure;
5258
5259   GtkTargetList *dest_target_list;
5260   GClosure *location_droppable_closure;
5261   
5262   guint source_set : 1;
5263   guint dest_set : 1;
5264 };
5265
5266 static TreeViewDragInfo*
5267 get_info (GtkTreeView *tree_view)
5268 {
5269   return g_object_get_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info");
5270 }
5271
5272 static void
5273 clear_source_info (TreeViewDragInfo *di)
5274 {
5275   if (di->source_target_list)
5276     gtk_target_list_unref (di->source_target_list);
5277
5278   if (di->row_draggable_closure)
5279     g_closure_unref (di->row_draggable_closure);
5280   
5281   di->source_target_list = NULL;
5282   di->row_draggable_closure = NULL;
5283 }
5284
5285 static void
5286 clear_dest_info (TreeViewDragInfo *di)
5287 {
5288   if (di->location_droppable_closure)
5289     g_closure_unref (di->location_droppable_closure);
5290
5291   if (di->dest_target_list)
5292     gtk_target_list_unref (di->dest_target_list);
5293   
5294   di->location_droppable_closure = NULL;
5295   di->dest_target_list = NULL;
5296 }
5297
5298 static void
5299 destroy_info (TreeViewDragInfo *di)
5300 {
5301   clear_source_info (di);
5302   clear_dest_info (di);
5303   g_free (di);
5304 }
5305
5306 static TreeViewDragInfo*
5307 ensure_info (GtkTreeView *tree_view)
5308 {
5309   TreeViewDragInfo *di;
5310
5311   di = get_info (tree_view);
5312
5313   if (di == NULL)
5314     {
5315       di = g_new0 (TreeViewDragInfo, 1);
5316       
5317       g_object_set_data_full (G_OBJECT (tree_view),
5318                               "gtk-tree-view-drag-info",
5319                               di,
5320                               (GDestroyNotify) destroy_info);
5321     }
5322
5323   return di;
5324 }
5325
5326 static void
5327 remove_info (GtkTreeView *tree_view)
5328 {
5329   g_object_set_data (G_OBJECT (tree_view), "gtk-tree-view-drag-info", NULL);
5330 }
5331
5332 #define SCROLL_EDGE_SIZE 15
5333
5334 static gint
5335 drag_scan_timeout (gpointer data)
5336 {
5337   GtkTreeView *tree_view;
5338   gint x, y;
5339   GdkModifierType state;
5340   GtkTreePath *path = NULL;
5341   GtkTreeViewColumn *column = NULL;
5342   GdkRectangle visible_rect;
5343   
5344   tree_view = GTK_TREE_VIEW (data);
5345
5346   gdk_window_get_pointer (tree_view->priv->bin_window,
5347                           &x, &y, &state);  
5348
5349   gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
5350
5351   /* See if we are near the edge. */
5352   if ((x - visible_rect.x) < SCROLL_EDGE_SIZE ||
5353       (visible_rect.x + visible_rect.width - x) < SCROLL_EDGE_SIZE ||
5354       (y - visible_rect.y) < SCROLL_EDGE_SIZE ||
5355       (visible_rect.y + visible_rect.height - y) < SCROLL_EDGE_SIZE)
5356     {
5357       gtk_tree_view_get_path_at_pos (tree_view,
5358                                      tree_view->priv->bin_window,
5359                                      x, y,
5360                                      &path,
5361                                      &column,
5362                                      NULL,
5363                                      NULL);
5364       
5365       if (path != NULL)
5366         {
5367           gtk_tree_view_scroll_to_cell (tree_view,
5368                                         path,
5369                                         column,
5370                                         0.5, 0.5); 
5371           
5372           gtk_tree_path_free (path);
5373         }
5374     }
5375   
5376   return TRUE;
5377 }
5378
5379
5380 static void
5381 ensure_scroll_timeout (GtkTreeView *tree_view)
5382 {
5383   if (tree_view->priv->scroll_timeout == 0)
5384     tree_view->priv->scroll_timeout = gtk_timeout_add (50, drag_scan_timeout, tree_view);
5385 }
5386
5387 static void
5388 remove_scroll_timeout (GtkTreeView *tree_view)
5389 {
5390   if (tree_view->priv->scroll_timeout != 0)
5391     {
5392       gtk_timeout_remove (tree_view->priv->scroll_timeout);
5393       tree_view->priv->scroll_timeout = 0;
5394     }
5395 }
5396
5397 void
5398 gtk_tree_view_set_rows_drag_source (GtkTreeView              *tree_view,
5399                                     GdkModifierType           start_button_mask,
5400                                     const GtkTargetEntry     *targets,
5401                                     gint                      n_targets,
5402                                     GdkDragAction             actions,
5403                                     GtkTreeViewDraggableFunc  row_draggable_func,
5404                                     gpointer                  user_data)
5405 {
5406   TreeViewDragInfo *di;
5407
5408   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5409   
5410   di = ensure_info (tree_view);
5411   clear_source_info (di);
5412
5413   di->start_button_mask = start_button_mask;
5414   di->source_target_list = gtk_target_list_new (targets, n_targets);
5415   di->source_actions = actions;
5416
5417   if (row_draggable_func)
5418     {
5419       di->row_draggable_closure = g_cclosure_new ((GCallback) row_draggable_func,
5420                                                   user_data, NULL);
5421       g_closure_ref (di->row_draggable_closure);
5422       g_closure_sink (di->row_draggable_closure);
5423     }
5424
5425   di->source_set = TRUE;
5426 }
5427
5428 void
5429 gtk_tree_view_set_rows_drag_dest (GtkTreeView              *tree_view,
5430                                   const GtkTargetEntry     *targets,
5431                                   gint                      n_targets,
5432                                   GdkDragAction             actions,
5433                                   GtkTreeViewDroppableFunc  location_droppable_func,
5434                                   gpointer                  user_data)
5435 {
5436   TreeViewDragInfo *di;
5437   
5438   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5439
5440   gtk_drag_dest_set (GTK_WIDGET (tree_view),
5441                      0,
5442                      NULL,
5443                      0,
5444                      actions);
5445   
5446   di = ensure_info (tree_view);
5447   clear_dest_info (di);  
5448
5449   if (targets)
5450     di->dest_target_list = gtk_target_list_new (targets, n_targets);
5451
5452   if (location_droppable_func)
5453     {
5454       di->location_droppable_closure = g_cclosure_new ((GCallback) location_droppable_func,
5455                                                        user_data, NULL);
5456       g_closure_ref (di->location_droppable_closure);
5457       g_closure_sink (di->location_droppable_closure);
5458     }
5459   
5460   di->dest_set = TRUE;
5461 }
5462
5463 void
5464 gtk_tree_view_unset_rows_drag_source (GtkTreeView *tree_view)
5465 {
5466   TreeViewDragInfo *di;
5467   
5468   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5469   
5470   di = get_info (tree_view);
5471
5472   if (di)
5473     {
5474       if (di->source_set)
5475         {
5476           clear_source_info (di);
5477           di->source_set = FALSE;
5478         }
5479
5480       if (!di->dest_set && !di->source_set)
5481         remove_info (tree_view);
5482     }
5483 }
5484
5485 void
5486 gtk_tree_view_unset_rows_drag_dest (GtkTreeView *tree_view)
5487 {
5488   TreeViewDragInfo *di;
5489   
5490   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5491   
5492   di = get_info (tree_view);
5493
5494   if (di)
5495     {
5496       if (di->dest_set)
5497         {
5498           gtk_drag_dest_unset (GTK_WIDGET (tree_view));
5499           clear_dest_info (di);
5500           di->dest_set = FALSE;
5501         }
5502
5503       if (!di->dest_set && !di->source_set)
5504         remove_info (tree_view);
5505     }
5506 }
5507
5508 void
5509 gtk_tree_view_set_drag_dest_row (GtkTreeView            *tree_view,
5510                                  GtkTreePath            *path,
5511                                  GtkTreeViewDropPosition pos)
5512 {
5513   GtkTreePath *current_dest;
5514   /* Note; this function is exported to allow a custom DND
5515    * implementation, so it can't touch TreeViewDragInfo
5516    */
5517   
5518   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5519
5520   current_dest = NULL;
5521   
5522   if (tree_view->priv->drag_dest_row)
5523     current_dest = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
5524
5525   if (current_dest)
5526     {
5527       gtk_tree_view_queue_draw_path (tree_view, current_dest, NULL);
5528       gtk_tree_path_free (current_dest);
5529     }
5530
5531   if (tree_view->priv->drag_dest_row)
5532     gtk_tree_row_reference_free (tree_view->priv->drag_dest_row);
5533
5534   tree_view->priv->drag_dest_pos = pos;
5535   
5536   if (path)
5537     {
5538       tree_view->priv->drag_dest_row =
5539         gtk_tree_row_reference_new_proxy (G_OBJECT (tree_view), tree_view->priv->model, path);
5540       gtk_tree_view_queue_draw_path (tree_view, path, NULL);
5541     }
5542   else
5543     tree_view->priv->drag_dest_row = NULL;
5544 }
5545
5546 void
5547 gtk_tree_view_get_drag_dest_row (GtkTreeView              *tree_view,
5548                                  GtkTreePath             **path,
5549                                  GtkTreeViewDropPosition  *pos)
5550 {
5551   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
5552   
5553   if (path)
5554     {
5555       if (tree_view->priv->drag_dest_row)
5556         *path = gtk_tree_row_reference_get_path (tree_view->priv->drag_dest_row);
5557       else
5558         *path = NULL;
5559     }
5560
5561   if (pos)
5562     *pos = tree_view->priv->drag_dest_pos;
5563 }
5564
5565 gboolean
5566 gtk_tree_view_get_dest_row_at_pos (GtkTreeView             *tree_view,
5567                                    gint                     drag_x,
5568                                    gint                     drag_y,
5569                                    GtkTreePath            **path,
5570                                    GtkTreeViewDropPosition *pos)
5571 {
5572   gint cell_y;
5573   gdouble offset_into_row;
5574   gdouble quarter;
5575   gint x, y;
5576   GdkRectangle cell;
5577   GtkTreeViewColumn *column = NULL;
5578   GtkTreePath *tmp_path = NULL;
5579   
5580   /* Note; this function is exported to allow a custom DND
5581    * implementation, so it can't touch TreeViewDragInfo
5582    */
5583   
5584   g_return_val_if_fail (tree_view != NULL, FALSE);
5585   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
5586   g_return_val_if_fail (drag_x >= 0, FALSE);
5587   g_return_val_if_fail (drag_y >= 0, FALSE);
5588   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
5589
5590   if (path)
5591     *path = NULL;
5592
5593   /* remember that drag_x and drag_y are in widget coords, convert to tree window */
5594
5595   gtk_tree_view_widget_to_tree_coords (tree_view, drag_x, drag_y,
5596                                        &x, &y);
5597   
5598   /* If in the top quarter of a row, we drop before that row; if
5599    * in the bottom quarter, drop after that row; if in the middle,
5600    * and the row has children, drop into the row.
5601    */
5602
5603   if (!gtk_tree_view_get_path_at_pos (tree_view,
5604                                       tree_view->priv->bin_window,
5605                                       x, y,
5606                                       &tmp_path,
5607                                       &column,
5608                                       NULL,
5609                                       &cell_y))
5610     return FALSE;  
5611
5612   gtk_tree_view_get_background_area (tree_view, tmp_path, column,
5613                                      &cell);
5614
5615   offset_into_row = cell_y;
5616   
5617   if (path)
5618     *path = tmp_path;
5619   else
5620     gtk_tree_path_free (tmp_path);
5621
5622   tmp_path = NULL;
5623   
5624   quarter = cell.height / 4.0;
5625   
5626   if (pos)
5627     {
5628       if (offset_into_row < quarter)
5629         {
5630           *pos = GTK_TREE_VIEW_DROP_BEFORE;          
5631         }
5632       else if (offset_into_row < quarter * 2)
5633         {
5634           *pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
5635         }
5636       else if (offset_into_row < quarter * 3)
5637         {
5638           *pos = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
5639         }
5640       else
5641         {
5642           *pos = GTK_TREE_VIEW_DROP_AFTER;
5643         }
5644     }
5645
5646   return TRUE;
5647 }
5648
5649 static gboolean
5650 gtk_tree_view_maybe_begin_dragging_row (GtkTreeView      *tree_view,
5651                                         GdkEventMotion   *event)
5652 {
5653   GdkDragContext *context;
5654   TreeViewDragInfo *di;
5655   GtkTreePath *path = NULL;
5656   gint button;
5657   gint cell_x, cell_y;
5658   GtkTreeModel *model;
5659   
5660   di = get_info (tree_view);
5661
5662   if (di == NULL)
5663     return FALSE;
5664
5665   if (tree_view->priv->pressed_button < 0)
5666     return FALSE;
5667   
5668   if (!gtk_drag_check_threshold (GTK_WIDGET (tree_view),
5669                                  tree_view->priv->press_start_x,
5670                                  tree_view->priv->press_start_y,
5671                                  event->x, event->y))
5672     return FALSE;
5673
5674   model = gtk_tree_view_get_model (tree_view);
5675
5676   if (model == NULL)
5677     return FALSE;
5678   
5679   button = tree_view->priv->pressed_button;
5680   tree_view->priv->pressed_button = -1;
5681
5682   gtk_tree_view_get_path_at_pos (tree_view,
5683                                  tree_view->priv->bin_window,
5684                                  tree_view->priv->press_start_x,
5685                                  tree_view->priv->press_start_y,
5686                                  &path,
5687                                  NULL,
5688                                  &cell_x,
5689                                  &cell_y);
5690
5691   if (path == NULL)
5692     return FALSE;
5693   
5694   /* FIXME if the path doesn't match the row_draggable predicate,
5695    * return FALSE and free path
5696    */  
5697
5698   /* FIXME Check whether we're a start button, if not return FALSE and
5699    * free path
5700    */
5701   
5702   context = gtk_drag_begin (GTK_WIDGET (tree_view),
5703                             di->source_target_list,
5704                             di->source_actions,
5705                             button,
5706                             (GdkEvent*)event);
5707
5708   gtk_drag_set_icon_default (context);
5709
5710   {
5711     GdkPixmap *row_pix;
5712
5713     row_pix = gtk_tree_view_create_row_drag_icon (tree_view,
5714                                                   path);
5715
5716     gtk_drag_set_icon_pixmap (context,
5717                               gdk_drawable_get_colormap (row_pix),
5718                               row_pix,
5719                               NULL,
5720                               /* the + 1 is for the black border in the icon */
5721                               tree_view->priv->press_start_x + 1,
5722                               cell_y + 1);
5723
5724     gdk_pixmap_unref (row_pix);
5725   }
5726   
5727   set_source_row (context, model, path);
5728   gtk_tree_path_free (path);
5729   
5730   return TRUE;
5731 }
5732
5733 /* Default signal implementations for the drag signals */
5734
5735 static void
5736 gtk_tree_view_drag_begin (GtkWidget      *widget,
5737                           GdkDragContext *context)
5738 {
5739   /* do nothing */
5740 }
5741
5742 static void
5743 gtk_tree_view_drag_end (GtkWidget      *widget,
5744                         GdkDragContext *context)
5745 {
5746   /* do nothing */
5747 }
5748
5749 static void
5750 gtk_tree_view_drag_data_get (GtkWidget        *widget,
5751                              GdkDragContext   *context,
5752                              GtkSelectionData *selection_data,
5753                              guint             info,
5754                              guint             time)
5755 {
5756   GtkTreeView *tree_view;
5757   GtkTreeModel *model;
5758   TreeViewDragInfo *di;
5759   GtkTreePath *source_row;
5760   
5761   tree_view = GTK_TREE_VIEW (widget);
5762
5763   model = gtk_tree_view_get_model (tree_view);
5764
5765   if (model == NULL)
5766     return;
5767
5768   di = get_info (GTK_TREE_VIEW (widget));
5769   
5770   if (di == NULL)    
5771     return;
5772
5773   source_row = get_source_row (context);
5774
5775   if (source_row == NULL)
5776     return;
5777   
5778   /* We can implement the GTK_TREE_MODEL_ROW target generically for
5779    * any model; for DragSource models there are some other targets
5780    * we also support.
5781    */
5782
5783   if (GTK_IS_TREE_DRAG_SOURCE (model) &&
5784       gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
5785                                           source_row,
5786                                           selection_data))
5787     goto done;
5788
5789   /* If drag_data_get does nothing, try providing row data. */
5790   if (selection_data->target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
5791     {
5792       gtk_selection_data_set_tree_row (selection_data,
5793                                        model,
5794                                        source_row);
5795     }
5796
5797  done:
5798   gtk_tree_path_free (source_row);
5799 }
5800
5801
5802 static gboolean
5803 check_model_dnd (GtkTreeModel *model,
5804                  GType         required_iface,
5805                  const gchar  *signal)
5806 {
5807   if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
5808     {
5809       g_warning ("You must override the default '%s' handler "
5810                  "on GtkTreeView when using models that don't support "
5811                  "the %s interface and enabling drag-and-drop. The simplest way to do this "
5812                  "is to connect to '%s' and call "
5813                  "gtk_signal_emit_stop_by_name() in your signal handler to prevent "
5814                  "the default handler from running. Look at the source code "
5815                  "for the default handler in gtktreeview.c to get an idea what "
5816                  "your handler should do. (gtktreeview.c is in the GTK source "
5817                  "code.) If you're using GTK from a language other than C, "
5818                  "there may be a more natural way to override default handlers, e.g. via derivation.",
5819                  signal, g_type_name (required_iface), signal);
5820       return FALSE;
5821     }
5822   else
5823     return TRUE;
5824 }
5825
5826 static void
5827 gtk_tree_view_drag_data_delete (GtkWidget      *widget,
5828                                 GdkDragContext *context)
5829 {
5830   TreeViewDragInfo *di;
5831   GtkTreeModel *model;
5832   GtkTreeView *tree_view;
5833   GtkTreePath *source_row;
5834   
5835   tree_view = GTK_TREE_VIEW (widget);
5836   model = gtk_tree_view_get_model (tree_view);
5837   
5838   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag_data_delete"))
5839     return;
5840   
5841   di = get_info (tree_view);
5842
5843   if (di == NULL)
5844     return;
5845
5846   source_row = get_source_row (context);
5847   
5848   if (source_row == NULL)
5849     return;
5850   
5851   gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
5852                                          source_row);
5853
5854   gtk_tree_path_free (source_row);
5855   
5856   set_source_row (context, NULL, NULL);
5857 }
5858
5859 static void
5860 remove_open_timeout (GtkTreeView *tree_view)
5861 {
5862   if (tree_view->priv->open_dest_timeout != 0)
5863     {
5864       gtk_timeout_remove (tree_view->priv->open_dest_timeout);
5865       tree_view->priv->open_dest_timeout = 0;
5866     }
5867 }
5868
5869 static void
5870 gtk_tree_view_drag_leave (GtkWidget      *widget,
5871                           GdkDragContext *context,
5872                           guint             time)
5873 {
5874   TreeViewDragInfo *di;
5875   
5876   di = get_info (GTK_TREE_VIEW (widget));
5877   
5878   /* unset any highlight row */
5879   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5880                                    NULL,
5881                                    GTK_TREE_VIEW_DROP_BEFORE);
5882   
5883   remove_scroll_timeout (GTK_TREE_VIEW (widget));
5884   remove_open_timeout (GTK_TREE_VIEW (widget));
5885 }
5886
5887 static gint
5888 open_row_timeout (gpointer data)
5889 {
5890   GtkTreeView *tree_view = data;
5891   GtkTreePath *dest_path = NULL;
5892   GtkTreeViewDropPosition pos;
5893
5894   gtk_tree_view_get_drag_dest_row (tree_view,
5895                                    &dest_path,
5896                                    &pos);
5897   
5898   if (dest_path && 
5899       (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
5900        pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
5901     {
5902       gtk_tree_view_expand_row (tree_view,
5903                                 dest_path,
5904                                 FALSE);
5905       tree_view->priv->open_dest_timeout = 0;
5906
5907       gtk_tree_path_free (dest_path);
5908       
5909       return FALSE;
5910     }  
5911   else
5912     {
5913       if (dest_path)
5914         gtk_tree_path_free (dest_path);
5915       return TRUE;
5916     }
5917 }
5918
5919 /* Returns TRUE if event should not be propagated to parent widgets */
5920 static gboolean
5921 set_destination_row (GtkTreeView    *tree_view,
5922                      GdkDragContext *context,
5923                      gint            x,
5924                      gint            y,
5925                      GdkDragAction  *suggested_action,
5926                      GdkAtom        *target)
5927 {
5928   GtkTreePath *path = NULL;
5929   GtkTreeViewDropPosition pos;
5930   GtkTreeViewDropPosition old_pos;
5931   TreeViewDragInfo *di;
5932   GtkWidget *widget;
5933   GtkTreePath *old_dest_path = NULL;
5934   
5935   *suggested_action = 0;
5936   *target = GDK_NONE;
5937   
5938   widget = GTK_WIDGET (tree_view);
5939   
5940   di = get_info (tree_view);
5941   
5942   if (di == NULL)
5943     {
5944       /* someone unset us as a drag dest, note that if
5945        * we return FALSE drag_leave isn't called
5946        */
5947
5948       gtk_tree_view_set_drag_dest_row (tree_view,
5949                                        NULL,
5950                                        GTK_TREE_VIEW_DROP_BEFORE);
5951
5952       remove_scroll_timeout (GTK_TREE_VIEW (widget));
5953       remove_open_timeout (GTK_TREE_VIEW (widget));
5954       
5955       return FALSE; /* no longer a drop site */
5956     }
5957
5958   *target = gtk_drag_dest_find_target (widget, context, di->dest_target_list);
5959   if (*target == GDK_NONE)
5960     {
5961       return FALSE;
5962     }
5963   
5964   if (!gtk_tree_view_get_dest_row_at_pos (tree_view,
5965                                           x, y,
5966                                           &path,
5967                                           &pos))
5968     {
5969       /* can't drop here */
5970       remove_open_timeout (tree_view);
5971
5972       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
5973                                        NULL,
5974                                        GTK_TREE_VIEW_DROP_BEFORE);
5975
5976       /* don't propagate to parent though */
5977       return TRUE;
5978     }
5979   
5980   g_assert (path);
5981
5982   /* If we left the current row's "open" zone, unset the timeout for
5983    * opening the row
5984    */
5985   gtk_tree_view_get_drag_dest_row (tree_view,
5986                                    &old_dest_path,
5987                                    &old_pos);
5988   
5989   if (old_dest_path &&
5990       (gtk_tree_path_compare (path, old_dest_path) != 0 ||
5991        !(pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
5992          pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
5993     remove_open_timeout (tree_view);
5994
5995   if (old_dest_path)
5996     gtk_tree_path_free (old_dest_path);
5997   
5998   if (TRUE /* FIXME if the location droppable predicate */)
5999     {
6000       GtkWidget *source_widget;
6001       
6002       *suggested_action = context->suggested_action;
6003       
6004       source_widget = gtk_drag_get_source_widget (context);
6005       
6006       if (source_widget == widget)
6007         {
6008           /* Default to MOVE, unless the user has
6009            * pressed ctrl or alt to affect available actions
6010            */
6011           if ((context->actions & GDK_ACTION_MOVE) != 0)
6012             *suggested_action = GDK_ACTION_MOVE;
6013         }
6014
6015       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
6016                                        path, pos);
6017     }
6018   else
6019     {
6020       /* can't drop here */
6021       remove_open_timeout (tree_view);
6022       
6023       gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
6024                                        NULL,
6025                                        GTK_TREE_VIEW_DROP_BEFORE);
6026     }
6027
6028   return TRUE;
6029 }
6030
6031 static gboolean
6032 gtk_tree_view_drag_motion (GtkWidget        *widget,
6033                            GdkDragContext   *context,
6034                            gint              x,
6035                            gint              y,
6036                            guint             time)
6037 {
6038   GtkTreePath *path = NULL;
6039   GtkTreeViewDropPosition pos;
6040   GtkTreeView *tree_view;
6041   GdkDragAction suggested_action = 0;
6042   GdkAtom target;
6043   
6044   tree_view = GTK_TREE_VIEW (widget);
6045   
6046   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
6047     return FALSE;
6048
6049   ensure_scroll_timeout (tree_view);
6050   
6051   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
6052
6053   if (path == NULL)
6054     {
6055       /* Can't drop here. */
6056       gdk_drag_status (context, 0, time);
6057     }
6058   else
6059     {
6060       if (tree_view->priv->open_dest_timeout == 0 &&
6061           (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
6062            pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE))
6063         {
6064           tree_view->priv->open_dest_timeout =
6065             gtk_timeout_add (500, open_row_timeout, tree_view);      
6066         }
6067
6068       if (target == gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
6069         {
6070           /* Request data so we can use the source row when
6071            * determining whether to accept the drop
6072            */
6073           set_status_pending (context, suggested_action);
6074           gtk_drag_get_data (widget, context, target, time);
6075         }
6076       else
6077         {
6078           set_status_pending (context, 0);
6079           gdk_drag_status (context, suggested_action, time);
6080         }
6081     }
6082
6083   if (path)
6084     gtk_tree_path_free (path);
6085
6086   return TRUE;
6087 }
6088
6089 static GtkTreePath*
6090 get_logical_dest_row (GtkTreeView *tree_view)
6091
6092 {
6093   /* adjust path to point to the row the drop goes in front of */
6094   GtkTreePath *path = NULL;
6095   GtkTreeViewDropPosition pos;
6096
6097   gtk_tree_view_get_drag_dest_row (tree_view, &path, &pos);
6098
6099   if (path == NULL)
6100     return NULL;
6101   
6102   if (pos == GTK_TREE_VIEW_DROP_BEFORE)
6103     ; /* do nothing */
6104   else if (pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE ||
6105            pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
6106     {
6107       /* get first child, drop before it */
6108       gtk_tree_path_append_index (path, 0);
6109     }
6110   else
6111     {
6112       g_assert (pos == GTK_TREE_VIEW_DROP_AFTER);
6113       gtk_tree_path_next (path);
6114     }
6115
6116   return path;
6117 }
6118
6119 static gboolean
6120 gtk_tree_view_drag_drop (GtkWidget        *widget,
6121                          GdkDragContext   *context,
6122                          gint              x,
6123                          gint              y,
6124                          guint             time)
6125 {
6126   GtkTreeView *tree_view;
6127   GtkTreePath *path;
6128   GdkDragAction suggested_action = 0;
6129   GdkAtom target = GDK_NONE;
6130   TreeViewDragInfo *di;
6131   GtkTreeModel *model;
6132   
6133   tree_view = GTK_TREE_VIEW (widget);
6134
6135   model = gtk_tree_view_get_model (tree_view);
6136   
6137   remove_scroll_timeout (GTK_TREE_VIEW (widget));
6138   remove_open_timeout (GTK_TREE_VIEW (widget));
6139   
6140   di = get_info (tree_view);  
6141   
6142   if (di == NULL)
6143     return FALSE;
6144   
6145   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_drop"))
6146     return FALSE;
6147   
6148   if (!set_destination_row (tree_view, context, x, y, &suggested_action, &target))
6149     return FALSE;
6150
6151   path = get_logical_dest_row (tree_view);
6152
6153   if (target != GDK_NONE && path != NULL)
6154     {
6155       /* in case a motion had requested drag data, change things so we
6156        * treat drag data receives as a drop.
6157        */
6158       set_status_pending (context, 0);
6159       
6160       set_dest_row (context, model, path);
6161     }
6162
6163   if (path)
6164     gtk_tree_path_free (path);
6165   
6166   /* Unset this thing */
6167   gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
6168                                    NULL,
6169                                    GTK_TREE_VIEW_DROP_BEFORE);
6170   
6171   if (target != GDK_NONE)
6172     {
6173       gtk_drag_get_data (widget, context, target, time);
6174       return TRUE;
6175     }
6176   else
6177     return FALSE;
6178 }
6179
6180 static void
6181 gtk_tree_view_drag_data_received (GtkWidget        *widget,
6182                                   GdkDragContext   *context,
6183                                   gint              x,
6184                                   gint              y,
6185                                   GtkSelectionData *selection_data,
6186                                   guint             info,
6187                                   guint             time)
6188 {
6189   GtkTreePath *path;
6190   TreeViewDragInfo *di;
6191   gboolean accepted = FALSE;
6192   GtkTreeModel *model;
6193   GtkTreeView *tree_view;
6194   GtkTreePath *dest_row;
6195   GdkDragAction suggested_action;
6196   
6197   tree_view = GTK_TREE_VIEW (widget);
6198
6199   model = gtk_tree_view_get_model (tree_view);
6200
6201   if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag_data_received"))
6202     return;  
6203   
6204   di = get_info (tree_view);
6205
6206   if (di == NULL)
6207     return;
6208
6209   suggested_action = get_status_pending (context);
6210
6211   if (suggested_action)
6212     {
6213       /* We are getting this data due to a request in drag_motion,
6214        * rather than due to a request in drag_drop, so we are just
6215        * supposed to call drag_status, not actually paste in the
6216        * data.
6217        */
6218       path = get_logical_dest_row (tree_view);
6219
6220       if (path == NULL)
6221         suggested_action = 0;
6222
6223       if (suggested_action)
6224         {
6225           GtkTreeModel *src_model = NULL;
6226           GtkTreePath *src_path = NULL;
6227           
6228           if (!gtk_selection_data_get_tree_row (selection_data,
6229                                                 &src_model,
6230                                                 &src_path))
6231             suggested_action = 0;
6232
6233           if (suggested_action)
6234             {
6235               if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
6236                                                          src_model,
6237                                                          src_path,
6238                                                          path))
6239                 suggested_action = 0;
6240
6241               gtk_tree_path_free (src_path);
6242             }
6243         }
6244       
6245       gdk_drag_status (context, suggested_action, time);
6246
6247       if (path)
6248         gtk_tree_path_free (path);
6249
6250       /* If you can't drop, remove user drop indicator until the next motion */
6251       if (suggested_action == 0)
6252         gtk_tree_view_set_drag_dest_row (GTK_TREE_VIEW (widget),
6253                                          NULL,
6254                                          GTK_TREE_VIEW_DROP_BEFORE);
6255       
6256       return;
6257     }
6258   
6259   dest_row = get_dest_row (context);
6260
6261   if (dest_row == NULL)
6262     return;
6263   
6264   if (selection_data->length >= 0)
6265     {
6266       if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
6267                                                  dest_row,
6268                                                  selection_data))
6269         accepted = TRUE;
6270     }
6271   
6272   gtk_drag_finish (context, 
6273                    accepted,
6274                    (context->action == GDK_ACTION_MOVE),
6275                    time);
6276
6277   gtk_tree_path_free (dest_row);
6278
6279   /* drop dest_row */
6280   set_dest_row (context, NULL, NULL);
6281 }