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