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