]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeview.c
handle case where there are no rows in the model
[~andy/gtk] / gtk / gtktreeview.c
1 /* gtktreeview.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20
21 #include "gtktreeview.h"
22 #include "gtkrbtree.h"
23 #include "gtktreeprivate.h"
24 #include "gtkcellrenderer.h"
25 #include "gtksignal.h"
26 #include "gtkmain.h"
27 #include "gtkbutton.h"
28 #include "gtkalignment.h"
29 #include "gtklabel.h"
30
31 #include <gdk/gdkkeysyms.h>
32
33
34 /* the width of the column resize windows */
35 #define TREE_VIEW_DRAG_WIDTH 6
36 #define TREE_VIEW_EXPANDER_WIDTH 14
37 #define TREE_VIEW_EXPANDER_HEIGHT 14
38 #define TREE_VIEW_VERTICAL_SEPARATOR 2
39 #define TREE_VIEW_HORIZONTAL_SEPARATOR 0
40
41
42 typedef struct _GtkTreeViewChild GtkTreeViewChild;
43
44 struct _GtkTreeViewChild
45 {
46   GtkWidget *widget;
47   gint x;
48   gint y;
49 };
50
51
52 static void     gtk_tree_view_init                 (GtkTreeView      *tree_view);
53 static void     gtk_tree_view_class_init           (GtkTreeViewClass *klass);
54
55 /* widget signals */
56 static void     gtk_tree_view_setup_model          (GtkTreeView      *tree_view);
57 static void     gtk_tree_view_realize              (GtkWidget        *widget);
58 static void     gtk_tree_view_unrealize            (GtkWidget        *widget);
59 static void     gtk_tree_view_map                  (GtkWidget        *widget);
60 static void     gtk_tree_view_size_request         (GtkWidget        *widget,
61                                                     GtkRequisition   *requisition);
62 static void     gtk_tree_view_size_allocate        (GtkWidget        *widget,
63                                                     GtkAllocation    *allocation);
64 static gboolean gtk_tree_view_expose               (GtkWidget        *widget,
65                                                     GdkEventExpose   *event);
66 static gboolean gtk_tree_view_motion               (GtkWidget        *widget,
67                                                     GdkEventMotion   *event);
68 static gboolean gtk_tree_view_enter_notify         (GtkWidget        *widget,
69                                                     GdkEventCrossing *event);
70 static gboolean gtk_tree_view_leave_notify         (GtkWidget        *widget,
71                                                     GdkEventCrossing *event);
72 static gboolean gtk_tree_view_button_press         (GtkWidget        *widget,
73                                                     GdkEventButton   *event);
74 static gboolean gtk_tree_view_button_release       (GtkWidget        *widget,
75                                                     GdkEventButton   *event);
76 static void     gtk_tree_view_draw_focus           (GtkWidget        *widget);
77 static gint     gtk_tree_view_focus_in             (GtkWidget        *widget,
78                                                     GdkEventFocus    *event);
79 static gint     gtk_tree_view_focus_out            (GtkWidget        *widget,
80                                                     GdkEventFocus    *event);
81 static gint     gtk_tree_view_focus                (GtkContainer     *container,
82                                                     GtkDirectionType  direction);
83
84 /* container signals */
85 static void     gtk_tree_view_remove               (GtkContainer     *container,
86                                                     GtkWidget        *widget);
87 static void     gtk_tree_view_forall               (GtkContainer     *container,
88                                                     gboolean          include_internals,
89                                                     GtkCallback       callback,
90                                                     gpointer          callback_data);
91
92 /* tree_model signals */
93 static void     gtk_tree_view_set_adjustments      (GtkTreeView      *tree_view,
94                                                     GtkAdjustment    *hadj,
95                                                     GtkAdjustment    *vadj);
96 static void     gtk_tree_view_changed              (GtkTreeModel     *model,
97                                                     GtkTreePath      *path,
98                                                     GtkTreeIter      *iter,
99                                                     gpointer          data);
100 static void     gtk_tree_view_inserted             (GtkTreeModel     *model,
101                                                     GtkTreePath      *path,
102                                                     GtkTreeIter      *iter,
103                                                     gpointer          data);
104 static void     gtk_tree_view_child_toggled        (GtkTreeModel     *model,
105                                                     GtkTreePath      *path,
106                                                     GtkTreeIter      *iter,
107                                                     gpointer          data);
108 static void     gtk_tree_view_deleted              (GtkTreeModel     *model,
109                                                     GtkTreePath      *path,
110                                                     gpointer          data);
111
112 /* Internal functions */
113 static void     gtk_tree_view_draw_arrow           (GtkTreeView      *tree_view,
114                                                     GtkRBNode        *node,
115                                                     gint              offset,
116                                                     gint              x,
117                                                     gint              y);
118 static gint     gtk_tree_view_new_column_width     (GtkTreeView      *tree_view,
119                                                     gint              i,
120                                                     gint             *x);
121 static void     gtk_tree_view_adjustment_changed   (GtkAdjustment    *adjustment,
122                                                     GtkTreeView      *tree_view);
123 static gint     gtk_tree_view_insert_iter_height   (GtkTreeView      *tree_view,
124                                                     GtkRBTree        *tree,
125                                                     GtkTreeIter      *iter,
126                                                     gint              depth);
127 static void     gtk_tree_view_build_tree           (GtkTreeView      *tree_view,
128                                                     GtkRBTree        *tree,
129                                                     GtkTreeIter      *iter,
130                                                     gint              depth,
131                                                     gboolean          recurse,
132                                                     gboolean          calc_bounds);
133 static void     gtk_tree_view_calc_size            (GtkTreeView      *priv,
134                                                     GtkRBTree        *tree,
135                                                     GtkTreeIter      *iter,
136                                                     gint              depth);
137 static gboolean gtk_tree_view_discover_dirty_iter  (GtkTreeView      *tree_view,
138                                                     GtkTreeIter      *iter,
139                                                     gint              depth,
140                                                     gint             *height);
141 static void     gtk_tree_view_discover_dirty       (GtkTreeView      *tree_view,
142                                                     GtkRBTree        *tree,
143                                                     GtkTreeIter      *iter,
144                                                     gint              depth);
145 static void     gtk_tree_view_check_dirty          (GtkTreeView      *tree_view);
146 static void     gtk_tree_view_create_button        (GtkTreeView      *tree_view,
147                                                     gint              i);
148 static void     gtk_tree_view_create_buttons       (GtkTreeView      *tree_view);
149 static void     gtk_tree_view_button_clicked       (GtkWidget        *widget,
150                                                     gpointer          data);
151 static void     gtk_tree_view_clamp_node_visible   (GtkTreeView      *tree_view,
152                                                     GtkRBTree        *tree,
153                                                     GtkRBNode        *node);
154
155
156
157 static GtkContainerClass *parent_class = NULL;
158
159
160 /* Class Functions */
161 GtkType
162 gtk_tree_view_get_type (void)
163 {
164   static GtkType tree_view_type = 0;
165
166   if (!tree_view_type)
167     {
168       static const GTypeInfo tree_view_info =
169       {
170         sizeof (GtkTreeViewClass),
171         NULL,           /* base_init */
172         NULL,           /* base_finalize */
173         (GClassInitFunc) gtk_tree_view_class_init,
174         NULL,           /* class_finalize */
175         NULL,           /* class_data */
176         sizeof (GtkTreeView),
177         0,              /* n_preallocs */
178         (GInstanceInitFunc) gtk_tree_view_init
179       };
180
181       tree_view_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkTreeView", &tree_view_info, 0);
182     }
183
184   return tree_view_type;
185 }
186
187 static void
188 gtk_tree_view_class_init (GtkTreeViewClass *class)
189 {
190   GtkObjectClass *object_class;
191   GtkWidgetClass *widget_class;
192   GtkContainerClass *container_class;
193
194   object_class = (GtkObjectClass*) class;
195   widget_class = (GtkWidgetClass*) class;
196   container_class = (GtkContainerClass*) class;
197   parent_class = g_type_class_peek_parent (class);
198
199   widget_class->realize = gtk_tree_view_realize;
200   widget_class->unrealize = gtk_tree_view_unrealize;
201   widget_class->map = gtk_tree_view_map;
202   widget_class->size_request = gtk_tree_view_size_request;
203   widget_class->size_allocate = gtk_tree_view_size_allocate;
204   widget_class->expose_event = gtk_tree_view_expose;
205   widget_class->motion_notify_event = gtk_tree_view_motion;
206   widget_class->enter_notify_event = gtk_tree_view_enter_notify;
207   widget_class->leave_notify_event = gtk_tree_view_leave_notify;
208   widget_class->button_press_event = gtk_tree_view_button_press;
209   widget_class->button_release_event = gtk_tree_view_button_release;
210   widget_class->draw_focus = gtk_tree_view_draw_focus;
211   widget_class->focus_in_event = gtk_tree_view_focus_in;
212   widget_class->focus_out_event = gtk_tree_view_focus_out;
213
214   container_class->forall = gtk_tree_view_forall;
215   container_class->remove = gtk_tree_view_remove;
216   container_class->focus = gtk_tree_view_focus;
217
218   class->set_scroll_adjustments = gtk_tree_view_set_adjustments;
219
220   widget_class->set_scroll_adjustments_signal =
221     gtk_signal_new ("set_scroll_adjustments",
222                     GTK_RUN_LAST,
223                     GTK_CLASS_TYPE (object_class),
224                     GTK_SIGNAL_OFFSET (GtkTreeViewClass, set_scroll_adjustments),
225                     gtk_marshal_VOID__POINTER_POINTER,
226                     GTK_TYPE_NONE, 2,
227                     GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
228 }
229
230 static void
231 gtk_tree_view_init (GtkTreeView *tree_view)
232 {
233   tree_view->priv = g_new0 (GtkTreeViewPrivate, 1);
234
235   GTK_WIDGET_SET_FLAGS (tree_view, GTK_CAN_FOCUS);
236
237   tree_view->priv->flags = GTK_TREE_VIEW_IS_LIST | GTK_TREE_VIEW_SHOW_EXPANDERS | GTK_TREE_VIEW_DRAW_KEYFOCUS | GTK_TREE_VIEW_HEADERS_VISIBLE;
238   tree_view->priv->tab_offset = TREE_VIEW_EXPANDER_WIDTH;
239   tree_view->priv->n_columns = 0;
240   tree_view->priv->columns = NULL;
241   tree_view->priv->button_pressed_node = NULL;
242   tree_view->priv->button_pressed_tree = NULL;
243   tree_view->priv->prelight_node = NULL;
244   tree_view->priv->prelight_offset = 0;
245   tree_view->priv->header_height = 1;
246   tree_view->priv->x_drag = 0;
247   tree_view->priv->drag_pos = -1;
248   tree_view->priv->selection = NULL;
249   tree_view->priv->anchor = NULL;
250   tree_view->priv->cursor = NULL;
251   gtk_tree_view_set_adjustments (tree_view, NULL, NULL);
252   _gtk_tree_view_set_size (tree_view, 0, 0);
253 }
254
255 /* Widget methods
256  */
257
258 static void
259 gtk_tree_view_realize_buttons (GtkTreeView *tree_view)
260 {
261   GList *list;
262   GtkTreeViewColumn *column;
263   GdkWindowAttr attr;
264   guint attributes_mask;
265
266   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
267   g_return_if_fail (tree_view->priv->header_window != NULL);
268
269   attr.window_type = GDK_WINDOW_CHILD;
270   attr.wclass = GDK_INPUT_ONLY;
271   attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
272   attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
273   attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view));
274   attr.event_mask = (GDK_BUTTON_PRESS_MASK |
275                      GDK_BUTTON_RELEASE_MASK |
276                      GDK_POINTER_MOTION_MASK |
277                      GDK_POINTER_MOTION_HINT_MASK |
278                      GDK_KEY_PRESS_MASK);
279   attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
280   attr.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
281   tree_view->priv->cursor_drag = attr.cursor;
282
283   attr.y = 0;
284   attr.width = TREE_VIEW_DRAG_WIDTH;
285   attr.height = tree_view->priv->header_height;
286
287   for (list = tree_view->priv->columns; list; list = list->next)
288     {
289       column = list->data;
290       if (column->button)
291         {
292           if (column->visible == FALSE)
293             continue;
294           if (column->window != NULL)
295             continue;
296
297           gtk_widget_set_parent_window (column->button,
298                                         tree_view->priv->header_window);
299
300           attr.x = (column->button->allocation.x + column->button->allocation.width) - 3;
301           
302           column->window = gdk_window_new (tree_view->priv->header_window,
303                                            &attr, attributes_mask);
304           gdk_window_set_user_data (column->window, tree_view);
305         }
306     }
307 }
308
309 static void
310 gtk_tree_view_realize (GtkWidget *widget)
311 {
312   GList *tmp_list;
313   GtkTreeView *tree_view;
314   GdkGCValues values;
315   GdkWindowAttr attributes;
316   gint attributes_mask;
317
318   g_return_if_fail (widget != NULL);
319   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
320
321   tree_view = GTK_TREE_VIEW (widget);
322
323   if (!GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP) &&
324       tree_view->priv->model)
325     gtk_tree_view_setup_model (tree_view);
326
327   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
328   GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
329
330   /* Make the main, clipping window */
331   attributes.window_type = GDK_WINDOW_CHILD;
332   attributes.x = widget->allocation.x;
333   attributes.y = widget->allocation.y;
334   attributes.width = widget->allocation.width;
335   attributes.height = widget->allocation.height;
336   attributes.wclass = GDK_INPUT_OUTPUT;
337   attributes.visual = gtk_widget_get_visual (widget);
338   attributes.colormap = gtk_widget_get_colormap (widget);
339   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
340
341   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
342
343   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
344                                    &attributes, attributes_mask);
345   gdk_window_set_user_data (widget->window, widget);
346
347   /* Make the window for the tree */
348   attributes.x = 0;
349   attributes.y = 0;
350   attributes.width = tree_view->priv->width;
351   attributes.height = tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view);
352   attributes.event_mask = GDK_EXPOSURE_MASK |
353     GDK_SCROLL_MASK |
354     GDK_POINTER_MOTION_MASK |
355     GDK_ENTER_NOTIFY_MASK |
356     GDK_LEAVE_NOTIFY_MASK |
357     GDK_BUTTON_PRESS_MASK |
358     GDK_BUTTON_RELEASE_MASK |
359     gtk_widget_get_events (widget);
360
361   tree_view->priv->bin_window = gdk_window_new (widget->window,
362                                                 &attributes, attributes_mask);
363   gdk_window_set_user_data (tree_view->priv->bin_window, widget);
364
365   /* Make the column header window */
366   attributes.x = 0;
367   attributes.y = 0;
368   attributes.width = MAX (tree_view->priv->width, widget->allocation.width);
369   attributes.height = tree_view->priv->header_height;
370   attributes.event_mask = (GDK_EXPOSURE_MASK |
371                            GDK_SCROLL_MASK |
372                            GDK_BUTTON_PRESS_MASK |
373                            GDK_BUTTON_RELEASE_MASK |
374                            GDK_KEY_PRESS_MASK |
375                            GDK_KEY_RELEASE_MASK) |
376     gtk_widget_get_events (widget);
377
378   tree_view->priv->header_window = gdk_window_new (widget->window,
379                                                    &attributes, attributes_mask);
380   gdk_window_set_user_data (tree_view->priv->header_window, widget);
381
382
383   values.foreground = (widget->style->white.pixel==0 ?
384                        widget->style->black:widget->style->white);
385   values.function = GDK_XOR;
386   values.subwindow_mode = GDK_INCLUDE_INFERIORS;
387   tree_view->priv->xor_gc = gdk_gc_new_with_values (widget->window,
388                                                     &values,
389                                                     GDK_GC_FOREGROUND |
390                                                     GDK_GC_FUNCTION |
391                                                     GDK_GC_SUBWINDOW);
392   /* Add them all up. */
393   widget->style = gtk_style_attach (widget->style, widget->window);
394   gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
395   gdk_window_set_background (tree_view->priv->bin_window, &widget->style->base[widget->state]);
396   gtk_style_set_background (widget->style, tree_view->priv->header_window, GTK_STATE_NORMAL);
397
398   tmp_list = tree_view->priv->children;
399   while (tmp_list)
400     {
401       GtkTreeViewChild *child = tmp_list->data;
402       tmp_list = tmp_list->next;
403
404       gtk_widget_set_parent_window (child->widget, tree_view->priv->bin_window);
405     }
406   gtk_tree_view_realize_buttons (GTK_TREE_VIEW (widget));
407   _gtk_tree_view_set_size (GTK_TREE_VIEW (widget), -1, -1);
408 }
409
410 static void
411 gtk_tree_view_unrealize (GtkWidget *widget)
412 {
413   GtkTreeView *tree_view;
414
415   g_return_if_fail (widget != NULL);
416   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
417
418   tree_view = GTK_TREE_VIEW (widget);
419
420   /* FIXME where do we clear column->window for each column? */
421   
422   gdk_window_set_user_data (tree_view->priv->bin_window, NULL);
423   gdk_window_destroy (tree_view->priv->bin_window);
424   tree_view->priv->bin_window = NULL;
425
426   gdk_window_set_user_data (tree_view->priv->header_window, NULL);
427   gdk_window_destroy (tree_view->priv->header_window);
428   tree_view->priv->header_window = NULL;
429
430   gdk_gc_destroy (tree_view->priv->xor_gc);
431
432   /* GtkWidget::unrealize destroys children and widget->window */
433   
434   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
435     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
436 }
437
438 static void
439 gtk_tree_view_map_buttons (GtkTreeView *tree_view)
440 {
441   GList *list;
442
443   g_return_if_fail (GTK_WIDGET_MAPPED (tree_view));
444   
445   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
446     {
447       GtkTreeViewColumn *column;
448       
449       for (list = tree_view->priv->columns; list; list = list->next)
450         {
451           column = list->data;
452           if (GTK_WIDGET_VISIBLE (column->button) &&
453               !GTK_WIDGET_MAPPED (column->button))
454             gtk_widget_map (column->button);
455         }
456       for (list = tree_view->priv->columns; list; list = list->next)
457         {
458           column = list->data;
459           if (column->visible == FALSE)
460             continue;
461           if (column->column_type == GTK_TREE_VIEW_COLUMN_RESIZEABLE)
462             {
463               gdk_window_raise (column->window);
464               gdk_window_show (column->window);
465             }
466           else
467             gdk_window_hide (column->window);
468         }
469       gdk_window_show (tree_view->priv->header_window);
470     }
471 }
472
473 static void
474 gtk_tree_view_map (GtkWidget *widget)
475 {
476   GList *tmp_list;
477   GtkTreeView *tree_view;
478
479   g_return_if_fail (widget != NULL);
480   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
481
482   tree_view = GTK_TREE_VIEW (widget);
483
484   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
485
486   tmp_list = tree_view->priv->children;
487   while (tmp_list)
488     {
489       GtkTreeViewChild *child = tmp_list->data;
490       tmp_list = tmp_list->next;
491
492       if (GTK_WIDGET_VISIBLE (child->widget))
493         {
494           if (!GTK_WIDGET_MAPPED (child->widget))
495             gtk_widget_map (child->widget);
496         }
497     }
498   gdk_window_show (tree_view->priv->bin_window);
499
500   gtk_tree_view_map_buttons (tree_view);
501   
502   gdk_window_show (widget->window);
503 }
504
505 static void
506 gtk_tree_view_size_request_buttons (GtkTreeView *tree_view)
507 {
508   GList *list;
509   
510   tree_view->priv->header_height = 1;
511
512   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
513     {
514       for (list = tree_view->priv->columns; list; list = list->next)
515         {
516           GtkRequisition requisition;
517           GtkTreeViewColumn *column;
518           
519           column = list->data;
520           
521           gtk_widget_size_request (column->button, &requisition);
522           
523           column->width = MAX (column->width, requisition.width);
524           tree_view->priv->header_height = MAX (tree_view->priv->header_height, requisition.height);
525         }
526     }
527 }
528
529 static void
530 gtk_tree_view_size_request (GtkWidget      *widget,
531                             GtkRequisition *requisition)
532 {
533   GtkTreeView *tree_view;
534   GList *tmp_list;
535
536   g_return_if_fail (widget != NULL);
537   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
538
539   tree_view = GTK_TREE_VIEW (widget);
540
541   requisition->width = 200;
542   requisition->height = 200;
543
544   tmp_list = tree_view->priv->children;
545
546   while (tmp_list)
547     {
548       GtkTreeViewChild *child = tmp_list->data;
549       GtkRequisition child_requisition;
550
551       tmp_list = tmp_list->next;
552
553       if (GTK_WIDGET_VISIBLE (child->widget))
554         gtk_widget_size_request (child->widget, &child_requisition);
555     }
556
557   gtk_tree_view_size_request_buttons (tree_view);
558 }
559
560 static void
561 gtk_tree_view_size_allocate_buttons (GtkWidget *widget)
562 {
563   GtkTreeView *tree_view;
564   GList *list;
565   GList *last_column;
566   GtkTreeViewColumn *column;
567   GtkAllocation allocation;
568   gint width = 0;
569
570   tree_view = GTK_TREE_VIEW (widget);
571
572   allocation.y = 0;
573   allocation.height = tree_view->priv->header_height;
574
575   for (last_column = g_list_last (tree_view->priv->columns);
576        last_column && !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible);
577        last_column = last_column->prev)
578     ;
579
580   if (last_column == NULL)
581     return;
582
583   for (list = tree_view->priv->columns; list != last_column; list = list->next)
584     {
585       column = list->data;
586
587       if (!column->visible)
588         continue;
589
590       allocation.x = width;
591       allocation.width = column->width;
592       width += column->width;
593       gtk_widget_size_allocate (column->button, &allocation);
594
595       if (column->window)
596         gdk_window_move_resize (column->window,
597                                 width - TREE_VIEW_DRAG_WIDTH/2, allocation.y,
598                                 TREE_VIEW_DRAG_WIDTH, allocation.height);
599     }
600   column = list->data;
601   allocation.x = width;
602   allocation.width = MAX (widget->allocation.width, tree_view->priv->width) - width;
603   gtk_widget_size_allocate (column->button, &allocation);
604   if (column->window)
605     gdk_window_move_resize (column->window,
606                             allocation.x + allocation.width - TREE_VIEW_DRAG_WIDTH/2,
607                             0,
608                             TREE_VIEW_DRAG_WIDTH, allocation.height);
609 }
610
611 static void
612 gtk_tree_view_size_allocate (GtkWidget     *widget,
613                              GtkAllocation *allocation)
614 {
615   GList *tmp_list;
616   GtkTreeView *tree_view;
617
618   g_return_if_fail (widget != NULL);
619   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
620
621   widget->allocation = *allocation;
622
623   tree_view = GTK_TREE_VIEW (widget);
624
625   tmp_list = tree_view->priv->children;
626
627   while (tmp_list)
628     {
629       GtkAllocation allocation;
630       GtkRequisition requisition;
631
632       GtkTreeViewChild *child = tmp_list->data;
633       tmp_list = tmp_list->next;
634
635       allocation.x = child->x;
636       allocation.y = child->y;
637       gtk_widget_get_child_requisition (child->widget, &requisition);
638       allocation.width = requisition.width;
639       allocation.height = requisition.height;
640
641       gtk_widget_size_allocate (child->widget, &allocation);
642     }
643
644   if (GTK_WIDGET_REALIZED (widget))
645     {
646       gdk_window_move_resize (widget->window,
647                               allocation->x, allocation->y,
648                               allocation->width, allocation->height);
649       gdk_window_move_resize (tree_view->priv->header_window,
650                               0, 0,
651                               MAX (tree_view->priv->width, allocation->width),
652                               tree_view->priv->header_height);
653     }
654
655   /* FIXME I don't think the invariant that the model must be setup
656    * before touching the buttons is maintained in most of the
657    * rest of the code, e.g. in realize, so something is wrong
658    */
659   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
660     gtk_tree_view_size_allocate_buttons (widget);
661   
662   tree_view->priv->hadjustment->page_size = allocation->width;
663   tree_view->priv->hadjustment->page_increment = allocation->width / 2;
664   tree_view->priv->hadjustment->lower = 0;
665   tree_view->priv->hadjustment->upper = tree_view->priv->width;
666   if (tree_view->priv->hadjustment->value + allocation->width > tree_view->priv->width)
667     tree_view->priv->hadjustment->value = MAX (tree_view->priv->width - allocation->width, 0);
668   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
669
670   tree_view->priv->vadjustment->page_size = allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view);
671   tree_view->priv->vadjustment->page_increment = (allocation->height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
672   tree_view->priv->vadjustment->lower = 0;
673   tree_view->priv->vadjustment->upper = tree_view->priv->height;
674   if (tree_view->priv->vadjustment->value + allocation->height > tree_view->priv->height)
675     gtk_adjustment_set_value (tree_view->priv->vadjustment,
676                               (gfloat) MAX (tree_view->priv->height - allocation->height, 0));
677   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
678 }
679
680 /* Warning: Very scary function.
681  * Modify at your own risk
682  */
683 static gboolean
684 gtk_tree_view_bin_expose (GtkWidget      *widget,
685                           GdkEventExpose *event)
686 {
687   GtkTreeView *tree_view;
688   GtkTreePath *path;
689   GtkRBTree *tree;
690   GList *list;
691   GtkRBNode *node, *last_node = NULL;
692   GtkRBNode *cursor = NULL;
693   GtkRBTree *cursor_tree = NULL, *last_tree = NULL;
694   GtkTreeIter iter;
695   GtkCellRenderer *cell;
696   gint new_y;
697   gint y_offset, x_offset, cell_offset;
698   gint i, max_height;
699   gint depth;
700   GdkRectangle background_area;
701   GdkRectangle cell_area;
702   guint flags;
703   gboolean last_selected;
704
705   g_return_val_if_fail (widget != NULL, FALSE);
706   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
707
708   tree_view = GTK_TREE_VIEW (widget);
709
710   if (tree_view->priv->tree == NULL)
711     return TRUE;
712
713   gtk_tree_view_check_dirty (GTK_TREE_VIEW (widget));
714   /* we want to account for a potential HEADER offset.
715    * That is, if the header exists, we want to offset our event by its
716    * height to find the right node.
717    */
718   new_y = (event->area.y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):event->area.y;
719   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
720                                        new_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
721                                        &tree,
722                                        &node) + new_y - event->area.y;
723   if (node == NULL)
724     return TRUE;
725
726   /* See if the last node was selected */
727   _gtk_rbtree_prev_full (tree, node, &last_tree, &last_node);
728   last_selected = (last_node && GTK_RBNODE_FLAG_SET (last_node, GTK_RBNODE_IS_SELECTED));
729
730   /* find the path for the node */
731   path = _gtk_tree_view_find_path ((GtkTreeView *)widget,
732                                    tree,
733                                    node);
734   gtk_tree_model_get_iter (tree_view->priv->model,
735                            &iter,
736                            path);
737   depth = gtk_tree_path_get_depth (path);
738   gtk_tree_path_free (path);
739
740   if (tree_view->priv->cursor)
741     _gtk_tree_view_find_node (tree_view, tree_view->priv->cursor, &cursor_tree, &cursor);
742
743   /* Actually process the expose event.  To do this, we want to
744    * start at the first node of the event, and walk the tree in
745    * order, drawing each successive node.
746    */
747
748   do
749     {
750       /* Need to think about this more.
751          if (tree_view->priv->show_expanders)
752          max_height = MAX (TREE_VIEW_EXPANDER_MIN_HEIGHT, GTK_RBNODE_GET_HEIGHT (node));
753          else
754       */
755       max_height = GTK_RBNODE_GET_HEIGHT (node);
756
757       x_offset = -event->area.x;
758       cell_offset = 0;
759
760       background_area.y = y_offset + event->area.y + TREE_VIEW_VERTICAL_SEPARATOR;
761       background_area.height = max_height - TREE_VIEW_VERTICAL_SEPARATOR;
762       flags = 0;
763
764       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PRELIT))
765         flags |= GTK_CELL_RENDERER_PRELIT;
766
767       if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED))
768         {
769           flags |= GTK_CELL_RENDERER_SELECTED;
770
771           /* Draw the selection */
772           gdk_draw_rectangle (event->window,
773                               GTK_WIDGET (tree_view)->style->bg_gc [GTK_STATE_SELECTED],
774                               TRUE,
775                               event->area.x,
776                               background_area.y - (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0),
777                               event->area.width,
778                               background_area.height + (last_selected?TREE_VIEW_VERTICAL_SEPARATOR:0));
779           last_selected = TRUE;
780         }
781       else
782         {
783           last_selected = FALSE;
784         }
785
786       for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
787         {
788           GtkTreeViewColumn *column = list->data;
789
790           if (!column->visible)
791             continue;
792
793           cell = column->cell;
794           gtk_tree_view_column_set_cell_data (column,
795                                               tree_view->priv->model,
796                                               &iter);
797
798           background_area.x = cell_offset;
799           background_area.width = TREE_VIEW_COLUMN_WIDTH (column);
800           if (i == 0 && TREE_VIEW_DRAW_EXPANDERS(tree_view))
801             {
802               cell_area = background_area;
803               cell_area.x += depth*tree_view->priv->tab_offset;
804               cell_area.width -= depth*tree_view->priv->tab_offset;
805               gtk_cell_renderer_render (cell,
806                                         event->window,
807                                         widget,
808                                         &background_area,
809                                         &cell_area,
810                                         &event->area,
811                                         flags);
812               if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT)
813                 {
814                   gint x, y;
815                   gdk_window_get_pointer (tree_view->priv->bin_window, &x, &y, 0);
816                   gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
817                                             node,
818                                             event->area.y + y_offset,
819                                             x, y);
820                 }
821             }
822           else
823             {
824               cell_area = background_area;
825               gtk_cell_renderer_render (cell,
826                                         event->window,
827                                         widget,
828                                         &background_area,
829                                         &cell_area,
830                                         &event->area,
831                                         flags);
832             }
833           cell_offset += TREE_VIEW_COLUMN_WIDTH (column);
834         }
835
836       if (node == cursor &&
837           GTK_WIDGET_HAS_FOCUS (widget))
838         gtk_tree_view_draw_focus (widget);
839
840       y_offset += max_height;
841       if (node->children)
842         {
843           GtkTreeIter parent = iter;
844           gboolean has_child;
845
846           tree = node->children;
847           node = tree->root;
848           while (node->left != tree->nil)
849             node = node->left;
850           has_child = gtk_tree_model_iter_children (tree_view->priv->model,
851                                                     &iter,
852                                                     &parent);
853           cell = gtk_tree_view_get_column (tree_view, 0)->cell;
854           depth++;
855
856           /* Sanity Check! */
857           TREE_VIEW_INTERNAL_ASSERT (has_child, FALSE);
858         }
859       else
860         {
861           gboolean done = FALSE;
862           do
863             {
864               node = _gtk_rbtree_next (tree, node);
865               if (node != NULL)
866                 {
867                   gboolean has_next = gtk_tree_model_iter_next (tree_view->priv->model, &iter);
868                   cell = gtk_tree_view_get_column (tree_view, 0)->cell;
869                   done = TRUE;
870
871                   /* Sanity Check! */
872                   TREE_VIEW_INTERNAL_ASSERT (has_next, FALSE);
873                 }
874               else
875                 {
876                   GtkTreeIter parent_iter = iter;
877                   gboolean has_parent;
878
879                   node = tree->parent_node;
880                   tree = tree->parent_tree;
881                   if (tree == NULL)
882                     /* we've run out of tree.  It's okay to return though, as
883                      * we'd only break out of the while loop below. */
884                     return TRUE;
885                   has_parent = gtk_tree_model_iter_parent (tree_view->priv->model,
886                                                            &iter,
887                                                            &parent_iter);
888                   depth--;
889
890                   /* Sanity check */
891                   TREE_VIEW_INTERNAL_ASSERT (has_parent, FALSE);
892                 }
893             }
894           while (!done);
895         }
896     }
897   while (y_offset < event->area.height);
898
899   return TRUE;
900 }
901
902 static gboolean
903 gtk_tree_view_expose (GtkWidget      *widget,
904                       GdkEventExpose *event)
905 {
906   GtkTreeView *tree_view;
907
908   g_return_val_if_fail (widget != NULL, FALSE);
909   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
910
911   tree_view = GTK_TREE_VIEW (widget);
912
913   if (event->window == tree_view->priv->bin_window)
914     return gtk_tree_view_bin_expose (widget, event);
915
916   return TRUE;
917 }
918
919 static gboolean
920 gtk_tree_view_motion (GtkWidget *widget,
921                       GdkEventMotion  *event)
922 {
923   GtkTreeView *tree_view;
924   GtkRBTree *tree;
925   GtkRBNode *node;
926   gint new_y;
927   gint y_offset;
928
929   g_return_val_if_fail (widget != NULL, FALSE);
930   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
931
932   tree_view = GTK_TREE_VIEW (widget);
933   
934   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
935     {
936       gint x;
937       gint new_width;
938
939       if (event->is_hint || event->window != widget->window)
940         gtk_widget_get_pointer (widget, &x, NULL);
941       else
942         x = event->x;
943
944       new_width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), tree_view->priv->drag_pos, &x);
945       if (x != tree_view->priv->x_drag)
946         {
947           gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), tree_view->priv->drag_pos), new_width);
948         }
949
950       /* FIXME: Do we need to scroll */
951       _gtk_tree_view_set_size (GTK_TREE_VIEW (widget), -1, tree_view->priv->height);
952       return FALSE;
953     }
954
955   /* Sanity check it */
956   if (event->window != tree_view->priv->bin_window)
957     return FALSE;
958   if (tree_view->priv->tree == NULL)
959     return FALSE;
960   
961   if (tree_view->priv->prelight_node != NULL)
962     {
963       if ((((gint) event->y - TREE_VIEW_HEADER_HEIGHT (tree_view) < tree_view->priv->prelight_offset) ||
964            ((gint) event->y - TREE_VIEW_HEADER_HEIGHT (tree_view) >=
965             (tree_view->priv->prelight_offset + GTK_RBNODE_GET_HEIGHT (tree_view->priv->prelight_node))) ||
966            ((gint) event->x > tree_view->priv->tab_offset)))
967         /* We need to unprelight the old one. */
968         {
969           if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
970             {
971               GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
972               gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
973                                         tree_view->priv->prelight_node,
974                                         tree_view->priv->prelight_offset,
975                                         event->x,
976                                         event->y);
977               GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
978             }
979
980           GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
981           tree_view->priv->prelight_node = NULL;
982           tree_view->priv->prelight_tree = NULL;
983           tree_view->priv->prelight_offset = 0;
984         }
985     }
986
987   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
988   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree, new_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
989                                        &tree,
990                                        &node) + new_y - (gint)event->y;
991
992   if (node == NULL)
993     return TRUE;
994
995   /* If we are currently pressing down a button, we don't want to prelight anything else. */
996   if ((tree_view->priv->button_pressed_node != NULL) &&
997       (tree_view->priv->button_pressed_node != node))
998     return TRUE;
999
1000   /* Do we want to prelight a tab? */
1001   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1002   if (event->x <= tree_view->priv->tab_offset &&
1003       event->x >= 0 &&
1004       ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT))
1005     {
1006       tree_view->priv->prelight_offset = event->y+y_offset;
1007       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1008     }
1009
1010   tree_view->priv->prelight_node = node;
1011   tree_view->priv->prelight_tree = tree;
1012   tree_view->priv->prelight_offset = event->y+y_offset;
1013
1014   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
1015   /* FIXME */
1016   gtk_widget_queue_draw (widget);
1017
1018   return TRUE;
1019 }
1020
1021 /* FIXME Is this function necessary? Can I get an enter_notify event
1022  * w/o either an expose event or a mouse motion event?
1023  */
1024 static gboolean
1025 gtk_tree_view_enter_notify (GtkWidget        *widget,
1026                             GdkEventCrossing *event)
1027 {
1028   GtkTreeView *tree_view;
1029   GtkRBTree *tree;
1030   GtkRBNode *node;
1031   gint new_y;
1032   gint y_offset;
1033
1034   g_return_val_if_fail (widget != NULL, FALSE);
1035   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1036
1037   tree_view = GTK_TREE_VIEW (widget);
1038
1039   /* Sanity check it */
1040   if (event->window != tree_view->priv->bin_window)
1041     return FALSE;
1042   if (tree_view->priv->tree == NULL)
1043     return FALSE;
1044
1045   if ((tree_view->priv->button_pressed_node != NULL) &&
1046       (tree_view->priv->button_pressed_node != node))
1047     return TRUE;
1048
1049   /* find the node internally */
1050   new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1051   y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
1052                                        new_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
1053                                        &tree,
1054                                        &node) + new_y - (gint)event->y;
1055
1056   if (node == NULL)
1057     return FALSE;
1058
1059   /* Do we want to prelight a tab? */
1060   GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1061   if (event->x <= tree_view->priv->tab_offset &&
1062       event->x >= 0 &&
1063       ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT))
1064     {
1065       tree_view->priv->prelight_offset = event->y+y_offset;
1066       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1067     }
1068
1069   tree_view->priv->prelight_node = node;
1070   tree_view->priv->prelight_tree = tree;
1071   tree_view->priv->prelight_offset = event->y+y_offset;
1072
1073   GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PRELIT);
1074   /* FIXME */
1075   gtk_widget_queue_draw (widget);
1076
1077   return TRUE;
1078 }
1079
1080 static gboolean
1081 gtk_tree_view_leave_notify (GtkWidget        *widget,
1082                             GdkEventCrossing *event)
1083 {
1084   GtkTreeView *tree_view;
1085
1086   g_return_val_if_fail (widget != NULL, FALSE);
1087   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1088
1089   tree_view = GTK_TREE_VIEW (widget);
1090
1091   if (tree_view->priv->prelight_node != NULL)
1092     {
1093       GTK_RBNODE_UNSET_FLAG (tree_view->priv->prelight_node, GTK_RBNODE_IS_PRELIT);
1094       tree_view->priv->prelight_node = NULL;
1095       tree_view->priv->prelight_tree = NULL;
1096       tree_view->priv->prelight_offset = 0;
1097       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_ARROW_PRELIT);
1098       /* FIXME */
1099       gtk_widget_queue_draw (widget);
1100     }
1101   return TRUE;
1102 }
1103
1104 static gboolean
1105 gtk_tree_view_button_press (GtkWidget      *widget,
1106                             GdkEventButton *event)
1107 {
1108   GtkTreeView *tree_view;
1109   GList *list;
1110   GtkTreeViewColumn *column;
1111   gint i;
1112   GdkRectangle background_area;
1113   GdkRectangle cell_area;
1114
1115   g_return_val_if_fail (widget != NULL, FALSE);
1116   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1117   g_return_val_if_fail (event != NULL, FALSE);
1118
1119   tree_view = GTK_TREE_VIEW (widget);
1120
1121   if (event->window == tree_view->priv->bin_window)
1122     {
1123       GtkRBNode *node;
1124       GtkRBTree *tree;
1125       GtkTreePath *path;
1126       gchar *path_string;
1127       gint depth;
1128       gint new_y;
1129       gint y_offset;
1130
1131       if (!GTK_WIDGET_HAS_FOCUS (widget))
1132         gtk_widget_grab_focus (widget);
1133       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1134       /* are we in an arrow? */
1135       if (tree_view->priv->prelight_node != FALSE && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1136         {
1137           if (event->button == 1)
1138             {
1139               gtk_grab_add (widget);
1140               tree_view->priv->button_pressed_node = tree_view->priv->prelight_node;
1141               tree_view->priv->button_pressed_tree = tree_view->priv->prelight_tree;
1142               gtk_tree_view_draw_arrow (GTK_TREE_VIEW (widget),
1143                                         tree_view->priv->prelight_node,
1144                                         tree_view->priv->prelight_offset,
1145                                         event->x,
1146                                         event->y);
1147             }
1148           return TRUE;
1149         }
1150
1151       /* find the node that was clicked */
1152       new_y = ((gint)event->y<TREE_VIEW_HEADER_HEIGHT (tree_view))?TREE_VIEW_HEADER_HEIGHT (tree_view):(gint)event->y;
1153       y_offset = -_gtk_rbtree_find_offset (tree_view->priv->tree,
1154                                            new_y - TREE_VIEW_HEADER_HEIGHT (tree_view),
1155                                            &tree,
1156                                            &node) + new_y - (gint)event->y;
1157
1158       if (node == NULL)
1159         /* We clicked in dead space */
1160         return TRUE;
1161
1162       /* Get the path and the node */
1163       path = _gtk_tree_view_find_path (tree_view, tree, node);
1164       depth = gtk_tree_path_get_depth (path);
1165       background_area.y = y_offset + event->y + TREE_VIEW_VERTICAL_SEPARATOR;
1166       background_area.height = GTK_RBNODE_GET_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR;
1167       background_area.x = 0;
1168       /* Let the cell have a chance at selecting it. */
1169
1170       for (i = 0, list = tree_view->priv->columns; i < tree_view->priv->n_columns; i++, list = list->next)
1171         {
1172           GtkTreeViewColumn *column = list->data;
1173           GtkCellRenderer *cell;
1174           GtkTreeIter iter;
1175
1176           if (!column->visible)
1177             continue;
1178
1179           background_area.width = TREE_VIEW_COLUMN_WIDTH (column);
1180           if (i == 0 && TREE_VIEW_DRAW_EXPANDERS(tree_view))
1181             {
1182               cell_area = background_area;
1183               cell_area.x += depth*tree_view->priv->tab_offset;
1184               cell_area.width -= depth*tree_view->priv->tab_offset;
1185             }
1186           else
1187             {
1188               cell_area = background_area;
1189             }
1190
1191           cell = column->cell;
1192
1193           if ((background_area.x > (gint) event->x) ||
1194               (background_area.y > (gint) event->y) ||
1195               (background_area.x + background_area.width <= (gint) event->x) ||
1196               (background_area.y + background_area.height <= (gint) event->y))
1197             {
1198               background_area.x += background_area.width;
1199               continue;
1200             }
1201
1202           gtk_tree_model_get_iter (tree_view->priv->model,
1203                                    &iter,
1204                                    path);
1205           gtk_tree_view_column_set_cell_data (column,
1206                                               tree_view->priv->model,
1207                                               &iter);
1208
1209           path_string = gtk_tree_path_to_string (path);
1210           if (gtk_cell_renderer_event (cell,
1211                                        (GdkEvent *)event,
1212                                        widget,
1213                                        path_string,
1214                                        &background_area,
1215                                        &cell_area,
1216                                        0))
1217
1218             {
1219               g_free (path_string);
1220               gtk_tree_path_free (path);
1221               return TRUE;
1222             }
1223           else
1224             {
1225               g_free (path_string);
1226               break;
1227             }
1228         }
1229       /* Handle the selection */
1230       if (tree_view->priv->selection == NULL)
1231         tree_view->priv->selection =
1232           _gtk_tree_selection_new_with_tree_view (tree_view);
1233
1234       _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
1235                                                 node,
1236                                                 tree,
1237                                                 path,
1238                                                 event->state);
1239       gtk_tree_path_free (path);
1240       return TRUE;
1241     }
1242
1243   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
1244     {
1245       column = list->data;
1246       if (event->window == column->window &&
1247           column->column_type == GTK_TREE_VIEW_COLUMN_RESIZEABLE &&
1248           column->window)
1249         {
1250           gpointer drag_data;
1251
1252           if (gdk_pointer_grab (column->window, FALSE,
1253                                 GDK_POINTER_MOTION_HINT_MASK |
1254                                 GDK_BUTTON1_MOTION_MASK |
1255                                 GDK_BUTTON_RELEASE_MASK,
1256                                 NULL, NULL, event->time))
1257             return FALSE;
1258
1259           gtk_grab_add (widget);
1260           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1261
1262           /* block attached dnd signal handler */
1263           drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1264           if (drag_data)
1265             gtk_signal_handler_block_by_data (GTK_OBJECT (widget), drag_data);
1266
1267           if (!GTK_WIDGET_HAS_FOCUS (widget))
1268             gtk_widget_grab_focus (widget);
1269
1270           tree_view->priv->drag_pos = i;
1271           tree_view->priv->x_drag = (column->button->allocation.x + column->button->allocation.width);
1272         }
1273     }
1274   return TRUE;
1275 }
1276
1277 static gboolean
1278 gtk_tree_view_button_release (GtkWidget      *widget,
1279                               GdkEventButton *event)
1280 {
1281   GtkTreeView *tree_view;
1282
1283   g_return_val_if_fail (widget != NULL, FALSE);
1284   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1285   g_return_val_if_fail (event != NULL, FALSE);
1286
1287   tree_view = GTK_TREE_VIEW (widget);
1288
1289   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE))
1290     {
1291       gpointer drag_data;
1292       gint width;
1293       gint x;
1294       gint i;
1295
1296       i = tree_view->priv->drag_pos;
1297       tree_view->priv->drag_pos = -1;
1298
1299       /* unblock attached dnd signal handler */
1300       drag_data = gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data");
1301       if (drag_data)
1302         gtk_signal_handler_unblock_by_data (GTK_OBJECT (widget), drag_data);
1303
1304       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IN_COLUMN_RESIZE);
1305       gtk_widget_get_pointer (widget, &x, NULL);
1306       gtk_grab_remove (widget);
1307       gdk_pointer_ungrab (event->time);
1308
1309       width = gtk_tree_view_new_column_width (GTK_TREE_VIEW (widget), i, &x);
1310       gtk_tree_view_column_set_width (gtk_tree_view_get_column (GTK_TREE_VIEW (widget), i), width);
1311       return FALSE;
1312     }
1313
1314   if (tree_view->priv->button_pressed_node == NULL)
1315     return FALSE;
1316
1317   if (event->button == 1)
1318     {
1319       gtk_grab_remove (widget);
1320       if (tree_view->priv->button_pressed_node == tree_view->priv->prelight_node && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT))
1321         {
1322           GtkTreePath *path;
1323           GtkTreeIter iter;
1324
1325           /* Actually activate the node */
1326           if (tree_view->priv->button_pressed_node->children == NULL)
1327             {
1328               GtkTreeIter child;
1329               path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
1330                                                tree_view->priv->button_pressed_tree,
1331                                                tree_view->priv->button_pressed_node);
1332               tree_view->priv->button_pressed_node->children = _gtk_rbtree_new ();
1333               tree_view->priv->button_pressed_node->children->parent_tree = tree_view->priv->button_pressed_tree;
1334               tree_view->priv->button_pressed_node->children->parent_node = tree_view->priv->button_pressed_node;
1335               gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
1336               gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
1337
1338               gtk_tree_view_build_tree (tree_view,
1339                                         tree_view->priv->button_pressed_node->children,
1340                                         &child,
1341                                         gtk_tree_path_get_depth (path) + 1,
1342                                         FALSE,
1343                                         GTK_WIDGET_REALIZED (widget));
1344             }
1345           else
1346             {
1347               path = _gtk_tree_view_find_path (GTK_TREE_VIEW (widget),
1348                                                tree_view->priv->button_pressed_node->children,
1349                                                tree_view->priv->button_pressed_node->children->root);
1350               gtk_tree_model_get_iter (tree_view->priv->model,
1351                                        &iter,
1352                                        path);
1353
1354               gtk_tree_view_discover_dirty (GTK_TREE_VIEW (widget),
1355                                             tree_view->priv->button_pressed_node->children,
1356                                             &iter,
1357                                             gtk_tree_path_get_depth (path));
1358               _gtk_rbtree_remove (tree_view->priv->button_pressed_node->children);
1359             }
1360           gtk_tree_path_free (path);
1361
1362           _gtk_tree_view_set_size (GTK_TREE_VIEW (widget), -1, -1);
1363         }
1364
1365       tree_view->priv->button_pressed_node = NULL;
1366     }
1367
1368   return TRUE;
1369 }
1370
1371
1372 static void
1373 gtk_tree_view_draw_focus (GtkWidget *widget)
1374 {
1375   GtkTreeView *tree_view;
1376   GtkRBTree *cursor_tree = NULL;
1377   GtkRBNode *cursor = NULL;
1378
1379   g_return_if_fail (widget != NULL);
1380   g_return_if_fail (GTK_IS_TREE_VIEW (widget));
1381
1382   tree_view = GTK_TREE_VIEW (widget);
1383
1384   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS))
1385     return;
1386   if (tree_view->priv->cursor == NULL)
1387     return;
1388
1389   _gtk_tree_view_find_node (tree_view, tree_view->priv->cursor, &cursor_tree, &cursor);
1390   if (cursor == NULL)
1391     return;
1392
1393   /* FIXME need a style function appropriate for this */
1394   gdk_draw_rectangle (tree_view->priv->bin_window,
1395                       widget->style->fg_gc[GTK_STATE_NORMAL],
1396                       FALSE,
1397                       0,
1398                       _gtk_rbtree_node_find_offset (cursor_tree, cursor) + TREE_VIEW_HEADER_HEIGHT (tree_view),
1399                       (gint) MAX (tree_view->priv->width, tree_view->priv->hadjustment->upper),
1400                       GTK_RBNODE_GET_HEIGHT (cursor));
1401 }
1402
1403
1404 static gint
1405 gtk_tree_view_focus_in (GtkWidget     *widget,
1406                         GdkEventFocus *event)
1407 {
1408   GtkTreeView *tree_view;
1409
1410   g_return_val_if_fail (widget != NULL, FALSE);
1411   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1412   g_return_val_if_fail (event != NULL, FALSE);
1413
1414   tree_view = GTK_TREE_VIEW (widget);
1415
1416   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1417
1418   /* FIXME don't redraw so much */
1419   gtk_widget_queue_draw (widget);
1420
1421   return FALSE;
1422 }
1423
1424
1425 static gint
1426 gtk_tree_view_focus_out (GtkWidget     *widget,
1427                          GdkEventFocus *event)
1428 {
1429   g_return_val_if_fail (widget != NULL, FALSE);
1430   g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
1431   g_return_val_if_fail (event != NULL, FALSE);
1432
1433   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1434
1435   /* FIXME don't redraw so much */
1436   gtk_widget_queue_draw (widget);
1437
1438   return FALSE;
1439 }
1440
1441 /* FIXME: It would be neat to someday make the headers a seperate widget that
1442  * can be shared between various apps.  Wishful thinking, though...
1443  */
1444 /* Returns TRUE if the focus is within the headers, after the focus operation is
1445  * done
1446  */
1447 static gboolean
1448 gtk_tree_view_header_focus (GtkTreeView        *tree_view,
1449                             GtkDirectionType  dir)
1450 {
1451   GtkWidget *focus_child;
1452   GtkContainer *container;
1453
1454   GList *last_column, *first_column;
1455   GList *tmp_list;
1456
1457   if (! GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE))
1458     return FALSE;
1459
1460   focus_child = GTK_CONTAINER (tree_view)->focus_child;
1461   container = GTK_CONTAINER (tree_view);
1462
1463   for (last_column = g_list_last (tree_view->priv->columns);
1464        last_column &&
1465          !(GTK_TREE_VIEW_COLUMN (last_column->data)->visible) &&
1466          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (last_column->data)->button);
1467        last_column = last_column->prev)
1468     ;
1469
1470   for (first_column = tree_view->priv->columns;
1471        first_column &&
1472          !(GTK_TREE_VIEW_COLUMN (first_column->data)->visible) &&
1473          GTK_WIDGET_CAN_FOCUS (GTK_TREE_VIEW_COLUMN (first_column->data)->button);
1474        first_column = first_column->next)
1475     ;
1476
1477   /* no headers are visible, or are focussable.  We can't focus in or out.
1478    * I wonder if focussable is a real word...
1479    */
1480   if (last_column == NULL)
1481     return FALSE;
1482
1483   /* First thing we want to handle is entering and leaving the headers.
1484    */
1485   switch (dir)
1486     {
1487     case GTK_DIR_TAB_BACKWARD:
1488       if (!focus_child)
1489         {
1490           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
1491           gtk_widget_grab_focus (focus_child);
1492           goto cleanup;
1493         }
1494       if (focus_child == GTK_TREE_VIEW_COLUMN (first_column->data)->button)
1495         {
1496           focus_child = NULL;
1497           goto cleanup;
1498         }
1499       break;
1500
1501     case GTK_DIR_TAB_FORWARD:
1502       if (!focus_child)
1503         {
1504           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
1505           gtk_widget_grab_focus (focus_child);
1506           goto cleanup;
1507         }
1508       if (focus_child == GTK_TREE_VIEW_COLUMN (last_column->data)->button)
1509         {
1510           focus_child = NULL;
1511           goto cleanup;
1512         }
1513       break;
1514
1515     case GTK_DIR_LEFT:
1516       if (!focus_child)
1517         {
1518           focus_child = GTK_TREE_VIEW_COLUMN (last_column->data)->button;
1519           gtk_widget_grab_focus (focus_child);
1520           goto cleanup;
1521         }
1522       if (focus_child == GTK_TREE_VIEW_COLUMN (first_column->data)->button)
1523         {
1524           focus_child = NULL;
1525           goto cleanup;
1526         }
1527       break;
1528
1529     case GTK_DIR_RIGHT:
1530       if (!focus_child)
1531         {
1532           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
1533           gtk_widget_grab_focus (focus_child);
1534           goto cleanup;
1535         }
1536       if (focus_child == GTK_TREE_VIEW_COLUMN (last_column->data)->button)
1537         {
1538           focus_child = NULL;
1539           goto cleanup;
1540         }
1541       break;
1542
1543     case GTK_DIR_UP:
1544       if (!focus_child)
1545         {
1546           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
1547           gtk_widget_grab_focus (focus_child);
1548         }
1549       else
1550         {
1551           focus_child = NULL;
1552         }
1553       goto cleanup;
1554
1555     case GTK_DIR_DOWN:
1556       if (!focus_child)
1557         {
1558           focus_child = GTK_TREE_VIEW_COLUMN (first_column->data)->button;
1559           gtk_widget_grab_focus (focus_child);
1560         }
1561       else
1562         {
1563           focus_child = NULL;
1564         }
1565       goto cleanup;
1566     }
1567
1568   /* We need to move the focus to the next button. */
1569   if (focus_child)
1570     {
1571       for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1572         if (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button == focus_child)
1573           {
1574             if (gtk_container_focus (GTK_CONTAINER (GTK_TREE_VIEW_COLUMN (tmp_list->data)->button), dir))
1575               {
1576                 /* The focus moves inside the button. */
1577                 /* This is probably a great example of bad UI */
1578                 goto cleanup;
1579               }
1580             break;
1581           }
1582
1583       /* We need to move the focus among the row of buttons. */
1584       while (tmp_list)
1585         {
1586           GtkTreeViewColumn *column;
1587
1588           if (dir == GTK_DIR_RIGHT || dir == GTK_DIR_TAB_FORWARD)
1589             tmp_list = tmp_list->next;
1590           else
1591             tmp_list = tmp_list->prev;
1592
1593           if (tmp_list == NULL)
1594             {
1595               g_warning ("Internal button not found");
1596               goto cleanup;
1597             }
1598           column = tmp_list->data;
1599           if (column->button &&
1600               column->visible &&
1601               GTK_WIDGET_CAN_FOCUS (column->button))
1602             {
1603               focus_child = column->button;
1604               gtk_widget_grab_focus (column->button);
1605               break;
1606             }
1607         }
1608     }
1609
1610  cleanup:
1611   /* if focus child is non-null, we assume it's been set to the current focus child
1612    */
1613   if (focus_child)
1614     {
1615       /* If the following isn't true, then the view is smaller then the scrollpane.
1616        */
1617       if ((focus_child->allocation.x + focus_child->allocation.width) <=
1618           (tree_view->priv->hadjustment->upper))
1619         {
1620           /* Scroll to the button, if needed */
1621           if ((tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size) <
1622               (focus_child->allocation.x + focus_child->allocation.width))
1623             gtk_adjustment_set_value (tree_view->priv->hadjustment,
1624                                       focus_child->allocation.x + focus_child->allocation.width -
1625                                       tree_view->priv->hadjustment->page_size);
1626           else if (tree_view->priv->hadjustment->value > focus_child->allocation.x)
1627             gtk_adjustment_set_value (tree_view->priv->hadjustment,
1628                                       focus_child->allocation.x);
1629         }
1630     }
1631
1632   return (focus_child != NULL);
1633 }
1634
1635 /* WARNING: Scary function */
1636 static gint
1637 gtk_tree_view_focus (GtkContainer     *container,
1638                      GtkDirectionType  direction)
1639 {
1640   GtkTreeView *tree_view;
1641   GtkWidget *focus_child;
1642   GdkEvent *event;
1643   GtkRBTree *cursor_tree;
1644   GtkRBNode *cursor_node;
1645
1646   g_return_val_if_fail (container != NULL, FALSE);
1647   g_return_val_if_fail (GTK_IS_TREE_VIEW (container), FALSE);
1648   g_return_val_if_fail (GTK_WIDGET_VISIBLE (container), FALSE);
1649
1650   tree_view = GTK_TREE_VIEW (container);
1651
1652   if (!GTK_WIDGET_IS_SENSITIVE (container))
1653     return FALSE;
1654   if (tree_view->priv->tree == NULL)
1655     return FALSE;
1656
1657   focus_child = container->focus_child;
1658
1659   /* Case 1.  Headers have focus. */
1660   if (focus_child)
1661     {
1662       switch (direction)
1663         {
1664         case GTK_DIR_LEFT:
1665         case GTK_DIR_TAB_BACKWARD:
1666           return (gtk_tree_view_header_focus (tree_view, direction));
1667         case GTK_DIR_UP:
1668           return FALSE;
1669         case GTK_DIR_TAB_FORWARD:
1670         case GTK_DIR_RIGHT:
1671         case GTK_DIR_DOWN:
1672           if (direction != GTK_DIR_DOWN)
1673             {
1674               if (gtk_tree_view_header_focus (tree_view, direction))
1675                 return TRUE;
1676             }
1677           GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1678           gtk_widget_grab_focus (GTK_WIDGET (container));
1679
1680           if (tree_view->priv->selection == NULL)
1681             tree_view->priv->selection =
1682               _gtk_tree_selection_new_with_tree_view (tree_view);
1683
1684           /* if there is no keyboard focus yet, we select the first node
1685            */
1686           if (tree_view->priv->cursor == NULL)
1687             tree_view->priv->cursor = gtk_tree_path_new_root ();
1688           if (tree_view->priv->cursor)
1689             gtk_tree_selection_select_path (tree_view->priv->selection,
1690                                             tree_view->priv->cursor);
1691           /* FIXME make this more efficient */
1692           gtk_widget_queue_draw (GTK_WIDGET (tree_view));
1693           return TRUE;
1694         }
1695     }
1696
1697   /* Case 2. We don't have focus at all. */
1698   if (!GTK_WIDGET_HAS_FOCUS (container))
1699     {
1700       if ((direction == GTK_DIR_TAB_FORWARD) ||
1701           (direction == GTK_DIR_RIGHT) ||
1702           (direction == GTK_DIR_DOWN))
1703         {
1704           if (gtk_tree_view_header_focus (tree_view, direction))
1705             return TRUE;
1706         }
1707
1708       /* The headers didn't want the focus, so we take it. */
1709       GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_DRAW_KEYFOCUS);
1710       gtk_widget_grab_focus (GTK_WIDGET (container));
1711
1712       if (tree_view->priv->selection == NULL)
1713         tree_view->priv->selection =
1714           _gtk_tree_selection_new_with_tree_view (tree_view);
1715
1716       if (tree_view->priv->cursor == NULL)
1717         tree_view->priv->cursor = gtk_tree_path_new_root ();
1718
1719       if (tree_view->priv->cursor)
1720         gtk_tree_selection_select_path (tree_view->priv->selection,
1721                                         tree_view->priv->cursor);
1722       /* FIXME make this more efficient */
1723       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
1724       return TRUE;
1725     }
1726
1727   /* Case 3. We have focus already, but no cursor.  We pick the first one
1728    * and run with it. */
1729   if (tree_view->priv->cursor == NULL)
1730     {
1731       /* We lost our cursor somehow.  Arbitrarily select the first node, and
1732        * return
1733        */
1734       tree_view->priv->cursor = gtk_tree_path_new_root ();
1735
1736       if (tree_view->priv->cursor)
1737         gtk_tree_selection_select_path (tree_view->priv->selection,
1738                                         tree_view->priv->cursor);
1739       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
1740                                 0.0);
1741       /* FIXME make this more efficient */
1742       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
1743       return TRUE;
1744     }
1745
1746
1747   /* Case 3. We have focus already.  Move the cursor. */
1748   if (direction == GTK_DIR_LEFT)
1749     {
1750       gfloat val;
1751       val = tree_view->priv->hadjustment->value - tree_view->priv->hadjustment->page_size/2;
1752       val = MAX (val, 0.0);
1753       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
1754       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
1755       return TRUE;
1756     }
1757   if (direction == GTK_DIR_RIGHT)
1758     {
1759       gfloat val;
1760       val = tree_view->priv->hadjustment->value + tree_view->priv->hadjustment->page_size/2;
1761       val = MIN (tree_view->priv->hadjustment->upper - tree_view->priv->hadjustment->page_size, val);
1762       gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->hadjustment), val);
1763       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
1764       return TRUE;
1765     }
1766   cursor_tree = NULL;
1767   cursor_node = NULL;
1768
1769   _gtk_tree_view_find_node (tree_view, tree_view->priv->cursor,
1770                             &cursor_tree,
1771                             &cursor_node);
1772   switch (direction)
1773     {
1774     case GTK_DIR_TAB_BACKWARD:
1775     case GTK_DIR_UP:
1776       _gtk_rbtree_prev_full (cursor_tree,
1777                              cursor_node,
1778                              &cursor_tree,
1779                              &cursor_node);
1780       break;
1781     case GTK_DIR_TAB_FORWARD:
1782     case GTK_DIR_DOWN:
1783       _gtk_rbtree_next_full (cursor_tree,
1784                              cursor_node,
1785                              &cursor_tree,
1786                              &cursor_node);
1787       break;
1788     default:
1789       break;
1790     }
1791
1792   if (cursor_node)
1793     {
1794       GdkModifierType state = 0;
1795
1796       event = gtk_get_current_event ();
1797       if (event)
1798         gdk_event_get_state (event, &state);
1799
1800       if (event)
1801         gdk_event_free (event);
1802       gtk_tree_path_free (tree_view->priv->cursor);
1803
1804       tree_view->priv->cursor = _gtk_tree_view_find_path (tree_view,
1805                                                           cursor_tree,
1806                                                           cursor_node);
1807       if (tree_view->priv->cursor)
1808         _gtk_tree_selection_internal_select_node (tree_view->priv->selection,
1809                                                   cursor_node,
1810                                                   cursor_tree,
1811                                                   tree_view->priv->cursor,
1812                                                   state);
1813       gtk_tree_view_clamp_node_visible (tree_view, cursor_tree, cursor_node);
1814       gtk_widget_grab_focus (GTK_WIDGET (tree_view));
1815       /* FIXME make this more efficient */
1816       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
1817       return TRUE;
1818     }
1819
1820   /* At this point, we've progressed beyond the edge of the rows. */
1821
1822   if ((direction == GTK_DIR_LEFT) ||
1823       (direction == GTK_DIR_TAB_BACKWARD) ||
1824       (direction == GTK_DIR_UP))
1825     /* We can't go back anymore.  Try the headers */
1826     return (gtk_tree_view_header_focus (tree_view, direction));
1827
1828   /* we've reached the end of the tree.  Go on. */
1829   return FALSE;
1830 }
1831
1832 /* Container method
1833  */
1834 static void
1835 gtk_tree_view_remove (GtkContainer *container,
1836                       GtkWidget    *widget)
1837 {
1838   GtkTreeView *tree_view;
1839   GtkTreeViewChild *child = NULL;
1840   GList *tmp_list;
1841
1842   g_return_if_fail (container != NULL);
1843   g_return_if_fail (GTK_IS_TREE_VIEW (container));
1844
1845   tree_view = GTK_TREE_VIEW (container);
1846
1847   tmp_list = tree_view->priv->children;
1848   while (tmp_list)
1849     {
1850       child = tmp_list->data;
1851       if (child->widget == widget)
1852         break;
1853       tmp_list = tmp_list->next;
1854     }
1855
1856   if (tmp_list)
1857     {
1858       gtk_widget_unparent (widget);
1859
1860       tree_view->priv->children = g_list_remove_link (tree_view->priv->children, tmp_list);
1861       g_list_free_1 (tmp_list);
1862       g_free (child);
1863     }
1864 }
1865
1866 static void
1867 gtk_tree_view_forall (GtkContainer *container,
1868                       gboolean      include_internals,
1869                       GtkCallback   callback,
1870                       gpointer      callback_data)
1871 {
1872   GtkTreeView *tree_view;
1873   GtkTreeViewChild *child = NULL;
1874   GtkTreeViewColumn *column;
1875   GList *tmp_list;
1876
1877   g_return_if_fail (container != NULL);
1878   g_return_if_fail (GTK_IS_TREE_VIEW (container));
1879   g_return_if_fail (callback != NULL);
1880
1881   tree_view = GTK_TREE_VIEW (container);
1882
1883   tmp_list = tree_view->priv->children;
1884   while (tmp_list)
1885     {
1886       child = tmp_list->data;
1887       tmp_list = tmp_list->next;
1888
1889       (* callback) (child->widget, callback_data);
1890     }
1891   if (include_internals == FALSE)
1892     return;
1893
1894   for (tmp_list = tree_view->priv->columns; tmp_list; tmp_list = tmp_list->next)
1895     {
1896       column = tmp_list->data;
1897       if (column->button)
1898         (* callback) (column->button, callback_data);
1899     }
1900 }
1901
1902 /* TreeModel Callbacks
1903  */
1904
1905 static void
1906 gtk_tree_view_changed (GtkTreeModel *model,
1907                        GtkTreePath  *path,
1908                        GtkTreeIter  *iter,
1909                        gpointer      data)
1910 {
1911   GtkTreeView *tree_view = (GtkTreeView *)data;
1912   GtkRBTree *tree;
1913   GtkRBNode *node;
1914   gint height;
1915   gboolean dirty_marked;
1916
1917   g_return_if_fail (path != NULL || iter != NULL);
1918
1919   if (path == NULL)
1920     path = gtk_tree_model_get_path (model, iter);
1921   else if (iter == NULL)
1922     gtk_tree_model_get_iter (model, iter, path);
1923
1924   if (_gtk_tree_view_find_node (tree_view,
1925                                 path,
1926                                 &tree,
1927                                 &node))
1928     /* We aren't actually showing the node */
1929     return;
1930
1931   dirty_marked = gtk_tree_view_discover_dirty_iter (tree_view,
1932                                                     iter,
1933                                                     gtk_tree_path_get_depth (path),
1934                                                     &height);
1935
1936   if (GTK_RBNODE_GET_HEIGHT (node) != height + TREE_VIEW_VERTICAL_SEPARATOR)
1937     {
1938       _gtk_rbtree_node_set_height (tree, node, height + TREE_VIEW_VERTICAL_SEPARATOR);
1939       gtk_widget_queue_resize (GTK_WIDGET (data));
1940       return;
1941     }
1942   if (dirty_marked)
1943     gtk_widget_queue_resize (GTK_WIDGET (data));
1944   else
1945     {
1946       /* FIXME: just redraw the node */
1947       gtk_widget_queue_draw (GTK_WIDGET (data));
1948     }
1949 }
1950
1951 static void
1952 gtk_tree_view_inserted (GtkTreeModel *model,
1953                         GtkTreePath  *path,
1954                         GtkTreeIter  *iter,
1955                         gpointer      data)
1956 {
1957   GtkTreeView *tree_view = (GtkTreeView *) data;
1958   gint *indices;
1959   GtkRBTree *tmptree, *tree;
1960   GtkRBNode *tmpnode = NULL;
1961   gint max_height;
1962   gint depth;
1963   gint i = 0;
1964
1965   tmptree = tree = tree_view->priv->tree;
1966   g_return_if_fail (path != NULL || iter != NULL);
1967
1968   if (path == NULL)
1969     path = gtk_tree_model_get_path (model, iter);
1970   else if (iter == NULL)
1971     gtk_tree_model_get_iter (model, iter, path);
1972
1973   depth = gtk_tree_path_get_depth (path);
1974   indices = gtk_tree_path_get_indices (path);
1975
1976   /* First, find the parent tree */
1977   while (i < depth - 1)
1978     {
1979       if (tmptree == NULL)
1980         {
1981           /* We aren't showing the node */
1982           return;
1983         }
1984
1985       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
1986       if (tmpnode == NULL)
1987         {
1988           g_warning ("A node was inserted with a parent that's not in the tree.\n" \
1989                      "This possibly means that a GtkTreeModel inserted a child node\n" \
1990                      "before the parent was inserted.");
1991           return;
1992         }
1993       else if (!GTK_RBNODE_FLAG_SET (tmpnode, GTK_RBNODE_IS_PARENT))
1994         {
1995           /* FIXME enforce correct behavior on model, probably */
1996           /* In theory, the model should have emitted child_toggled here.  We
1997            * try to catch it anyway, just to be safe, in case the model hasn't.
1998            */
1999           GtkTreePath *tmppath = _gtk_tree_view_find_path (tree_view,
2000                                                            tree,
2001                                                            tmpnode);
2002           gtk_tree_view_child_toggled (model, tmppath, NULL, data);
2003           gtk_tree_path_free (tmppath);
2004           return;
2005         }
2006
2007       tmptree = tmpnode->children;
2008       tree = tmptree;
2009       i++;
2010     }
2011
2012   if (tree == NULL)
2013     return;
2014
2015   /* next, update the selection */
2016   if (tree_view->priv->anchor)
2017     {
2018       gint *select_indices = gtk_tree_path_get_indices (tree_view->priv->anchor);
2019       gint select_depth = gtk_tree_path_get_depth (tree_view->priv->anchor);
2020
2021       for (i = 0; i < depth && i < select_depth; i++)
2022         {
2023           if (indices[i] < select_indices[i])
2024             {
2025               select_indices[i]++;
2026               break;
2027             }
2028           else if (indices[i] > select_indices[i])
2029             break;
2030           else if (i == depth - 1)
2031             {
2032               select_indices[i]++;
2033               break;
2034             }
2035         }
2036     }
2037
2038   /* ref the node */
2039   gtk_tree_model_ref_iter (tree_view->priv->model, iter);
2040   max_height = gtk_tree_view_insert_iter_height (tree_view,
2041                                                  tree,
2042                                                  iter,
2043                                                  depth);
2044   if (indices[depth - 1] == 0)
2045     {
2046       tmpnode = _gtk_rbtree_find_count (tree, 1);
2047       _gtk_rbtree_insert_before (tree, tmpnode, max_height);
2048     }
2049   else
2050     {
2051       tmpnode = _gtk_rbtree_find_count (tree, indices[depth - 1]);
2052       _gtk_rbtree_insert_after (tree, tmpnode, max_height);
2053     }
2054
2055   _gtk_tree_view_set_size (tree_view, -1, tree_view->priv->height + max_height);
2056 }
2057
2058 static void
2059 gtk_tree_view_child_toggled (GtkTreeModel *model,
2060                              GtkTreePath  *path,
2061                              GtkTreeIter  *iter,
2062                              gpointer      data)
2063 {
2064   GtkTreeView *tree_view = (GtkTreeView *)data;
2065   GtkTreeIter real_iter;
2066   gboolean has_child;
2067   GtkRBTree *tree;
2068   GtkRBNode *node;
2069
2070   g_return_if_fail (path != NULL || iter != NULL);
2071
2072   if (iter)
2073     real_iter = *iter;
2074
2075   if (path == NULL)
2076     path = gtk_tree_model_get_path (model, iter);
2077   else if (iter == NULL)
2078     gtk_tree_model_get_iter (model, &real_iter, path);
2079
2080   if (_gtk_tree_view_find_node (tree_view,
2081                                 path,
2082                                 &tree,
2083                                 &node))
2084     /* We aren't actually showing the node */
2085     return;
2086
2087   has_child = gtk_tree_model_iter_has_child (model, &real_iter);
2088   /* Sanity check.
2089    */
2090   if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT) == has_child)
2091     return;
2092
2093   if (has_child)
2094     GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_IS_PARENT);
2095   else
2096     GTK_RBNODE_UNSET_FLAG (node, GTK_RBNODE_IS_PARENT);
2097
2098   if (has_child && GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_IS_LIST))
2099     {
2100       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
2101       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_SHOW_EXPANDERS))
2102         {
2103           GList *list;
2104           for (list = tree_view->priv->columns; list; list = list->next)
2105             if (GTK_TREE_VIEW_COLUMN (list->data)->visible)
2106               {
2107                 GTK_TREE_VIEW_COLUMN (list->data)->dirty = TRUE;
2108                 break;
2109               }
2110         }
2111       gtk_widget_queue_resize (GTK_WIDGET (tree_view));
2112     }
2113   else
2114     {
2115       /* FIXME: Just redraw the node */
2116       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2117     }
2118 }
2119
2120 static void
2121 gtk_tree_view_deleted (GtkTreeModel *model,
2122                        GtkTreePath  *path,
2123                        gpointer      data)
2124 {
2125   GtkTreeView *tree_view = (GtkTreeView *)data;
2126   GtkRBTree *tree;
2127   GtkRBNode *node;
2128   GList *list;
2129
2130   g_return_if_fail (path != NULL);
2131
2132   if (_gtk_tree_view_find_node (tree_view, path, &tree, &node))
2133     return;
2134
2135   /* next, update the selection */
2136   if (tree_view->priv->anchor)
2137     {
2138       gint i;
2139       gint depth = gtk_tree_path_get_depth (path);
2140       gint *indices = gtk_tree_path_get_indices (path);
2141       gint select_depth = gtk_tree_path_get_depth (tree_view->priv->anchor);
2142       gint *select_indices = gtk_tree_path_get_indices (tree_view->priv->anchor);
2143
2144       if (gtk_tree_path_compare (path, tree_view->priv->anchor) == 0)
2145         {
2146           if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_SELECTED) &&
2147               tree_view->priv->selection)
2148             gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->selection),
2149                                      "selection_changed");
2150         }
2151       else
2152         {
2153           for (i = 0; i < depth && i < select_depth; i++)
2154             {
2155               if (indices[i] < select_indices[i])
2156                 {
2157                   select_indices[i] = MAX (select_indices[i], 0);
2158                   break;
2159                 }
2160               else if (indices[i] > select_indices[i])
2161                 break;
2162               else if (i == depth - 1)
2163                 {
2164                   select_indices[i] = MAX (select_indices[i], 0);
2165                   break;
2166                 }
2167             }
2168         }
2169     }
2170
2171   for (list = tree_view->priv->columns; list; list = list->next)
2172     if (((GtkTreeViewColumn *)list->data)->visible &&
2173         ((GtkTreeViewColumn *)list->data)->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2174       ((GtkTreeViewColumn *)list->data)->dirty = TRUE;
2175
2176   if (tree->root->count == 1)
2177     _gtk_rbtree_remove (tree);
2178   else
2179     _gtk_rbtree_remove_node (tree, node);
2180
2181   _gtk_tree_view_set_size (GTK_TREE_VIEW (data), -1, -1);
2182 }
2183
2184 /* Internal tree functions */
2185 static gint
2186 gtk_tree_view_insert_iter_height (GtkTreeView *tree_view,
2187                                   GtkRBTree   *tree,
2188                                   GtkTreeIter *iter,
2189                                   gint         depth)
2190 {
2191   GtkTreeViewColumn *column;
2192   GtkCellRenderer *cell;
2193   gboolean first = TRUE;
2194   GList *list;
2195   gint max_height = 0;
2196
2197   /* do stuff with node */
2198   for (list = tree_view->priv->columns; list; list = list->next)
2199     {
2200       gint height = 0, width = 0;
2201       column = list->data;
2202
2203       if (!column->visible)
2204         continue;
2205       if (column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2206         {
2207           first = FALSE;;
2208           continue;
2209         }
2210
2211       cell = column->cell;
2212       gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
2213
2214       gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &height);
2215       max_height = MAX (max_height, TREE_VIEW_VERTICAL_SEPARATOR + height);
2216
2217       if (first == TRUE && TREE_VIEW_DRAW_EXPANDERS (tree_view))
2218         column->width = MAX (column->width, depth * tree_view->priv->tab_offset + width);
2219       else
2220         column->width = MAX (column->width, width);
2221
2222       first = FALSE;
2223     }
2224   return max_height;
2225
2226 }
2227
2228 static void
2229 gtk_tree_view_build_tree (GtkTreeView *tree_view,
2230                           GtkRBTree   *tree,
2231                           GtkTreeIter *iter,
2232                           gint         depth,
2233                           gboolean     recurse,
2234                           gboolean     calc_bounds)
2235 {
2236   GtkRBNode *temp = NULL;
2237   gint max_height;
2238
2239   do
2240     {
2241       max_height = 0;
2242       if (calc_bounds)
2243         max_height = gtk_tree_view_insert_iter_height (tree_view,
2244                                                        tree,
2245                                                        iter,
2246                                                        depth);
2247
2248       gtk_tree_model_ref_iter (tree_view->priv->model, iter);
2249       temp = _gtk_rbtree_insert_after (tree, temp, max_height);
2250       if (recurse)
2251         {
2252           GtkTreeIter child;
2253
2254           if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
2255             {
2256               temp->children = _gtk_rbtree_new ();
2257               temp->children->parent_tree = tree;
2258               temp->children->parent_node = temp;
2259               gtk_tree_view_build_tree (tree_view, temp->children, &child, depth + 1, recurse, calc_bounds);
2260             }
2261         }
2262       if (gtk_tree_model_iter_has_child (tree_view->priv->model, iter))
2263         {
2264           if ((temp->flags&GTK_RBNODE_IS_PARENT) != GTK_RBNODE_IS_PARENT)
2265             temp->flags ^= GTK_RBNODE_IS_PARENT;
2266           GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_IS_LIST);
2267         }
2268     }
2269   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
2270 }
2271
2272 static void
2273 gtk_tree_view_calc_size (GtkTreeView *tree_view,
2274                          GtkRBTree   *tree,
2275                          GtkTreeIter *iter,
2276                          gint         depth)
2277 {
2278   GtkRBNode *temp;
2279   GtkTreeIter child;
2280   GtkCellRenderer *cell;
2281   GList *list;
2282   GtkTreeViewColumn *column;
2283   gint max_height;
2284   gint i;
2285
2286   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
2287
2288   temp = tree->root;
2289   while (temp->left != tree->nil)
2290     temp = temp->left;
2291
2292   do
2293     {
2294       max_height = 0;
2295       /* Do stuff with node */
2296       for (list = tree_view->priv->columns, i = 0; i < tree_view->priv->n_columns; list = list->next, i++)
2297         {
2298           gint height = 0, width = 0;
2299           column = list->data;
2300
2301           if (!column->visible)
2302             continue;
2303
2304           gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
2305           cell = column->cell;
2306           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &height);
2307           max_height = MAX (max_height, TREE_VIEW_VERTICAL_SEPARATOR + height);
2308
2309           /* FIXME: I'm getting the width of all nodes here. )-: */
2310           if (column->dirty == FALSE || column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2311             continue;
2312
2313           if (i == 0 && TREE_VIEW_DRAW_EXPANDERS (tree_view))
2314             column->width = MAX (column->width, depth * tree_view->priv->tab_offset + width);
2315           else
2316             column->width = MAX (column->width, width);
2317         }
2318       _gtk_rbtree_node_set_height (tree, temp, max_height);
2319       if (temp->children != NULL &&
2320           gtk_tree_model_iter_children (tree_view->priv->model, &child, iter))
2321         gtk_tree_view_calc_size (tree_view, temp->children, &child, depth + 1);
2322       temp = _gtk_rbtree_next (tree, temp);
2323     }
2324   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
2325 }
2326
2327 static gboolean
2328 gtk_tree_view_discover_dirty_iter (GtkTreeView *tree_view,
2329                                    GtkTreeIter *iter,
2330                                    gint         depth,
2331                                    gint        *height)
2332 {
2333   GtkCellRenderer *cell;
2334   GtkTreeViewColumn *column;
2335   GList *list;
2336   gint i;
2337   gint retval = FALSE;
2338   gint tmpheight;
2339
2340   if (height)
2341     *height = 0;
2342
2343   for (i = 0, list = tree_view->priv->columns; list; list = list->next, i++)
2344     {
2345       gint width;
2346       column = list->data;
2347       if (column->dirty == TRUE || column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2348         continue;
2349       if (!column->visible)
2350         continue;
2351
2352       cell = column->cell;
2353       gtk_tree_view_column_set_cell_data (column, tree_view->priv->model, iter);
2354
2355       if (height)
2356         {
2357           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, &tmpheight);
2358           *height = MAX (*height, tmpheight);
2359         }
2360       else
2361         {
2362           gtk_cell_renderer_get_size (cell, GTK_WIDGET (tree_view), &width, NULL);
2363         }
2364       if (i == 0 && TREE_VIEW_DRAW_EXPANDERS (tree_view))
2365         {
2366           if (depth * tree_view->priv->tab_offset + width > column->width)
2367             {
2368               column->dirty = TRUE;
2369               retval = TRUE;
2370             }
2371         }
2372       else
2373         {
2374           if (width > column->width)
2375             {
2376               column->dirty = TRUE;
2377               retval = TRUE;
2378             }
2379         }
2380     }
2381
2382   return retval;
2383 }
2384
2385 static void
2386 gtk_tree_view_discover_dirty (GtkTreeView *tree_view,
2387                               GtkRBTree   *tree,
2388                               GtkTreeIter *iter,
2389                               gint         depth)
2390 {
2391   GtkRBNode *temp = tree->root;
2392   GtkTreeViewColumn *column;
2393   GList *list;
2394   GtkTreeIter child;
2395   gboolean is_all_dirty;
2396
2397   TREE_VIEW_INTERNAL_ASSERT_VOID (tree != NULL);
2398
2399   while (temp->left != tree->nil)
2400     temp = temp->left;
2401
2402   do
2403     {
2404       is_all_dirty = TRUE;
2405       for (list = tree_view->priv->columns; list; list = list->next)
2406         {
2407           column = list->data;
2408           if (column->dirty == FALSE)
2409             {
2410               is_all_dirty = FALSE;
2411               break;
2412             }
2413         }
2414
2415       if (is_all_dirty)
2416         return;
2417
2418       gtk_tree_view_discover_dirty_iter (tree_view,
2419                                          iter,
2420                                          depth,
2421                                          FALSE);
2422       if (gtk_tree_model_iter_children (tree_view->priv->model, &child, iter) &&
2423           temp->children != NULL)
2424         gtk_tree_view_discover_dirty (tree_view, temp->children, &child, depth + 1);
2425       temp = _gtk_rbtree_next (tree, temp);
2426     }
2427   while (gtk_tree_model_iter_next (tree_view->priv->model, iter));
2428 }
2429
2430
2431 static void
2432 gtk_tree_view_check_dirty (GtkTreeView *tree_view)
2433 {
2434   GtkTreePath *path;
2435   gboolean dirty = FALSE;
2436   GList *list;
2437   GtkTreeViewColumn *column;
2438   GtkTreeIter iter;
2439   
2440   for (list = tree_view->priv->columns; list; list = list->next)
2441     {
2442       column = list->data;
2443       if (column->dirty)
2444         {
2445           dirty = TRUE;
2446           if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2447             {
2448               column->width = column->button->requisition.width;
2449             }
2450         }
2451     }
2452   if (dirty == FALSE)
2453     return;
2454
2455   path = gtk_tree_path_new_root ();
2456   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
2457     {
2458       gtk_tree_view_calc_size (tree_view, tree_view->priv->tree, &iter, 1);
2459       _gtk_tree_view_set_size (tree_view, -1, -1);
2460     }
2461       
2462   gtk_tree_path_free (path);
2463   
2464   for (list = tree_view->priv->columns; list; list = list->next)
2465     {
2466       column = list->data;
2467       column->dirty = FALSE;
2468     }
2469 }
2470
2471 static void
2472 gtk_tree_view_create_button (GtkTreeView *tree_view,
2473                              gint         i)
2474 {
2475   GtkWidget *button;
2476   GtkTreeViewColumn *column;
2477
2478   column = g_list_nth (tree_view->priv->columns, i)->data;
2479   gtk_widget_push_composite_child ();
2480   button = column->button = gtk_button_new ();
2481   gtk_widget_pop_composite_child ();
2482
2483   gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
2484
2485   gtk_signal_connect (GTK_OBJECT (button), "clicked",
2486                       (GtkSignalFunc) gtk_tree_view_button_clicked,
2487                       (gpointer) tree_view);
2488
2489   gtk_widget_show (button);
2490 }
2491
2492 static void
2493 gtk_tree_view_create_buttons (GtkTreeView *tree_view)
2494 {
2495   GtkWidget *alignment;
2496   GtkWidget *label;
2497   GtkRequisition requisition;
2498   GList *list;
2499   GtkTreeViewColumn *column;
2500   gint i;
2501
2502   for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
2503     {
2504       column = list->data;
2505
2506       if (column->button != NULL)
2507         continue;
2508
2509       gtk_tree_view_create_button (tree_view, i);
2510       switch (column->justification)
2511         {
2512         case GTK_JUSTIFY_LEFT:
2513           alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
2514           break;
2515         case GTK_JUSTIFY_RIGHT:
2516           alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
2517           break;
2518         case GTK_JUSTIFY_CENTER:
2519           alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
2520           break;
2521         case GTK_JUSTIFY_FILL:
2522         default:
2523           alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
2524           break;
2525         }
2526       label = gtk_label_new (column->title);
2527
2528       gtk_container_add (GTK_CONTAINER (alignment), label);
2529       gtk_container_add (GTK_CONTAINER (column->button), alignment);
2530
2531       gtk_widget_show (label);
2532       gtk_widget_show (alignment);
2533     }
2534
2535   gtk_tree_view_size_request_buttons (tree_view);
2536   
2537   if (GTK_WIDGET_REALIZED (tree_view))
2538     gtk_tree_view_realize_buttons (tree_view);
2539
2540   if (GTK_WIDGET_MAPPED (tree_view))
2541     gtk_tree_view_map_buttons (tree_view);  
2542 }
2543
2544 static void
2545 gtk_tree_view_button_clicked (GtkWidget *widget,
2546                               gpointer   data)
2547 {
2548   GList *list;
2549   GtkTreeView *tree_view;
2550
2551   g_return_if_fail (widget != NULL);
2552   g_return_if_fail (GTK_IS_TREE_VIEW (data));
2553
2554   tree_view = GTK_TREE_VIEW (data);
2555
2556   /* find the column whose button was pressed */
2557   for (list = tree_view->priv->columns; list; list = list->next)
2558     if (GTK_TREE_VIEW_COLUMN (list->data)->button == widget)
2559       break;
2560
2561   if (list)
2562     gtk_tree_view_column_clicked (GTK_TREE_VIEW_COLUMN (list->data));
2563 }
2564
2565 /* Make sure the node is visible vertically */
2566 static void
2567 gtk_tree_view_clamp_node_visible (GtkTreeView *tree_view,
2568                                   GtkRBTree   *tree,
2569                                   GtkRBNode   *node)
2570 {
2571   gint offset;
2572
2573   offset = _gtk_rbtree_node_find_offset (tree, node);
2574
2575   /* we reverse the order, b/c in the unusual case of the
2576    * node's height being taller then the visible area, we'd rather
2577    * have the node flush to the top
2578    */
2579   if (offset + GTK_RBNODE_GET_HEIGHT (node) >
2580       tree_view->priv->vadjustment->value + tree_view->priv->vadjustment->page_size)
2581     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
2582                               offset + GTK_RBNODE_GET_HEIGHT (node) -
2583                               tree_view->priv->vadjustment->page_size);
2584   if (offset < tree_view->priv->vadjustment->value)
2585     gtk_adjustment_set_value (GTK_ADJUSTMENT (tree_view->priv->vadjustment),
2586                               offset);
2587 }
2588
2589 /* This function could be more efficient.
2590  * I'll optimize it if profiling seems to imply that
2591  * it's important
2592  */
2593 GtkTreePath *
2594 _gtk_tree_view_find_path (GtkTreeView *tree_view,
2595                           GtkRBTree   *tree,
2596                           GtkRBNode   *node)
2597 {
2598   GtkTreePath *path;
2599   GtkRBTree *tmp_tree;
2600   GtkRBNode *tmp_node, *last;
2601   gint count;
2602
2603   path = gtk_tree_path_new ();
2604
2605   g_return_val_if_fail (node != NULL, path);
2606   g_return_val_if_fail (node != tree->nil, path);
2607
2608   count = 1 + node->left->count;
2609
2610   last = node;
2611   tmp_node = node->parent;
2612   tmp_tree = tree;
2613   while (tmp_tree)
2614     {
2615       while (tmp_node != tmp_tree->nil)
2616         {
2617           if (tmp_node->right == last)
2618             count += 1 + tmp_node->left->count;
2619           last = tmp_node;
2620           tmp_node = tmp_node->parent;
2621         }
2622       gtk_tree_path_prepend_index (path, count - 1);
2623       last = tmp_tree->parent_node;
2624       tmp_tree = tmp_tree->parent_tree;
2625       if (last)
2626         {
2627           count = 1 + last->left->count;
2628           tmp_node = last->parent;
2629         }
2630     }
2631   return path;
2632 }
2633
2634 /* Returns whether or not it's a parent, or not */
2635 gboolean
2636 _gtk_tree_view_find_node (GtkTreeView  *tree_view,
2637                           GtkTreePath  *path,
2638                           GtkRBTree   **tree,
2639                           GtkRBNode   **node)
2640 {
2641   GtkRBNode *tmpnode = NULL;
2642   GtkRBTree *tmptree = tree_view->priv->tree;
2643   gint *indices = gtk_tree_path_get_indices (path);
2644   gint depth = gtk_tree_path_get_depth (path);
2645   gint i = 0;
2646
2647   *node = NULL;
2648   *tree = NULL;
2649
2650   do
2651     {
2652       if (tmptree == NULL)
2653         {
2654           *node = tmpnode;
2655           *tree = tmptree;
2656           return TRUE;
2657         }
2658       tmpnode = _gtk_rbtree_find_count (tmptree, indices[i] + 1);
2659       if (++i >= depth)
2660         {
2661           *node = tmpnode;
2662           *tree = tmptree;
2663           return FALSE;
2664         }
2665       tmptree = tmpnode->children;
2666     }
2667   while (1);
2668 }
2669
2670 /* x and y are the mouse position
2671  */
2672 static void
2673 gtk_tree_view_draw_arrow (GtkTreeView *tree_view,
2674                           GtkRBNode   *node,
2675                           gint         offset,
2676                           gint         x,
2677                           gint         y)
2678 {
2679   GdkRectangle area;
2680   GtkStateType state;
2681   GdkPoint points[3];
2682   GtkWidget *widget;
2683   
2684   if (! GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT))
2685     return;
2686
2687   widget = GTK_WIDGET (tree_view);
2688   
2689   area.x = 0;
2690   area.y = offset + TREE_VIEW_VERTICAL_SEPARATOR;
2691   area.width = tree_view->priv->tab_offset - 2;
2692   area.height = GTK_RBNODE_GET_HEIGHT (node) - TREE_VIEW_VERTICAL_SEPARATOR;
2693
2694   if (node == tree_view->priv->button_pressed_node)
2695     {
2696       if (x >= area.x && x <= (area.x + area.width) &&
2697           y >= area.y && y <= (area.y + area.height))
2698         state = GTK_STATE_ACTIVE;
2699       else
2700         state = GTK_STATE_NORMAL;
2701     }
2702   else
2703     {
2704       state = (node==tree_view->priv->prelight_node&&GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_ARROW_PRELIT)?GTK_STATE_PRELIGHT:GTK_STATE_NORMAL);
2705     }
2706
2707   /* FIXME expander size should come from a style property */
2708 #define EXPANDER_SIZE 8
2709   gtk_paint_expander (widget->style,
2710                       tree_view->priv->bin_window,
2711                       state,
2712                       &area,
2713                       widget,
2714                       "treeview",
2715                       area.x,
2716                       (area.y + (area.height - EXPANDER_SIZE) / 2 - (area.height + 1) % 2),
2717                       node->children != NULL);
2718 #undef EXPANDER_SIZE
2719 }
2720
2721 void
2722 _gtk_tree_view_set_size (GtkTreeView     *tree_view,
2723                          gint             width,
2724                          gint             height)
2725 {
2726   GList *list;
2727   GtkTreeViewColumn *column;
2728   gint i;
2729
2730   if (width == tree_view->priv->width &&
2731       height == tree_view->priv->height)
2732     return;
2733   
2734   if (tree_view->priv->model == NULL)
2735     {
2736       tree_view->priv->width = width;
2737       tree_view->priv->height = height;
2738       gtk_widget_queue_draw (GTK_WIDGET (tree_view));
2739       return;
2740     }
2741   if (width == -1)
2742     {
2743       width = 0;
2744       for (list = tree_view->priv->columns, i = 0; list; list = list->next, i++)
2745         {
2746           column = list->data;
2747           if (!column->visible)
2748             continue;
2749           width += TREE_VIEW_COLUMN_WIDTH (column);
2750         }
2751     }
2752   if (height == -1)
2753     height = tree_view->priv->tree->root->offset + TREE_VIEW_VERTICAL_SEPARATOR;
2754
2755   tree_view->priv->width = width;
2756   tree_view->priv->height = height;
2757
2758   if (tree_view->priv->hadjustment->upper != tree_view->priv->width)
2759     {
2760       tree_view->priv->hadjustment->upper = tree_view->priv->width;
2761       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->hadjustment), "changed");
2762     }
2763
2764   if (tree_view->priv->vadjustment->upper != tree_view->priv->height)
2765     {
2766       tree_view->priv->vadjustment->upper = tree_view->priv->height;
2767       gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
2768     }
2769
2770   if (GTK_WIDGET_REALIZED (tree_view))
2771     {
2772       gdk_window_resize (tree_view->priv->bin_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), height + TREE_VIEW_HEADER_HEIGHT (tree_view));
2773       gdk_window_resize (tree_view->priv->header_window, MAX (width, GTK_WIDGET (tree_view)->allocation.width), tree_view->priv->header_height);
2774     }
2775   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
2776 }
2777
2778 /* this function returns the new width of the column being resized given
2779  * the column and x position of the cursor; the x cursor position is passed
2780  * in as a pointer and automagicly corrected if it's beyond min/max limits
2781  */
2782 static gint
2783 gtk_tree_view_new_column_width (GtkTreeView *tree_view,
2784                                 gint       i,
2785                                 gint      *x)
2786 {
2787   GtkTreeViewColumn *column;
2788   gint width;
2789
2790   /* first translate the x position from widget->window
2791    * to clist->clist_window
2792    */
2793
2794   column = g_list_nth (tree_view->priv->columns, i)->data;
2795   width = *x - column->button->allocation.x;
2796
2797   /* Clamp down the value */
2798   if (column->min_width == -1)
2799     width = MAX (column->button->requisition.width,
2800                  width);
2801   else
2802     width = MAX (column->min_width,
2803                  width);
2804   if (column->max_width != -1)
2805     width = MIN (width, column->max_width != -1);
2806   *x = column->button->allocation.x + width;
2807
2808   return width;
2809 }
2810
2811 /* Callbacks */
2812 static void
2813 gtk_tree_view_adjustment_changed (GtkAdjustment *adjustment,
2814                                   GtkTreeView     *tree_view)
2815 {
2816   if (GTK_WIDGET_REALIZED (tree_view))
2817     {
2818       gdk_window_move (tree_view->priv->bin_window,
2819                        - tree_view->priv->hadjustment->value,
2820                        - tree_view->priv->vadjustment->value);
2821       gdk_window_move (tree_view->priv->header_window,
2822                        - tree_view->priv->hadjustment->value,
2823                        0);
2824
2825       gdk_window_process_updates (tree_view->priv->bin_window, TRUE);
2826       gdk_window_process_updates (tree_view->priv->header_window, TRUE);
2827     }
2828 }
2829
2830 \f
2831
2832 /* Public methods
2833  */
2834
2835 /**
2836  * gtk_tree_view_new:
2837  * 
2838  * Creates a new #GtkTreeView widget.
2839  * 
2840  * Return value: A newly created #GtkTreeView widget.
2841  **/
2842 GtkWidget *
2843 gtk_tree_view_new (void)
2844 {
2845   GtkTreeView *tree_view;
2846
2847   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
2848
2849   return GTK_WIDGET (tree_view);
2850 }
2851
2852 /**
2853  * gtk_tree_view_new_with_model:
2854  * @model: the model.
2855  * 
2856  * Creates a new #GtkTreeView widget with the model initialized to @model.
2857  * 
2858  * Return value: A newly created #GtkTreeView widget.
2859  **/
2860 GtkWidget *
2861 gtk_tree_view_new_with_model (GtkTreeModel *model)
2862 {
2863   GtkTreeView *tree_view;
2864
2865   tree_view = GTK_TREE_VIEW (gtk_type_new (gtk_tree_view_get_type ()));
2866   gtk_tree_view_set_model (tree_view, model);
2867
2868   return GTK_WIDGET (tree_view);
2869 }
2870
2871 /**
2872  * gtk_tree_view_get_model:
2873  * @tree_view: a #GtkTreeView
2874  * 
2875  * Returns the model the the #GtkTreeView is based on.  Returns NULL if the
2876  * model is unset.
2877  * 
2878  * Return value: A #GtkTreeModel, or NULL if none is currently being used.
2879  **/
2880 GtkTreeModel *
2881 gtk_tree_view_get_model (GtkTreeView *tree_view)
2882 {
2883   g_return_val_if_fail (tree_view != NULL, NULL);
2884   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
2885
2886   return tree_view->priv->model;
2887 }
2888
2889 static void
2890 gtk_tree_view_setup_model (GtkTreeView *tree_view)
2891 {
2892   GtkTreePath *path;
2893   GtkTreeIter iter;
2894
2895   tree_view->priv->tree = _gtk_rbtree_new ();
2896
2897   gtk_signal_connect (GTK_OBJECT (tree_view->priv->model),
2898                       "changed",
2899                       gtk_tree_view_changed,
2900                       tree_view);
2901   gtk_signal_connect (GTK_OBJECT (tree_view->priv->model),
2902                       "inserted",
2903                       gtk_tree_view_inserted,
2904                       tree_view);
2905   gtk_signal_connect (GTK_OBJECT (tree_view->priv->model),
2906                       "child_toggled",
2907                       gtk_tree_view_child_toggled,
2908                       tree_view);
2909   gtk_signal_connect (GTK_OBJECT (tree_view->priv->model),
2910                       "deleted",
2911                       gtk_tree_view_deleted,
2912                       tree_view);
2913
2914   if (tree_view->priv->columns == NULL)
2915     return;
2916
2917   path = gtk_tree_path_new_root ();
2918
2919   if (gtk_tree_model_get_iter (tree_view->priv->model, &iter, path))
2920     {
2921       gtk_tree_view_build_tree (tree_view, tree_view->priv->tree, &iter, 1, FALSE, GTK_WIDGET_REALIZED (tree_view));
2922     }
2923   
2924   gtk_tree_path_free (path);
2925
2926   gtk_tree_view_create_buttons (tree_view);
2927
2928   GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
2929 }
2930
2931 /**
2932  * gtk_tree_view_set_model:
2933  * @tree_view: A #GtkTreeNode.
2934  * @model: The model.
2935  * 
2936  * Sets the model for a #GtkTreeView.  If the @tree_view already has a model
2937  * set, it will remove it before setting the new model.  If @model is NULL, then
2938  * it will unset the old model.
2939  **/
2940 void
2941 gtk_tree_view_set_model (GtkTreeView  *tree_view,
2942                          GtkTreeModel *model)
2943 {
2944   GList *list;
2945   GtkTreeViewColumn *column;
2946
2947   g_return_if_fail (tree_view != NULL);
2948   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
2949
2950   if (tree_view->priv->model != NULL)
2951     {
2952
2953       /* No longer do this. */
2954 #if 0
2955       for (list = tree_view->priv->columns; list; list = list->next)
2956         {
2957           column = list->data;
2958           if (column->button)
2959             {
2960               gtk_widget_unparent (column->button);
2961               gdk_window_set_user_data (column->window, NULL);
2962               gdk_window_destroy (column->window);
2963             }
2964         }
2965 #endif
2966       if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_MODEL_SETUP))
2967         {
2968           gtk_signal_disconnect_by_func (GTK_OBJECT (tree_view->priv->model),
2969                                          gtk_tree_view_changed,
2970                                          tree_view);
2971           gtk_signal_disconnect_by_func (GTK_OBJECT (tree_view->priv->model),
2972                                          gtk_tree_view_inserted,
2973                                          tree_view);
2974           gtk_signal_disconnect_by_func (GTK_OBJECT (tree_view->priv->model),
2975                                          gtk_tree_view_child_toggled,
2976                                          tree_view);
2977           gtk_signal_disconnect_by_func (GTK_OBJECT (tree_view->priv->model),
2978                                          gtk_tree_view_deleted,
2979                                          tree_view);
2980           _gtk_rbtree_free (tree_view->priv->tree);
2981         }
2982 #if 0
2983       g_list_free (tree_view->priv->columns);
2984       tree_view->priv->columns = NULL;
2985 #endif
2986       GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_MODEL_SETUP);
2987     }
2988
2989   tree_view->priv->model = model;
2990   if (model == NULL)
2991     {
2992       tree_view->priv->tree = NULL;
2993       if (GTK_WIDGET_REALIZED (tree_view))
2994         _gtk_tree_view_set_size (tree_view, 0, 0);
2995       return;
2996     }
2997   else if (GTK_WIDGET_REALIZED (tree_view))
2998     {
2999       gtk_tree_view_setup_model (tree_view);
3000       _gtk_tree_view_set_size (tree_view, -1, -1);
3001     }
3002 }
3003
3004 /**
3005  * gtk_tree_view_get_selection:
3006  * @tree_view: A #GtkTreeView.
3007  * 
3008  * Gets the #GtkTreeSelection associated with @tree_view.
3009  * 
3010  * Return value: A #GtkTreeSelection object.
3011  **/
3012 GtkTreeSelection *
3013 gtk_tree_view_get_selection (GtkTreeView *tree_view)
3014 {
3015   g_return_val_if_fail (tree_view != NULL, NULL);
3016   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3017
3018   if (tree_view->priv->selection == NULL)
3019     tree_view->priv->selection =
3020       _gtk_tree_selection_new_with_tree_view (tree_view);
3021
3022   return tree_view->priv->selection;
3023 }
3024
3025 /**
3026  * gtk_tree_view_get_hadjustment:
3027  * @tree_view: A #GtkTreeView
3028  * 
3029  * Gets the #GtkAdjustment currently being used for the horizontal aspect.
3030  * 
3031  * Return value: A #GtkAdjustment object, or NULL if none is currently being
3032  * used.
3033  **/
3034 GtkAdjustment *
3035 gtk_tree_view_get_hadjustment (GtkTreeView *tree_view)
3036 {
3037   g_return_val_if_fail (tree_view != NULL, NULL);
3038   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3039
3040   if (tree_view->priv->hadjustment == NULL)
3041     gtk_tree_view_set_hadjustment (tree_view, NULL);
3042   
3043   return tree_view->priv->hadjustment;
3044 }
3045
3046 /**
3047  * gtk_tree_view_set_hadjustment:
3048  * @tree_view: A #GtkTreeView
3049  * @adjustment: The #GtkAdjustment to set, or NULL
3050  * 
3051  * Sets the #GtkAdjustment for the current horizontal aspect.
3052  **/
3053 void
3054 gtk_tree_view_set_hadjustment (GtkTreeView   *tree_view,
3055                                GtkAdjustment *adjustment)
3056 {
3057   g_return_if_fail (tree_view != NULL);
3058   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3059
3060   gtk_tree_view_set_adjustments (tree_view,
3061                                  adjustment,
3062                                  tree_view->priv->vadjustment);
3063 }
3064
3065 /**
3066  * gtk_tree_view_get_vadjustment:
3067  * @tree_view: A #GtkTreeView
3068  * 
3069  * Gets the #GtkAdjustment currently being used for the vertical aspect.
3070  * 
3071  * Return value: A #GtkAdjustment object, or NULL if none is currently being
3072  * used.
3073  **/
3074 GtkAdjustment *
3075 gtk_tree_view_get_vadjustment (GtkTreeView *tree_view)
3076 {
3077   g_return_val_if_fail (tree_view != NULL, NULL);
3078   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3079
3080   if (tree_view->priv->vadjustment == NULL)
3081     gtk_tree_view_set_vadjustment (tree_view, NULL);
3082   
3083   return tree_view->priv->vadjustment;
3084 }
3085
3086 /**
3087  * gtk_tree_view_set_vadjustment:
3088  * @tree_view: A #GtkTreeView
3089  * @adjustment: The #GtkAdjustment to set, or NULL
3090  * 
3091  * Sets the #GtkAdjustment for the current vertical aspect.
3092  **/
3093 void
3094 gtk_tree_view_set_vadjustment (GtkTreeView   *tree_view,
3095                                GtkAdjustment *adjustment)
3096 {
3097   g_return_if_fail (tree_view != NULL);
3098   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3099
3100   gtk_tree_view_set_adjustments (tree_view,
3101                                  tree_view->priv->hadjustment,
3102                                  adjustment);
3103 }
3104
3105 /**
3106  * gtk_tree_view_set_adjustments:
3107  * @tree_view: A #GtkTreeView
3108  * @hadj: The horizontal #GtkAdjustment to set, or NULL
3109  * @vadj: The vertical #GtkAdjustment to set, or NULL
3110  * 
3111  * Sets the horizonal and or vertical #GtkAdjustment.
3112  **/
3113 static void
3114 gtk_tree_view_set_adjustments (GtkTreeView   *tree_view,
3115                                GtkAdjustment *hadj,
3116                                GtkAdjustment *vadj)
3117 {
3118   gboolean need_adjust = FALSE;
3119
3120   g_return_if_fail (tree_view != NULL);
3121   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3122
3123   if (hadj)
3124     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
3125   else
3126     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
3127   if (vadj)
3128     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
3129   else
3130     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
3131
3132   if (tree_view->priv->hadjustment && (tree_view->priv->hadjustment != hadj))
3133     {
3134       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->hadjustment), tree_view);
3135       gtk_object_unref (GTK_OBJECT (tree_view->priv->hadjustment));
3136     }
3137
3138   if (tree_view->priv->vadjustment && (tree_view->priv->vadjustment != vadj))
3139     {
3140       gtk_signal_disconnect_by_data (GTK_OBJECT (tree_view->priv->vadjustment), tree_view);
3141       gtk_object_unref (GTK_OBJECT (tree_view->priv->vadjustment));
3142     }
3143
3144   if (tree_view->priv->hadjustment != hadj)
3145     {
3146       tree_view->priv->hadjustment = hadj;
3147       gtk_object_ref (GTK_OBJECT (tree_view->priv->hadjustment));
3148       gtk_object_sink (GTK_OBJECT (tree_view->priv->hadjustment));
3149
3150       gtk_signal_connect (GTK_OBJECT (tree_view->priv->hadjustment), "value_changed",
3151                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
3152                           tree_view);
3153       need_adjust = TRUE;
3154     }
3155
3156   if (tree_view->priv->vadjustment != vadj)
3157     {
3158       tree_view->priv->vadjustment = vadj;
3159       gtk_object_ref (GTK_OBJECT (tree_view->priv->vadjustment));
3160       gtk_object_sink (GTK_OBJECT (tree_view->priv->vadjustment));
3161
3162       gtk_signal_connect (GTK_OBJECT (tree_view->priv->vadjustment), "value_changed",
3163                           (GtkSignalFunc) gtk_tree_view_adjustment_changed,
3164                           tree_view);
3165       need_adjust = TRUE;
3166     }
3167
3168   if (need_adjust)
3169     gtk_tree_view_adjustment_changed (NULL, tree_view);
3170 }
3171
3172
3173 /* Column and header operations */
3174
3175 /**
3176  * gtk_tree_view_get_headers_visible:
3177  * @tree_view: A #GtkTreeView.
3178  * 
3179  * Returns TRUE if the headers on the @tree_view are visible.
3180  * 
3181  * Return value: Whether the headers are visible or not.
3182  **/
3183 gboolean
3184 gtk_tree_view_get_headers_visible (GtkTreeView *tree_view)
3185 {
3186   g_return_val_if_fail (tree_view != NULL, FALSE);
3187   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
3188
3189   return GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3190 }
3191
3192 /**
3193  * gtk_tree_view_set_headers_visible:
3194  * @tree_view: A #GtkTreeView.
3195  * @headers_visible: TRUE if the headers are visible
3196  * 
3197  * Sets the the visibility state of the headers.
3198  **/
3199 void
3200 gtk_tree_view_set_headers_visible (GtkTreeView *tree_view,
3201                                    gboolean     headers_visible)
3202 {
3203   gint x, y;
3204   GList *list;
3205   GtkTreeViewColumn *column;
3206
3207   g_return_if_fail (tree_view != NULL);
3208   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3209
3210   headers_visible = !! headers_visible;
3211   
3212   if (GTK_TREE_VIEW_FLAG_SET (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE) == headers_visible)
3213     return;
3214
3215   if (headers_visible)
3216     GTK_TREE_VIEW_SET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3217   else
3218     GTK_TREE_VIEW_UNSET_FLAG (tree_view, GTK_TREE_VIEW_HEADERS_VISIBLE);
3219
3220   if (GTK_WIDGET_REALIZED (tree_view))
3221     {
3222       gdk_window_get_position (tree_view->priv->bin_window, &x, &y);
3223       if (headers_visible)
3224         {
3225           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height + TREE_VIEW_HEADER_HEIGHT (tree_view));
3226           
3227           if (GTK_WIDGET_MAPPED (tree_view))
3228             gtk_tree_view_map_buttons (tree_view);
3229         }
3230       else
3231         {
3232           gdk_window_move_resize (tree_view->priv->bin_window, x, y, tree_view->priv->width, tree_view->priv->height);
3233
3234           for (list = tree_view->priv->columns; list; list = list->next)
3235             {
3236               column = list->data;
3237               gtk_widget_unmap (column->button);
3238             }
3239           gdk_window_hide (tree_view->priv->header_window);
3240         }
3241     }
3242
3243   tree_view->priv->vadjustment->page_size = GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view);
3244   tree_view->priv->vadjustment->page_increment = (GTK_WIDGET (tree_view)->allocation.height - TREE_VIEW_HEADER_HEIGHT (tree_view)) / 2;
3245   tree_view->priv->vadjustment->lower = 0;
3246   tree_view->priv->vadjustment->upper = tree_view->priv->height;
3247   gtk_signal_emit_by_name (GTK_OBJECT (tree_view->priv->vadjustment), "changed");
3248
3249   gtk_widget_queue_resize (GTK_WIDGET (tree_view));
3250 }
3251
3252
3253 /**
3254  * gtk_tree_view_columns_autosize:
3255  * @tree_view: A #GtkTreeView.
3256  * 
3257  * Resizes all columns to their optimal width.
3258  **/
3259 void
3260 gtk_tree_view_columns_autosize (GtkTreeView *tree_view)
3261 {
3262   gboolean dirty = FALSE;
3263   GList *list;
3264   GtkTreeViewColumn *column;
3265
3266   g_return_if_fail (tree_view != NULL);
3267   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3268
3269   for (list = tree_view->priv->columns; list; list = list->next)
3270     {
3271       column = list->data;
3272       if (column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
3273         continue;
3274       column->dirty = TRUE;
3275       dirty = TRUE;
3276     }
3277
3278   if (dirty)
3279     gtk_widget_queue_resize (GTK_WIDGET (tree_view));
3280 }
3281
3282 /* FIXME let's rename this to be "interactive" or something,
3283  * "active" is confusing since it also is a widget state
3284  */
3285 /**
3286  * gtk_tree_view_set_headers_clickable:
3287  * @tree_view: A #GtkTreeView.
3288  * @setting: TRUE if the columns are clickable.
3289  * 
3290  * Allow the column title buttons to be clicked.
3291  **/
3292 void
3293 gtk_tree_view_set_headers_clickable (GtkTreeView *tree_view,
3294                                      gboolean   setting)
3295 {
3296   GList *list;
3297
3298   g_return_if_fail (tree_view != NULL);
3299   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3300   g_return_if_fail (tree_view->priv->model != NULL);
3301
3302   for (list = tree_view->priv->columns; list; list = list->next)
3303     gtk_tree_view_column_set_header_clickable (GTK_TREE_VIEW_COLUMN (list->data), setting);
3304 }
3305
3306 /**
3307  * gtk_tree_view_append_column:
3308  * @tree_view: A #GtkTreeView.
3309  * @column: The #GtkTreeViewColumn to add.
3310  * 
3311  * Appends @column to the list of columns.
3312  * 
3313  * Return value: The number of columns in @tree_view after appending.
3314  **/
3315 gint
3316 gtk_tree_view_append_column (GtkTreeView       *tree_view,
3317                              GtkTreeViewColumn *column)
3318 {
3319   g_return_val_if_fail (tree_view != NULL, -1);
3320   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
3321   g_return_val_if_fail (column != NULL, -1);
3322   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
3323   g_return_val_if_fail (column->tree_view == NULL, -1);
3324
3325   g_object_ref (G_OBJECT (column));
3326   tree_view->priv->columns = g_list_append (tree_view->priv->columns,
3327                                             column);
3328   column->tree_view = GTK_WIDGET (tree_view);
3329
3330   tree_view->priv->n_columns++;
3331
3332   /* FIXME create header for the new column! */
3333   
3334   return tree_view->priv->n_columns;
3335 }
3336
3337
3338 /**
3339  * gtk_tree_view_remove_column:
3340  * @tree_view: A #GtkTreeView.
3341  * @column: The #GtkTreeViewColumn to remove.
3342  * 
3343  * Removes @column from @tree_view.
3344  * 
3345  * Return value: The number of columns in @tree_view after removing.
3346  **/
3347 gint
3348 gtk_tree_view_remove_column (GtkTreeView       *tree_view,
3349                              GtkTreeViewColumn *column)
3350 {
3351   g_return_val_if_fail (tree_view != NULL, -1);
3352   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
3353   g_return_val_if_fail (column != NULL, -1);
3354   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
3355   g_return_val_if_fail (column->tree_view == GTK_WIDGET (tree_view), -1);
3356
3357   tree_view->priv->columns = g_list_remove (tree_view->priv->columns,
3358                                            column);
3359   column->tree_view = NULL;
3360   g_object_unref (G_OBJECT (column));
3361
3362   tree_view->priv->n_columns--;
3363
3364   /* FIXME destroy header for the column! */
3365   
3366   return tree_view->priv->n_columns;
3367 }
3368
3369 /**
3370  * gtk_tree_view_insert_column:
3371  * @tree_view: A #GtkTreeView.
3372  * @column: The #GtkTreeViewColumn to be inserted.
3373  * @position: The position to insert @column in.
3374  * 
3375  * This inserts the @column into the @tree_view at @position.
3376  * 
3377  * Return value: The number of columns in @tree_view after insertion.
3378  **/
3379 gint
3380 gtk_tree_view_insert_column (GtkTreeView       *tree_view,
3381                              GtkTreeViewColumn *column,
3382                              gint               position)
3383 {
3384   g_return_val_if_fail (tree_view != NULL, -1);
3385   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), -1);
3386   g_return_val_if_fail (column != NULL, -1);
3387   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), -1);
3388   g_return_val_if_fail (column->tree_view == NULL, -1);
3389
3390   g_object_ref (G_OBJECT (column));
3391   tree_view->priv->columns = g_list_insert (tree_view->priv->columns,
3392                                            column, position);
3393   column->tree_view = GTK_WIDGET (tree_view);
3394
3395   tree_view->priv->n_columns++;
3396
3397   /* FIXME create header for the column! */
3398   
3399   return tree_view->priv->n_columns;
3400 }
3401
3402 /**
3403  * gtk_tree_view_get_column:
3404  * @tree_view: A #GtkTreeView.
3405  * @n: The position of the column, counting from 0.
3406  * 
3407  * Gets the #GtkTreeViewColumn at the given position in the #tree_view.
3408  * 
3409  * Return value: The #GtkTreeViewColumn, or NULL if the position is outside the
3410  * range of columns.
3411  **/
3412 GtkTreeViewColumn *
3413 gtk_tree_view_get_column (GtkTreeView *tree_view,
3414                           gint         n)
3415 {
3416   g_return_val_if_fail (tree_view != NULL, NULL);
3417   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), NULL);
3418   g_return_val_if_fail (tree_view->priv->model != NULL, NULL);
3419
3420   if (n < 0 || n >= tree_view->priv->n_columns)
3421     return NULL;
3422   
3423   if (tree_view->priv->columns == NULL)
3424     return NULL;
3425
3426   return GTK_TREE_VIEW_COLUMN (g_list_nth (tree_view->priv->columns, n)->data);
3427 }
3428
3429 /**
3430  * gtk_tree_view_move_to:
3431  * @tree_view: A #GtkTreeView.
3432  * @path: The path of the row to move to.
3433  * @column: The #GtkTreeViewColumn to move horizontally to.
3434  * @row_align: The vertical alignment of the row specified by @path.
3435  * @col_align: The horizontal alignment of the column specified by @column.
3436  * 
3437  * Moves the alignments of @tree_view to the position specified by
3438  * @column and @path.  If @column is NULL, then the first visible
3439  * column is assumed, and the @tree_view is left justified.  Likewise,
3440  * if @path is NULL the first row is assumed, and the @tree_view is
3441  * top justified.  @row_align determines where the row is placed, and
3442  * @col_align determines where @column is placed.  Both are expected
3443  * to be between 0.0 and 1.0. 0.0 means left/top alignment, 1.0 means
3444  * right/bottom alignment, 0.5 means center.
3445  **/
3446 void
3447 gtk_tree_view_move_to (GtkTreeView       *tree_view,
3448                        GtkTreePath       *path,
3449                        GtkTreeViewColumn *column,
3450                        gfloat             row_align,
3451                        gfloat             col_align)
3452 {
3453   GtkRBNode *node = NULL;
3454   GtkRBTree *tree = NULL;
3455
3456   g_return_if_fail (tree_view != NULL);
3457   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3458
3459   row_align = CLAMP (row_align, 0, 1);
3460   col_align = CLAMP (col_align, 0, 1);
3461
3462   if (path != NULL)
3463     {
3464       _gtk_tree_view_find_node (tree_view, path,
3465                                 &tree, &node);
3466       /* Should we justify it to the bottom? */
3467       if (node == NULL)
3468         return;
3469     }
3470
3471   if (tree_view->priv->hadjustment && column >= 0)
3472     {
3473       /* FIXME -- write  */
3474     }
3475 }
3476
3477 /**
3478  * gtk_tree_view_get_path_at_pos:
3479  * @tree_view: A #GtkTreeView.
3480  * @window: The #GtkWindow to check against.
3481  * @x: The x position to be identified.
3482  * @y: The y position to be identified.
3483  * @path: A pointer to a #GtkTreePath pointer to be filled in, or NULL
3484  * @column: A pointer to a #GtkTreeViewColumn pointer to be filled in, or NULL
3485  * 
3486  * Finds the path at the point (@x, @y) relative to @window.  If @window is
3487  * NULL, then the point is found relative to the widget coordinates.  This
3488  * function is expected to be called after an event, with event->window being
3489  * passed in as @window.  It is primarily for things like popup menus.  If @path
3490  * is non-NULL, then it will be filled with the #GtkTreePath at that point.
3491  * This path should be freed with #gtk_tree_path_free.  If @column is non-NULL,
3492  * then it will be filled with the column at that point.
3493  * 
3494  * Return value: TRUE if a row exists at that coordinate.
3495  **/
3496 gboolean
3497 gtk_tree_view_get_path_at_pos (GtkTreeView        *tree_view,
3498                                GdkWindow          *window,
3499                                gint                x,
3500                                gint                y,
3501                                GtkTreePath       **path,
3502                                GtkTreeViewColumn **column)
3503
3504 {
3505   GtkRBTree *tree;
3506   GtkRBNode *node;
3507
3508   g_return_val_if_fail (tree_view != NULL, FALSE);
3509   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
3510   g_return_val_if_fail (x >= 0, FALSE);
3511   g_return_val_if_fail (y >= 0, FALSE);
3512   g_return_val_if_fail (tree_view->priv->bin_window != NULL, FALSE);
3513
3514   if (window)
3515     g_return_val_if_fail (window == tree_view->priv->bin_window, FALSE);
3516
3517   if (path)
3518     *path = NULL;
3519   if (column)
3520     *column = NULL;
3521
3522   if (x > tree_view->priv->hadjustment->upper)
3523     return FALSE;
3524
3525   if (column)
3526     {
3527       GtkTreeViewColumn *tmp_column;
3528       GtkTreeViewColumn *last_column = NULL;
3529       GList *list;
3530
3531       for (list = tree_view->priv->columns; list; list = list->next)
3532         {
3533           tmp_column = list->data;
3534
3535           if (tmp_column->visible == FALSE)
3536             continue;
3537
3538           last_column = tmp_column;
3539           if (x <= tmp_column->width)
3540             {
3541               *column = tmp_column;
3542               break;
3543             }
3544           x -= tmp_column->width;
3545         }
3546
3547       if (*column == NULL)
3548         *column = last_column;
3549     }
3550
3551   if (window)
3552     {
3553       _gtk_rbtree_find_offset (tree_view->priv->tree,
3554                                y - TREE_VIEW_HEADER_HEIGHT (tree_view),
3555                                &tree, &node);
3556     }
3557   else
3558     {
3559       if (y < TREE_VIEW_HEADER_HEIGHT (tree_view))
3560         return FALSE;
3561
3562       _gtk_rbtree_find_offset (tree_view->priv->tree, y - TREE_VIEW_HEADER_HEIGHT (tree_view) +
3563                                tree_view->priv->vadjustment->value,
3564                                &tree, &node);
3565     }
3566
3567   if (tree == NULL)
3568     return FALSE;
3569
3570   if (path)
3571     *path = _gtk_tree_view_find_path (tree_view, tree, node);
3572
3573   return TRUE;
3574 }
3575
3576 static void
3577 gtk_tree_view_expand_all_helper (GtkRBTree  *tree,
3578                                  GtkRBNode  *node,
3579                                  gpointer  data)
3580 {
3581   GtkTreeView *tree_view = data;
3582
3583   if (node->children)
3584     _gtk_rbtree_traverse (node->children,
3585                           node->children->root,
3586                           G_PRE_ORDER,
3587                           gtk_tree_view_expand_all_helper,
3588                           data);
3589   else if ((node->flags & GTK_RBNODE_IS_PARENT) == GTK_RBNODE_IS_PARENT && node->children == NULL)
3590     {
3591       GtkTreePath *path;
3592       GtkTreeIter iter;
3593       GtkTreeIter child;
3594
3595       node->children = _gtk_rbtree_new ();
3596       node->children->parent_tree = tree;
3597       node->children->parent_node = node;
3598       path = _gtk_tree_view_find_path (tree_view, tree, node);
3599       gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
3600       gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
3601       gtk_tree_view_build_tree (tree_view,
3602                                 node->children,
3603                                 &child,
3604                                 gtk_tree_path_get_depth (path) + 1,
3605                                 TRUE,
3606                                 GTK_WIDGET_REALIZED (tree_view));
3607       gtk_tree_path_free (path);
3608     }
3609 }
3610
3611 /**
3612  * gtk_tree_view_expand_all:
3613  * @tree_view: A #GtkTreeView.
3614  * 
3615  * Recursively expands all nodes in the @tree_view.
3616  **/
3617 void
3618 gtk_tree_view_expand_all (GtkTreeView *tree_view)
3619 {
3620   g_return_if_fail (tree_view != NULL);
3621   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3622   g_return_if_fail (tree_view->priv->tree != NULL);
3623
3624   _gtk_rbtree_traverse (tree_view->priv->tree,
3625                         tree_view->priv->tree->root,
3626                         G_PRE_ORDER,
3627                         gtk_tree_view_expand_all_helper,
3628                         tree_view);
3629
3630   _gtk_tree_view_set_size (tree_view, -1,-1);
3631 }
3632
3633 static void
3634 gtk_tree_view_collapse_all_helper (GtkRBTree  *tree,
3635                                    GtkRBNode  *node,
3636                                    gpointer    data)
3637 {
3638   if (node->children)
3639     {
3640       GtkTreePath *path;
3641       GtkTreeIter iter;
3642
3643       path = _gtk_tree_view_find_path (GTK_TREE_VIEW (data),
3644                                        node->children,
3645                                        node->children->root);
3646       gtk_tree_model_get_iter (GTK_TREE_VIEW (data)->priv->model,
3647                                &iter,
3648                                path);
3649       gtk_tree_view_discover_dirty (GTK_TREE_VIEW (data),
3650                                     node->children,
3651                                     &iter,
3652                                     gtk_tree_path_get_depth (path));
3653       _gtk_rbtree_remove (node->children);
3654       gtk_tree_path_free (path);
3655     }
3656 }
3657
3658 /**
3659  * gtk_tree_view_collapse_all:
3660  * @tree_view: A #GtkTreeView.
3661  * 
3662  * Recursively collapses all visible, expanded nodes in @tree_view.
3663  **/
3664 void
3665 gtk_tree_view_collapse_all (GtkTreeView *tree_view)
3666 {
3667   g_return_if_fail (tree_view != NULL);
3668   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
3669   g_return_if_fail (tree_view->priv->tree != NULL);
3670
3671   _gtk_rbtree_traverse (tree_view->priv->tree,
3672                         tree_view->priv->tree->root,
3673                         G_PRE_ORDER,
3674                         gtk_tree_view_collapse_all_helper,
3675                         tree_view);
3676
3677   if (GTK_WIDGET_MAPPED (tree_view))
3678     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3679 }
3680
3681 /* FIXME the bool return values for expand_row and collapse_row are
3682  * not analagous; they should be TRUE if the row had children and
3683  * was not already in the requested state.
3684  */
3685
3686 /**
3687  * gtk_tree_view_expand_row:
3688  * @tree_view: a #GtkTreeView
3689  * @path: path to a row
3690  * @open_all: whether to recursively expand, or just expand immediate children
3691  * 
3692  * Opens the row so its children are visible
3693  * 
3694  * Return value: %TRUE if the row existed and had children
3695  **/
3696 gboolean
3697 gtk_tree_view_expand_row (GtkTreeView *tree_view,
3698                           GtkTreePath *path,
3699                           gboolean     open_all)
3700 {
3701   GtkTreeIter iter;
3702   GtkTreeIter child;
3703   GtkRBTree *tree;
3704   GtkRBNode *node;
3705
3706   g_return_val_if_fail (tree_view != NULL, FALSE);
3707   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
3708   g_return_val_if_fail (tree_view->priv->model != NULL, FALSE);
3709   g_return_val_if_fail (path != NULL, FALSE);
3710
3711   if (_gtk_tree_view_find_node (tree_view,
3712                                 path,
3713                                 &tree,
3714                                 &node))
3715     return FALSE;
3716
3717   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
3718   if (! gtk_tree_model_iter_has_child (tree_view->priv->model, &iter))
3719     return FALSE;
3720
3721   node->children = _gtk_rbtree_new ();
3722   node->children->parent_tree = tree;
3723   node->children->parent_node = node;
3724
3725   gtk_tree_model_iter_children (tree_view->priv->model, &child, &iter);
3726   gtk_tree_view_build_tree (tree_view,
3727                             node->children,
3728                             &child,
3729                             gtk_tree_path_get_depth (path) + 1,
3730                             open_all,
3731                             GTK_WIDGET_REALIZED (tree_view));
3732
3733   if (GTK_WIDGET_MAPPED (tree_view))
3734     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3735
3736   return TRUE;
3737 }
3738
3739 /**
3740  * gtk_tree_view_collapse_row:
3741  * @tree_view: a #GtkTreeView
3742  * @path: path to a row in the @tree_view
3743  * 
3744  * Collapses a row (hides its child rows).
3745  * 
3746  * Return value: %TRUE if the row was expanded
3747  **/
3748 gboolean
3749 gtk_tree_view_collapse_row (GtkTreeView *tree_view,
3750                             GtkTreePath *path)
3751 {
3752   GtkRBTree *tree;
3753   GtkRBNode *node;
3754   GtkTreeIter iter;
3755
3756   g_return_val_if_fail (tree_view != NULL, FALSE);
3757   g_return_val_if_fail (GTK_IS_TREE_VIEW (tree_view), FALSE);
3758   g_return_val_if_fail (tree_view->priv->tree != NULL, FALSE);
3759   g_return_val_if_fail (path != NULL, FALSE);
3760
3761   if (_gtk_tree_view_find_node (tree_view,
3762                                 path,
3763                                 &tree,
3764                                 &node))
3765     return FALSE;
3766
3767   if (node->children == NULL)
3768     return FALSE;
3769
3770   gtk_tree_model_get_iter (tree_view->priv->model, &iter, path);
3771   gtk_tree_view_discover_dirty (tree_view,
3772                                 node->children,
3773                                 &iter,
3774                                 gtk_tree_path_get_depth (path));
3775   _gtk_rbtree_remove (node->children);
3776
3777   if (GTK_WIDGET_MAPPED (tree_view))
3778     gtk_widget_queue_draw (GTK_WIDGET (tree_view));
3779
3780   return TRUE;
3781 }
3782