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