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