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