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