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