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