]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeviewcolumn.c
Add editable interface. This should be the last big GtkTreeView API
[~andy/gtk] / gtk / gtktreeviewcolumn.c
1 /* gtktreeviewcolumn.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 #include "gtktreeviewcolumn.h"
21 #include "gtktreeview.h"
22 #include "gtktreeprivate.h"
23 #include "gtksignal.h"
24 #include "gtkbutton.h"
25 #include "gtkalignment.h"
26 #include "gtklabel.h"
27 #include "gtkhbox.h"
28 #include "gtkarrow.h"
29 #include "gtkintl.h"
30 #include <string.h>
31
32 enum
33 {
34   PROP_0,
35   PROP_VISIBLE,
36   PROP_WIDTH,
37   PROP_SIZING,
38   PROP_FIXED_WIDTH,
39   PROP_MIN_WIDTH,
40   PROP_MAX_WIDTH,
41   PROP_TITLE,
42   PROP_CLICKABLE,
43   PROP_WIDGET,
44   PROP_ALIGNMENT,
45   PROP_REORDERABLE,
46   PROP_SORT_INDICATOR,
47   PROP_SORT_ORDER
48 };
49
50 enum
51 {
52   CLICKED,
53   LAST_SIGNAL
54 };
55
56 typedef struct _GtkTreeViewColumnCellInfo GtkTreeViewColumnCellInfo;
57 struct _GtkTreeViewColumnCellInfo
58 {
59   GtkCellRenderer *cell;
60   GSList *attributes;
61   GtkTreeCellDataFunc func;
62   gpointer func_data;
63   GtkDestroyNotify destroy;
64   gint requested_width;
65   guint expand : 1;
66   guint pack : 1;
67   guint has_focus : 1;
68 };
69
70 /* Type methods */
71 static void gtk_tree_view_column_init                          (GtkTreeViewColumn       *tree_column);
72 static void gtk_tree_view_column_class_init                    (GtkTreeViewColumnClass  *klass);
73
74 /* GObject methods */
75 static void gtk_tree_view_column_set_property                  (GObject                 *object,
76                                                                 guint                    prop_id,
77                                                                 const GValue            *value,
78                                                                 GParamSpec              *pspec);
79 static void gtk_tree_view_column_get_property                  (GObject                 *object,
80                                                                 guint                    prop_id,
81                                                                 GValue                  *value,
82                                                                 GParamSpec              *pspec);
83 static void gtk_tree_view_column_finalize                      (GObject                 *object);
84
85 /* Button handling code */ 
86 static void gtk_tree_view_column_create_button                 (GtkTreeViewColumn       *tree_column);
87 static void gtk_tree_view_column_update_button                 (GtkTreeViewColumn       *tree_column);
88
89 /* Button signal handlers */
90 static gint gtk_tree_view_column_button_event                  (GtkWidget               *widget,
91                                                                 GdkEvent                *event,
92                                                                 gpointer                 data);
93 static void gtk_tree_view_column_button_realize                (GtkWidget               *widget,
94                                                                 gpointer                 data);
95 static void gtk_tree_view_column_button_clicked                (GtkWidget               *widget,
96                                                                 gpointer                 data);
97
98 /* Property handlers */
99 static void gtk_tree_view_model_sort_column_changed            (GtkTreeSortable         *sortable,
100                                                                 GtkTreeViewColumn       *tree_column);
101
102 /* Internal functions */
103 static void gtk_tree_view_column_sort                          (GtkTreeViewColumn       *tree_column,
104                                                                 gpointer                 data);
105 static void gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn       *tree_column);
106 static void gtk_tree_view_column_set_attributesv               (GtkTreeViewColumn       *tree_column,
107                                                                 GtkCellRenderer         *cell_renderer,
108                                                                 va_list                  args);
109 static GtkTreeViewColumnCellInfo *gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
110                                                                       GtkCellRenderer   *cell_renderer);
111
112
113
114 static GtkObjectClass *parent_class = NULL;
115 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
116
117
118 GtkType
119 gtk_tree_view_column_get_type (void)
120 {
121   static GtkType tree_column_type = 0;
122
123   if (!tree_column_type)
124     {
125       static const GTypeInfo tree_column_info =
126       {
127         sizeof (GtkTreeViewColumnClass),
128         NULL,           /* base_init */
129         NULL,           /* base_finalize */
130         (GClassInitFunc) gtk_tree_view_column_class_init,
131         NULL,           /* class_finalize */
132         NULL,           /* class_data */
133         sizeof (GtkTreeViewColumn),
134         0,
135         (GInstanceInitFunc) gtk_tree_view_column_init,
136       };
137
138       tree_column_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeViewColumn", &tree_column_info, 0);
139     }
140
141   return tree_column_type;
142 }
143
144 static void
145 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
146 {
147   GObjectClass *object_class;
148
149   object_class = (GObjectClass*) class;
150
151   parent_class = g_type_class_peek_parent (class);
152
153   class->clicked = NULL;
154
155   object_class->finalize = gtk_tree_view_column_finalize;
156   object_class->set_property = gtk_tree_view_column_set_property;
157   object_class->get_property = gtk_tree_view_column_get_property;
158   
159   tree_column_signals[CLICKED] =
160     g_signal_new ("clicked",
161                   GTK_CLASS_TYPE (object_class),
162                   G_SIGNAL_RUN_LAST,
163                   G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
164                   NULL, NULL,
165                   gtk_marshal_VOID__VOID,
166                   GTK_TYPE_NONE, 0);
167
168   g_object_class_install_property (object_class,
169                                    PROP_VISIBLE,
170                                    g_param_spec_boolean ("visible",
171                                                         _("Visible"),
172                                                         _("Whether to display the column"),
173                                                          TRUE,
174                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
175   
176   g_object_class_install_property (object_class,
177                                    PROP_WIDTH,
178                                    g_param_spec_int ("width",
179                                                      _("Width"),
180                                                      _("Current width of the column"),
181                                                      0,
182                                                      G_MAXINT,
183                                                      0,
184                                                      G_PARAM_READABLE));
185   g_object_class_install_property (object_class,
186                                    PROP_SIZING,
187                                    g_param_spec_enum ("sizing",
188                                                       _("Sizing"),
189                                                       _("Resize mode of the column"),
190                                                       GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
191                                                       GTK_TREE_VIEW_COLUMN_AUTOSIZE,
192                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
193   
194   g_object_class_install_property (object_class,
195                                    PROP_FIXED_WIDTH,
196                                    g_param_spec_int ("fixed_width",
197                                                      _("Fixed Width"),
198                                                      _("Current fixed width of the column"),
199                                                      1,
200                                                      G_MAXINT,
201                                                      1, /* not useful */
202                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
203
204   g_object_class_install_property (object_class,
205                                    PROP_MIN_WIDTH,
206                                    g_param_spec_int ("min_width",
207                                                      _("Minimum Width"),
208                                                      _("Minimum allowed width of the column"),
209                                                      -1,
210                                                      G_MAXINT,
211                                                      -1,
212                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
213
214   g_object_class_install_property (object_class,
215                                    PROP_MAX_WIDTH,
216                                    g_param_spec_int ("max_width",
217                                                      _("Maximum Width"),
218                                                      _("Maximum allowed width of the column"),
219                                                      -1,
220                                                      G_MAXINT,
221                                                      -1,
222                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
223
224   g_object_class_install_property (object_class,
225                                    PROP_TITLE,
226                                    g_param_spec_string ("title",
227                                                         _("Title"),
228                                                         _("Title to appear in column header"),
229                                                         "",
230                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
231   
232   g_object_class_install_property (object_class,
233                                    PROP_CLICKABLE,
234                                    g_param_spec_boolean ("clickable",
235                                                         _("Clickable"),
236                                                         _("Whether the header can be clicked"),
237                                                          TRUE,
238                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
239   
240
241   g_object_class_install_property (object_class,
242                                    PROP_WIDGET,
243                                    g_param_spec_object ("widget",
244                                                         _("Widget"),
245                                                         _("Widget to put in column header button instead of column title"),
246                                                         GTK_TYPE_WIDGET,
247                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
248
249   g_object_class_install_property (object_class,
250                                    PROP_ALIGNMENT,
251                                    g_param_spec_float ("alignment",
252                                                        _("Alignment"),
253                                                        _("X Alignment of the column header text or widget"),
254                                                        0.0,
255                                                        1.0,
256                                                        0.5,
257                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
258
259   g_object_class_install_property (object_class,
260                                    PROP_REORDERABLE,
261                                    g_param_spec_boolean ("reorderable",
262                                                          _("Reorderable"),
263                                                          _("Wether the column can be reordered around the headers"),
264                                                          FALSE,
265                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
266
267   g_object_class_install_property (object_class,
268                                    PROP_SORT_INDICATOR,
269                                    g_param_spec_boolean ("sort_indicator",
270                                                         _("Sort indicator"),
271                                                         _("Whether to show a sort indicator"),
272                                                          FALSE,
273                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
274
275   g_object_class_install_property (object_class,
276                                    PROP_SORT_ORDER,
277                                    g_param_spec_enum ("sort_order",
278                                                       _("Sort order"),
279                                                       _("Sort direction the sort indicator should indicate"),
280                                                       GTK_TYPE_SORT_TYPE,
281                                                       GTK_SORT_ASCENDING,
282                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
283   
284 }
285
286 static void
287 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
288 {
289   tree_column->button = NULL;
290   tree_column->xalign = 0.0;
291   tree_column->width = 0;
292   tree_column->requested_width = -1;
293   tree_column->min_width = -1;
294   tree_column->max_width = -1;
295   tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
296   tree_column->visible = TRUE;
297   tree_column->clickable = FALSE;
298   tree_column->dirty = TRUE;
299   tree_column->sort_order = GTK_SORT_ASCENDING;
300   tree_column->show_sort_indicator = FALSE;
301   tree_column->property_changed_signal = 0;
302   tree_column->sort_clicked_signal = 0;
303   tree_column->sort_column_changed_signal = 0;
304   tree_column->sort_column_id = -1;
305   tree_column->reorderable = FALSE;
306   tree_column->maybe_reordered = FALSE;
307 }
308
309 static void
310 gtk_tree_view_column_finalize (GObject *object)
311 {
312   GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
313   GList *list;
314
315   for (list = tree_column->cell_list; list; list = list->next)
316     {
317       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
318       if (info->func_data && info->destroy)
319         (info->destroy) (info->func_data);
320       gtk_tree_view_column_clear_attributes (tree_column, info->cell);
321       g_object_unref (G_OBJECT (info->cell));
322       g_free (info);
323     }
324
325   g_free (tree_column->title);
326
327   G_OBJECT_CLASS (parent_class)->finalize (object);
328 }
329
330 static void
331 gtk_tree_view_column_set_property (GObject         *object,
332                                    guint            prop_id,
333                                    const GValue    *value,
334                                    GParamSpec      *pspec)
335 {
336   GtkTreeViewColumn *tree_column;
337
338   tree_column = GTK_TREE_VIEW_COLUMN (object);
339
340   switch (prop_id)
341     {
342     case PROP_VISIBLE:
343       gtk_tree_view_column_set_visible (tree_column,
344                                         g_value_get_boolean (value));
345       break;
346
347     case PROP_SIZING:
348       gtk_tree_view_column_set_sizing (tree_column,
349                                        g_value_get_enum (value));
350       break;
351
352     case PROP_FIXED_WIDTH:
353       gtk_tree_view_column_set_fixed_width (tree_column,
354                                             g_value_get_int (value));
355       break;
356
357     case PROP_MIN_WIDTH:
358       gtk_tree_view_column_set_min_width (tree_column,
359                                           g_value_get_int (value));
360       break;
361
362     case PROP_MAX_WIDTH:
363       gtk_tree_view_column_set_max_width (tree_column,
364                                           g_value_get_int (value));
365       break;
366
367     case PROP_TITLE:
368       gtk_tree_view_column_set_title (tree_column,
369                                       g_value_get_string (value));
370       break;
371
372     case PROP_CLICKABLE:
373       gtk_tree_view_column_set_clickable (tree_column,
374                                           g_value_get_boolean (value));
375       break;
376
377     case PROP_WIDGET:
378       gtk_tree_view_column_set_widget (tree_column,
379                                        (GtkWidget*) g_value_get_object (value));
380       break;
381
382     case PROP_ALIGNMENT:
383       gtk_tree_view_column_set_alignment (tree_column,
384                                           g_value_get_float (value));
385       break;
386
387     case PROP_REORDERABLE:
388       gtk_tree_view_column_set_reorderable (tree_column,
389                                             g_value_get_boolean (value));
390       break;
391
392     case PROP_SORT_INDICATOR:
393       gtk_tree_view_column_set_sort_indicator (tree_column,
394                                                g_value_get_boolean (value));
395       break;
396
397     case PROP_SORT_ORDER:
398       gtk_tree_view_column_set_sort_order (tree_column,
399                                            g_value_get_enum (value));
400       break;
401       
402     default:
403       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
404       break;
405     }
406 }
407
408 static void
409 gtk_tree_view_column_get_property (GObject         *object,
410                                    guint            prop_id,
411                                    GValue          *value,
412                                    GParamSpec      *pspec)
413 {
414   GtkTreeViewColumn *tree_column;
415
416   tree_column = GTK_TREE_VIEW_COLUMN (object);
417
418   switch (prop_id)
419     {
420     case PROP_VISIBLE:
421       g_value_set_boolean (value,
422                            gtk_tree_view_column_get_visible (tree_column));
423       break;
424
425     case PROP_WIDTH:
426       g_value_set_int (value,
427                        gtk_tree_view_column_get_width (tree_column));
428       break;
429
430     case PROP_SIZING:
431       g_value_set_enum (value,
432                         gtk_tree_view_column_get_sizing (tree_column));
433       break;
434
435     case PROP_FIXED_WIDTH:
436       g_value_set_int (value,
437                        gtk_tree_view_column_get_fixed_width (tree_column));
438       break;
439
440     case PROP_MIN_WIDTH:
441       g_value_set_int (value,
442                        gtk_tree_view_column_get_min_width (tree_column));
443       break;
444
445     case PROP_MAX_WIDTH:
446       g_value_set_int (value,
447                        gtk_tree_view_column_get_max_width (tree_column));
448       break;
449
450     case PROP_TITLE:
451       g_value_set_string (value,
452                           gtk_tree_view_column_get_title (tree_column));
453       break;
454
455     case PROP_CLICKABLE:
456       g_value_set_boolean (value,
457                            gtk_tree_view_column_get_clickable (tree_column));
458       break;
459
460     case PROP_WIDGET:
461       g_value_set_object (value,
462                           (GObject*) gtk_tree_view_column_get_widget (tree_column));
463       break;
464
465     case PROP_ALIGNMENT:
466       g_value_set_float (value,
467                          gtk_tree_view_column_get_alignment (tree_column));
468       break;
469
470     case PROP_REORDERABLE:
471       g_value_set_boolean (value,
472                            gtk_tree_view_column_get_reorderable (tree_column));
473       break;
474
475     case PROP_SORT_INDICATOR:
476       g_value_set_boolean (value,
477                            gtk_tree_view_column_get_sort_indicator (tree_column));
478       break;
479
480     case PROP_SORT_ORDER:
481       g_value_set_enum (value,
482                         gtk_tree_view_column_get_sort_order (tree_column));
483       break;
484       
485     default:
486       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
487       break;
488     }
489 }
490
491 /* Helper functions
492  */
493
494 /* Button handling code
495  */
496 static void
497 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
498 {
499   GtkTreeView *tree_view;
500   GtkWidget *child;
501   GtkWidget *hbox;
502
503   tree_view = (GtkTreeView *) tree_column->tree_view;
504
505   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
506   g_return_if_fail (tree_column->button == NULL);
507
508   gtk_widget_push_composite_child ();
509   tree_column->button = gtk_button_new ();
510   gtk_widget_pop_composite_child ();
511
512   /* make sure we own a reference to it as well. */
513   if (tree_view->priv->header_window)
514     gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
515   gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
516   
517   gtk_signal_connect (GTK_OBJECT (tree_column->button), "realize",
518                       (GtkSignalFunc) gtk_tree_view_column_button_realize,
519                       NULL);
520
521   gtk_signal_connect (GTK_OBJECT (tree_column->button), "event",
522                       (GtkSignalFunc) gtk_tree_view_column_button_event,
523                       (gpointer) tree_column);
524   
525   gtk_signal_connect (GTK_OBJECT (tree_column->button), "clicked",
526                       (GtkSignalFunc) gtk_tree_view_column_button_clicked,
527                       (gpointer) tree_column);
528
529   tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
530
531   hbox = gtk_hbox_new (FALSE, 2);
532   tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
533
534   if (tree_column->child)
535     child = tree_column->child;
536   else
537     {
538       child = gtk_label_new (tree_column->title);
539       gtk_widget_show (child);
540     }
541
542   if (tree_column->xalign <= 0.5)
543     gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
544   else
545     gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
546
547   gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
548         
549   gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
550   gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
551
552   gtk_widget_show (hbox);
553   gtk_widget_show (tree_column->alignment);
554   gtk_tree_view_column_update_button (tree_column);
555 }
556
557 static void 
558 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
559 {
560   GtkWidget *hbox;
561   GtkWidget *alignment;
562   GtkWidget *arrow;
563   GtkWidget *current_child;
564
565   /* Create a button if necessary */
566   if (tree_column->visible &&
567       tree_column->button == NULL &&
568       tree_column->tree_view &&
569       GTK_WIDGET_REALIZED (tree_column->tree_view))
570     gtk_tree_view_column_create_button (tree_column);
571   
572   if (! tree_column->button)
573     return;
574
575   hbox = GTK_BIN (tree_column->button)->child;
576   alignment = tree_column->alignment;
577   arrow = tree_column->arrow;
578   current_child = GTK_BIN (alignment)->child;
579
580   /* Set up the actual button */
581   gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
582                      0.5, 0.0, 0.0);
583       
584   if (tree_column->child)
585     {
586       if (current_child != tree_column->child)
587         {
588           gtk_container_remove (GTK_CONTAINER (alignment),
589                                 current_child);
590           gtk_container_add (GTK_CONTAINER (alignment),
591                              tree_column->child);
592         }
593     }
594   else 
595     {
596       if (current_child == NULL)
597         {
598           current_child = gtk_label_new (NULL);
599           gtk_widget_show (current_child);
600           gtk_container_add (GTK_CONTAINER (alignment),
601                              current_child);
602         }
603
604       g_return_if_fail (GTK_IS_LABEL (current_child));
605
606       if (tree_column->title)
607         gtk_label_set_text (GTK_LABEL (current_child),
608                             tree_column->title);
609       else
610         gtk_label_set_text (GTK_LABEL (current_child),
611                             "");
612     }
613
614   switch (tree_column->sort_order)
615     {
616     case GTK_SORT_ASCENDING:
617       gtk_arrow_set (GTK_ARROW (arrow),
618                      GTK_ARROW_DOWN,
619                      GTK_SHADOW_IN);
620       break;
621
622     case GTK_SORT_DESCENDING:
623       gtk_arrow_set (GTK_ARROW (arrow),
624                      GTK_ARROW_UP,
625                      GTK_SHADOW_IN);
626       break;
627           
628     default:
629       g_warning (G_STRLOC": bad sort order");
630       break;
631     }
632
633   /* Put arrow on the right if the text is left-or-center justified,
634        * and on the left otherwise; do this by packing boxes, so flipping
635        * text direction will reverse things
636        */
637   gtk_widget_ref (arrow);
638   gtk_container_remove (GTK_CONTAINER (hbox), arrow);
639
640   if (tree_column->xalign <= 0.5)
641     {
642       gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
643     }
644   else
645     {
646       gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
647       /* move it to the front */
648       gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
649     }
650   gtk_widget_unref (arrow);
651
652   if (tree_column->show_sort_indicator)
653     gtk_widget_show (arrow);
654   else
655     gtk_widget_hide (arrow);
656
657   /* It's always safe to hide the button.  It isn't always safe to show it, as if you show it
658    * before it's realized, it'll get the wrong window. */
659   if (tree_column->button &&
660       tree_column->tree_view != NULL &&
661       GTK_WIDGET_REALIZED (tree_column->tree_view))
662     {
663       if (tree_column->visible)
664         {
665           gtk_widget_show_now (tree_column->button);
666           if (tree_column->window)
667             {
668               if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_RESIZABLE)
669                 {
670                   gdk_window_show (tree_column->window);
671                   gdk_window_raise (tree_column->window);
672                 }
673               else
674                 {
675                   gdk_window_hide (tree_column->window);
676                 }
677             }
678         }
679       else
680         {
681           gtk_widget_hide (tree_column->button);
682           if (tree_column->window)
683             gdk_window_hide (tree_column->window);
684         }
685     }
686   
687   if (tree_column->reorderable || tree_column->clickable)
688     {
689       GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
690     }
691   else
692     {
693       GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
694       if (GTK_WIDGET_HAS_FOCUS (tree_column->button))
695         {
696           GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
697           if (GTK_WIDGET_TOPLEVEL (toplevel))
698             gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
699         }
700     }
701
702   gtk_tree_view_column_cell_set_dirty (tree_column);
703 }
704
705 /* Button signal handlers
706  */
707
708 static gint
709 gtk_tree_view_column_button_event (GtkWidget *widget,
710                                    GdkEvent  *event,
711                                    gpointer   data)
712 {
713   GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
714
715   g_return_val_if_fail (event != NULL, FALSE);
716
717   if (event->type == GDK_BUTTON_PRESS &&
718       column->reorderable)
719     {
720       column->maybe_reordered = TRUE;
721       gdk_window_get_pointer (widget->window,
722                               &column->drag_x,
723                               &column->drag_y,
724                               NULL);
725       gtk_widget_grab_focus (widget);
726     }
727
728   if (event->type == GDK_BUTTON_RELEASE &&
729       column->maybe_reordered)
730     column->maybe_reordered = FALSE;
731
732   if (event->type == GDK_MOTION_NOTIFY &&
733       (column->maybe_reordered) &&
734       (gtk_drag_check_threshold (widget,
735                                  column->drag_x,
736                                  column->drag_y,
737                                  (gint) ((GdkEventMotion *)event)->x,
738                                  (gint) ((GdkEventMotion *)event)->y)))
739     {
740       column->maybe_reordered = FALSE;
741       _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
742       return TRUE;
743     }
744   if (column->clickable == FALSE)
745     {
746       switch (event->type)
747         {
748         case GDK_BUTTON_PRESS:
749         case GDK_2BUTTON_PRESS:
750         case GDK_3BUTTON_PRESS:
751         case GDK_MOTION_NOTIFY:
752         case GDK_BUTTON_RELEASE:
753         case GDK_ENTER_NOTIFY:
754         case GDK_LEAVE_NOTIFY:
755           return TRUE;
756         default:
757           return FALSE;
758         }
759     }
760   return FALSE;
761 }
762
763 static void
764 gtk_tree_view_column_button_realize (GtkWidget *widget, gpointer data)
765 {
766   gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | GDK_POINTER_MOTION_MASK);
767 }
768
769 static void
770 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
771 {
772   g_signal_emit_by_name (G_OBJECT (data), "clicked");
773 }
774
775 static void
776 gtk_tree_view_model_sort_column_changed (GtkTreeSortable   *sortable,
777                                           GtkTreeViewColumn *column)
778 {
779   gint sort_column_id;
780   GtkSortType order;
781
782   if (gtk_tree_sortable_get_sort_column_id (sortable,
783                                             &sort_column_id,
784                                             &order))
785     {
786       if (sort_column_id == column->sort_column_id)
787         {
788           gtk_tree_view_column_set_sort_indicator (column, TRUE);
789           gtk_tree_view_column_set_sort_order (column, order);
790         }
791       else
792         {
793           gtk_tree_view_column_set_sort_indicator (column, FALSE);
794         }
795     }
796 }
797
798 static void
799 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
800                            gpointer           data)
801 {
802   GList *list;
803
804   g_return_if_fail (tree_column->tree_view != NULL);
805
806   if (tree_column->show_sort_indicator)
807     {
808       if (tree_column->sort_order == GTK_SORT_ASCENDING)
809         gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_DESCENDING);
810       else
811         gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
812     }
813   else
814     {
815       gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
816       gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
817     }
818
819   list = (GTK_TREE_VIEW (tree_column->tree_view)->priv->columns);
820   g_assert (list);
821   while (list)
822     {
823       GtkTreeViewColumn *tmp_column;
824
825       tmp_column = GTK_TREE_VIEW_COLUMN (list->data);
826       if (tmp_column->visible && tmp_column != tree_column)
827         gtk_tree_view_column_set_sort_indicator (tmp_column, FALSE);
828
829       list = list->next;
830     }
831
832   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
833                                         tree_column->sort_column_id,
834                                         tree_column->sort_order);
835 }
836
837
838 static void
839 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
840 {
841   GtkTreeModel *model;
842
843   if (tree_column->tree_view == NULL)
844     return;
845
846   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
847
848   if (model == NULL)
849     return;
850
851   if (GTK_IS_TREE_SORTABLE (model) &&
852       tree_column->sort_column_id != -1)
853     {
854       gint real_sort_column_id;
855       GtkSortType real_order;
856
857       if (tree_column->sort_column_changed_signal == 0)
858         tree_column->sort_column_changed_signal =
859           g_signal_connect (G_OBJECT (model), "sort_column_changed",
860                             GTK_SIGNAL_FUNC (gtk_tree_view_model_sort_column_changed),
861                             tree_column);
862       
863       if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
864                                                 &real_sort_column_id,
865                                                 &real_order) &&
866           (real_sort_column_id == tree_column->sort_column_id))
867         {
868           gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
869           gtk_tree_view_column_set_sort_order (tree_column, real_order);
870
871           return;
872         }
873     }
874 }
875
876
877 /* Exported Private Functions.
878  * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
879  */
880
881 void
882 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
883 {
884   GtkTreeView *tree_view;
885   GdkWindowAttr attr;
886   guint attributes_mask;
887
888   tree_view = (GtkTreeView *)column->tree_view;
889
890   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
891   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
892   g_return_if_fail (tree_view->priv->header_window != NULL);
893   g_return_if_fail (column->button != NULL);
894
895   gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
896
897   if (column->visible)
898     gtk_widget_show (column->button);
899
900   attr.window_type = GDK_WINDOW_CHILD;
901   attr.wclass = GDK_INPUT_ONLY;
902   attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
903   attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
904   attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view));
905   attr.event_mask = (GDK_BUTTON_PRESS_MASK |
906                      GDK_BUTTON_RELEASE_MASK |
907                      GDK_POINTER_MOTION_MASK |
908                      GDK_POINTER_MOTION_HINT_MASK |
909                      GDK_KEY_PRESS_MASK);
910   attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
911   attr.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
912   tree_view->priv->cursor_drag = attr.cursor;
913
914   attr.y = 0;
915   attr.width = TREE_VIEW_DRAG_WIDTH;
916   attr.height = tree_view->priv->header_height;
917
918   attr.x = (column->button->allocation.x + column->button->allocation.width) - 3;
919           
920   column->window = gdk_window_new (tree_view->priv->header_window,
921                                    &attr, attributes_mask);
922   gdk_window_set_user_data (column->window, tree_view);
923
924   gtk_tree_view_column_update_button (column);
925 }
926
927 void
928 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
929 {
930   g_return_if_fail (column != NULL);
931   g_return_if_fail (column->window != NULL);
932
933   gdk_window_set_user_data (column->window, NULL);
934   gdk_window_destroy (column->window);
935   column->window = NULL;
936 }
937
938 void
939 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
940                                      GtkTreeView       *tree_view)
941 {
942   g_assert (column->tree_view == NULL);
943
944   column->tree_view = GTK_WIDGET (tree_view);
945   gtk_tree_view_column_create_button (column);
946
947   column->property_changed_signal =
948           g_signal_connect_swapped (GTK_OBJECT (tree_view),
949                                     "notify::model",
950                                     GTK_SIGNAL_FUNC (gtk_tree_view_column_setup_sort_column_id_callback),
951                                     column);
952
953   gtk_tree_view_column_setup_sort_column_id_callback (column);
954 }
955
956 void
957 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
958 {
959   if (column->tree_view && column->button)
960     {
961       gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
962     }
963   if (column->property_changed_signal)
964     {
965       g_signal_handler_disconnect (G_OBJECT (column->tree_view), column->property_changed_signal);
966       column->property_changed_signal = 0;
967     }
968
969   if (column->sort_column_changed_signal)
970     {
971       g_signal_handler_disconnect (G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view))),
972                                    column->sort_column_changed_signal);
973       column->sort_column_changed_signal = 0;
974     }
975
976   column->tree_view = NULL;
977   column->button = NULL;
978 }
979
980 void
981 _gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
982                                  gint               width)
983 {
984   if (tree_column->min_width != -1 &&
985       width <= tree_column->min_width)
986     width = tree_column->min_width;
987   else if (tree_column->max_width != -1 &&
988            width > tree_column->max_width)
989     width = tree_column->max_width;
990   
991   if (tree_column->width == width)
992     return;
993   
994   tree_column->width = width;
995
996   g_object_notify (G_OBJECT (tree_column), "width");
997
998   if (tree_column->tree_view != NULL)
999     gtk_widget_queue_resize (tree_column->tree_view);
1000
1001 }
1002
1003 /* Public Functions */
1004
1005
1006 /**
1007  * gtk_tree_view_column_new:
1008  * 
1009  * Creates a new #GtkTreeViewColumn.
1010  * 
1011  * Return value: A newly created #GtkTreeViewColumn.
1012  **/
1013 GtkTreeViewColumn *
1014 gtk_tree_view_column_new (void)
1015 {
1016   GtkTreeViewColumn *tree_column;
1017
1018   tree_column = GTK_TREE_VIEW_COLUMN (gtk_type_new (GTK_TYPE_TREE_VIEW_COLUMN));
1019
1020   return tree_column;
1021 }
1022
1023 /**
1024  * gtk_tree_view_column_new_with_attributes:
1025  * @title: The title to set the header to.
1026  * @cell: The #GtkCellRenderer.
1027  * @Varargs: A NULL terminated list of attributes.
1028  * 
1029  * Creates a new #GtkTreeViewColumn with a number of default values.  This is
1030  * equivalent to calling @gtk_tree_view_column_set_title,
1031  * @gtk_tree_view_column_set_cell_renderer, and
1032  * @gtk_tree_view_column_set_attributes on the newly created #GtkTreeViewColumn.
1033  * 
1034  * Return value: A newly created #GtkTreeViewColumn.
1035  **/
1036 GtkTreeViewColumn *
1037 gtk_tree_view_column_new_with_attributes (const gchar     *title,
1038                                           GtkCellRenderer *cell,
1039                                           ...)
1040 {
1041   GtkTreeViewColumn *retval;
1042   va_list args;
1043
1044   retval = gtk_tree_view_column_new ();
1045
1046   gtk_tree_view_column_set_title (retval, title);
1047   gtk_tree_view_column_set_cell_renderer (retval, cell);
1048
1049   va_start (args, cell);
1050   gtk_tree_view_column_set_attributesv (retval, cell, args);
1051   va_end (args);
1052
1053   return retval;
1054 }
1055
1056 /**
1057  * gtk_tree_view_column_set_cell_renderer:
1058  * @tree_column: A #GtkTreeViewColumn.
1059  * @cell: The #GtkCellRenderer, or NULL.
1060  * 
1061  * Sets the cell renderer of the @tree_column.  If there is a cell
1062  * renderer already set, then it is removed.  If @cell is NULL, then
1063  * the cell renderer is unset.
1064  **/
1065 void
1066 gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
1067                                         GtkCellRenderer   *cell)
1068 {
1069   gtk_tree_view_column_pack_start (tree_column, cell, TRUE);
1070 }
1071
1072 static GtkTreeViewColumnCellInfo *
1073 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1074                                     GtkCellRenderer   *cell_renderer)
1075 {
1076   GList *list;
1077   for (list = tree_column->cell_list; list; list = list->next)
1078     if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1079       return (GtkTreeViewColumnCellInfo *) list->data;
1080   return NULL;
1081 }
1082
1083
1084 /**
1085  * gtk_tree_view_column_pack_start:
1086  * @tree_column: A #GtkTreeViewColumn.
1087  * @cell: The #GtkCellRenderer, 
1088  * @expand: TRUE if @cell is to be given extra space allocated to box.
1089  * 
1090  **/
1091 void
1092 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1093                                  GtkCellRenderer   *cell,
1094                                  gboolean           expand)
1095 {
1096   GtkTreeViewColumnCellInfo *cell_info;
1097
1098   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1099   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1100   g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1101
1102   g_object_ref (G_OBJECT (cell));
1103   gtk_object_sink (GTK_OBJECT (cell));
1104
1105   cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
1106   cell_info->cell = cell;
1107   cell_info->expand = expand ? TRUE : FALSE;
1108   cell_info->pack = GTK_PACK_START;
1109   cell_info->has_focus = 0;
1110   cell_info->attributes = NULL;
1111
1112   tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1113 }
1114
1115 void
1116 gtk_tree_view_column_pack_end (GtkTreeViewColumn  *tree_column,
1117                                GtkCellRenderer    *cell,
1118                                gboolean            expand)
1119 {
1120   GtkTreeViewColumnCellInfo *cell_info;
1121
1122   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1123   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1124   g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1125
1126   g_object_ref (G_OBJECT (cell));
1127   gtk_object_sink (GTK_OBJECT (cell));
1128
1129   cell_info = g_new (GtkTreeViewColumnCellInfo, 1);
1130   cell_info->cell = cell;
1131   cell_info->expand = expand ? TRUE : FALSE;
1132   cell_info->pack = GTK_PACK_END;
1133   cell_info->has_focus = 0;
1134   cell_info->attributes = NULL;
1135
1136   tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1137 }
1138
1139
1140 void
1141 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1142 {
1143   GList *list;
1144   g_return_if_fail (tree_column != NULL);
1145
1146   for (list = tree_column->cell_list; list; list = list->next)
1147     {
1148       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1149
1150       g_object_unref (G_OBJECT (info->cell));
1151       gtk_tree_view_column_clear_attributes (tree_column, info->cell);
1152       g_free (info);
1153     }
1154
1155   g_list_free (tree_column->cell_list);
1156   tree_column->cell_list = NULL;
1157 }
1158
1159 GList *
1160 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1161 {
1162   GList *retval = NULL, *list;
1163
1164   g_return_val_if_fail (tree_column != NULL, NULL);
1165
1166   for (list = tree_column->cell_list; list; list = list->next)
1167     {
1168       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1169
1170       retval = g_list_append (retval, info->cell);
1171     }
1172
1173   return retval;
1174 }
1175
1176 /**
1177  * gtk_tree_view_column_add_attribute:
1178  * @tree_column: A #GtkTreeViewColumn.
1179  * @cell_renderer: the #GtkCellRenderer to set attributes on
1180  * @attribute: An attribute on the renderer
1181  * @column: The column position on the model to get the attribute from.
1182  * 
1183  * Adds an attribute mapping to the list in @tree_column.  The @column is the
1184  * column of the model to get a value from, and the @attribute is the
1185  * parameter on @cell_renderer to be set from the value. So for example
1186  * if column 2 of the model contains strings, you could have the
1187  * "text" attribute of a #GtkCellRendererText get its values from
1188  * column 2.
1189  **/
1190 void
1191 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1192                                     GtkCellRenderer   *cell_renderer,
1193                                     const gchar       *attribute,
1194                                     gint               column)
1195 {
1196   GtkTreeViewColumnCellInfo *info;
1197
1198   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1199   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1200   g_return_if_fail (info != NULL);
1201
1202   info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
1203   info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
1204
1205   if (tree_column->tree_view)
1206     gtk_tree_view_column_cell_set_dirty (tree_column);
1207
1208 }
1209
1210 static void
1211 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1212                                       GtkCellRenderer   *cell_renderer,
1213                                       va_list            args)
1214 {
1215   gchar *attribute;
1216   gint column;
1217
1218   attribute = va_arg (args, gchar *);
1219
1220   gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1221   
1222   while (attribute != NULL)
1223     {
1224       column = va_arg (args, gint);
1225       gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1226       attribute = va_arg (args, gchar *);
1227     }
1228 }
1229
1230 /**
1231  * gtk_tree_view_column_set_attributes:
1232  * @tree_column: A #GtkTreeViewColumn.
1233  * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1234  * @Varargs: A NULL terminated listing of attributes.
1235  * 
1236  * Sets the attributes in the list as the attributes of @tree_column.
1237  * The attributes should be in attribute/column order, as in
1238  * @gtk_tree_view_column_add_attribute. All existing attributes
1239  * are removed, and replaced with the new attributes.
1240  **/
1241 void
1242 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1243                                      GtkCellRenderer   *cell_renderer,
1244                                      ...)
1245 {
1246   va_list args;
1247
1248   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1249   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1250   g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1251
1252   va_start (args, cell_renderer);
1253   gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1254   va_end (args);
1255 }
1256
1257
1258 /**
1259  * gtk_tree_view_column_set_cell_data_func:
1260  * @tree_column: A #GtkTreeViewColumn
1261  * @func: The #GtkTreeViewColumnFunc to use. 
1262  * @func_data: The user data for @func.
1263  * @destroy: The destroy notification for @func_data
1264  * 
1265  * Sets the #GtkTreeViewColumnFunc to use for the column.  This
1266  * function is used instead of the standard attributes mapping for
1267  * setting the column value, and should set the value of @tree_column's
1268  * cell renderer as appropriate.  @func may be NULL to remove an
1269  * older one.
1270  **/
1271 void
1272 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn   *tree_column,
1273                                          GtkCellRenderer     *cell_renderer,
1274                                          GtkTreeCellDataFunc  func,
1275                                          gpointer             func_data,
1276                                          GtkDestroyNotify     destroy)
1277 {
1278   GtkTreeViewColumnCellInfo *info;
1279
1280   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1281   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1282   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1283
1284   g_return_if_fail (info != NULL);
1285
1286   if (func == info->func &&
1287       func_data == info->func_data &&
1288       destroy == info->destroy)
1289     return;
1290
1291   if (info->func_data && info->destroy)
1292     (info->destroy) (info->func_data);
1293
1294   info->func = func;
1295   info->func_data = func_data;
1296   info->destroy = destroy;
1297
1298   if (tree_column->tree_view)
1299     gtk_tree_view_column_cell_set_dirty (tree_column);
1300 }
1301
1302
1303 /**
1304  * gtk_tree_view_column_clear_attributes:
1305  * @tree_column: a #GtkTreeViewColumn
1306  *@cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1307  * 
1308  * Clears all existing attributes previously set with
1309  * gtk_tree_view_column_set_attributes().
1310  **/
1311 void
1312 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1313                                        GtkCellRenderer   *cell_renderer)
1314 {
1315   GtkTreeViewColumnCellInfo *info;
1316   GSList *list;
1317
1318   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1319   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1320   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1321
1322   list = info->attributes;
1323
1324   while (list && list->next)
1325     {
1326       g_free (list->data);
1327       list = list->next->next;
1328     }
1329   g_slist_free (info->attributes);
1330   info->attributes = NULL;
1331
1332   if (tree_column->tree_view)
1333     gtk_tree_view_column_cell_set_dirty (tree_column);
1334 }
1335
1336
1337 /**
1338  * gtk_tree_view_column_set_spacing:
1339  * @tree_column: A #GtkTreeViewColumn.
1340  * @spacing: distance between cell renderers in pixels.
1341  * 
1342  * Sets the spacing field of @tree_column, which is the number of pixels to
1343  * place between cell renderers packed into it.
1344  **/
1345 void
1346 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1347                                   gint               spacing)
1348 {
1349   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1350   g_return_if_fail (spacing >= 0);
1351
1352   if (tree_column->spacing == spacing)
1353     return;
1354
1355   tree_column->spacing = spacing;
1356   if (tree_column->tree_view)
1357     gtk_tree_view_column_cell_set_dirty (tree_column);
1358 }
1359
1360 /**
1361  * gtk_tree_view_column_get_spacing:
1362  * @tree_column: A #GtkTreeViewColumn.
1363  * 
1364  * Returns the spacing of @tree_column.
1365  **/
1366 gint
1367 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1368 {
1369   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1370
1371   return tree_column->spacing;
1372 }
1373
1374 /* Options for manipulating the columns */
1375
1376 /**
1377  * gtk_tree_view_column_set_visible:
1378  * @tree_column: A #GtkTreeViewColumn.
1379  * @visible: TRUE if the @tree_column is visible.
1380  * 
1381  * Sets the visibility of @tree_column.
1382  **/
1383 void
1384 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1385                                   gboolean           visible)
1386 {
1387   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1388
1389   visible = !! visible;
1390   
1391   if (tree_column->visible == visible)
1392     return;
1393
1394   tree_column->visible = visible;
1395
1396   gtk_tree_view_column_update_button (tree_column);
1397   g_object_notify (G_OBJECT (tree_column), "visible");
1398 }
1399
1400 /**
1401  * gtk_tree_view_column_get_visible:
1402  * @tree_column: A #GtkTreeViewColumn.
1403  * 
1404  * Returns TRUE if @tree_column is visible.
1405  * 
1406  * Return value: whether the column is visible or not.  If it is visible, then
1407  * the tree will show the column.
1408  **/
1409 gboolean
1410 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1411 {
1412   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1413
1414   return tree_column->visible;
1415 }
1416
1417 /**
1418  * gtk_tree_view_column_set_sizing:
1419  * @tree_column: A #GtkTreeViewColumn.
1420  * @type: The #GtkTreeViewColumnSizing.
1421  * 
1422  * Sets the growth behavior of @tree_column to @type.
1423  **/
1424 void
1425 gtk_tree_view_column_set_sizing (GtkTreeViewColumn       *tree_column,
1426                                  GtkTreeViewColumnSizing  type)
1427 {
1428   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1429
1430   if (type == tree_column->column_type)
1431     return;
1432
1433   if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1434       tree_column->requested_width != -1)
1435     {
1436       gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1437     }
1438   tree_column->column_type = type;
1439
1440   gtk_tree_view_column_update_button (tree_column);
1441
1442   if (type != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1443   g_object_notify (G_OBJECT (tree_column), "sizing");
1444 }
1445
1446 /**
1447  * gtk_tree_view_column_get_sizing:
1448  * @tree_column: A #GtkTreeViewColumn.
1449  * 
1450  * Returns the current type of @tree_column.
1451  * 
1452  * Return value: The type of @tree_column.
1453  **/
1454 GtkTreeViewColumnSizing
1455 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1456 {
1457   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1458
1459   return tree_column->column_type;
1460 }
1461
1462 /**
1463  * gtk_tree_view_column_get_width:
1464  * @tree_column: A #GtkTreeViewColumn.
1465  * 
1466  * Returns the current size of the @tree_column in pixels.
1467  * 
1468  * Return value: The current width of the @tree_column.
1469  **/
1470 gint
1471 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1472 {
1473   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1474
1475   return tree_column->width;
1476 }
1477
1478 /**
1479  * gtk_tree_view_column_set_fixed_width:
1480  * @tree_column: A #GtkTreeViewColumn.
1481  * @width: The size to set the @tree_column to.
1482  * 
1483  * Sets the size of the column in pixels.  This is meaningful only if the sizing
1484  * type is #GTK_TREE_VIEW_COLUMN_FIXED.  In this case, the value is discarded
1485  * as the size of the column is based on the calculated width of the column. The
1486  * width is clamped to the min/max width for the column.
1487  **/
1488 void
1489 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1490                                       gint               width)
1491 {
1492   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1493   g_return_if_fail (width > 0);
1494
1495   if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1496     return;
1497
1498   tree_column->fixed_width = width;
1499   tree_column->requested_width = width;
1500   _gtk_tree_view_column_set_width (tree_column, width);
1501 }
1502
1503 /**
1504  * gtk_tree_view_column_get_fixed_width:
1505  * @tree_column: a #GtkTreeViewColumn
1506  * 
1507  * Gets the fixed width of the column.  This value is only meaning may not be the
1508  * actual width of the column on the screen, just what is requested.
1509  * 
1510  * Return value: the fixed width of the column
1511  **/
1512 gint
1513 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1514 {
1515   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1516
1517   return tree_column->fixed_width;
1518 }
1519
1520 /**
1521  * gtk_tree_view_column_set_min_width:
1522  * @tree_column: A #GtkTreeViewColumn.
1523  * @min_width: The minimum width of the column in pixels, or -1.
1524  * 
1525  * Sets the minimum width of the @tree_column.  If @min_width is -1, then the
1526  * minimum width is unset.
1527  **/
1528 void
1529 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1530                                     gint               min_width)
1531 {
1532   gint real_min_width;
1533
1534   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1535   g_return_if_fail (min_width >= -1);
1536
1537   if (min_width == tree_column->min_width)
1538     return;
1539
1540   if (tree_column->tree_view == NULL)
1541     {
1542       tree_column->min_width = min_width;
1543       return;
1544     }
1545
1546   real_min_width = (tree_column->min_width == -1) ?
1547     tree_column->button->requisition.width : tree_column->min_width;
1548
1549   /* We want to queue a resize if the either the old min_size or the
1550    * new min_size determined the size of the column */
1551   if (GTK_WIDGET_REALIZED (tree_column->tree_view))
1552     {
1553       if ((tree_column->min_width > tree_column->width) ||
1554           (tree_column->min_width == -1 &&
1555            tree_column->button->requisition.width > tree_column->width) ||
1556           (min_width > tree_column->width) ||
1557           (min_width == -1 &&
1558            tree_column->button->requisition.width > tree_column->width))
1559         gtk_widget_queue_resize (tree_column->tree_view);
1560     }
1561
1562   if (tree_column->max_width != -1 && tree_column->max_width < real_min_width)
1563     tree_column->max_width = real_min_width;
1564
1565   tree_column->min_width = min_width;
1566
1567   g_object_notify (G_OBJECT (tree_column), "min_width");
1568 }
1569
1570 /**
1571  * gtk_tree_view_column_get_min_width:
1572  * @tree_column: A #GtkTreeViewColumn.
1573  * 
1574  * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
1575  * width is set.
1576  * 
1577  * Return value: The minimum width of the @tree_column.
1578  **/
1579 gint
1580 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
1581 {
1582   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1583
1584   return tree_column->min_width;
1585 }
1586
1587 /**
1588  * gtk_tree_view_column_set_max_width:
1589  * @tree_column: A #GtkTreeViewColumn.
1590  * @max_width: The maximum width of the column in pixels, or -1.
1591  * 
1592  * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
1593  * maximum width is unset.  Note, the column can actually be wider than max
1594  * width if it's the last column in a view.  In this case, the column expands to
1595  * fill the view.
1596  **/
1597 void
1598 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
1599                                     gint               max_width)
1600 {
1601   gint real_max_width;
1602
1603   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1604   g_return_if_fail (max_width >= -1);
1605
1606   if (max_width == tree_column->max_width)
1607     return;
1608
1609   if (tree_column->tree_view == NULL)
1610     {
1611       tree_column->max_width = max_width;
1612       return;
1613     }
1614
1615   real_max_width = tree_column->max_width == -1 ?
1616     tree_column->button->requisition.width : tree_column->max_width;
1617
1618   if (tree_column->tree_view &&
1619       GTK_WIDGET_REALIZED (tree_column->tree_view) &&
1620       ((tree_column->max_width < tree_column->width) ||
1621        (max_width != -1 && max_width < tree_column->width)))
1622     gtk_widget_queue_resize (tree_column->tree_view);
1623
1624   tree_column->max_width = max_width;
1625
1626   if (real_max_width > max_width)
1627     tree_column->max_width = max_width;
1628
1629   g_object_notify (G_OBJECT (tree_column), "max_width");
1630 }
1631
1632 /**
1633  * gtk_tree_view_column_get_max_width:
1634  * @tree_column: A #GtkTreeViewColumn.
1635  * 
1636  * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
1637  * width is set.
1638  * 
1639  * Return value: The maximum width of the @tree_column.
1640  **/
1641 gint
1642 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
1643 {
1644   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1645
1646   return tree_column->max_width;
1647 }
1648
1649 /**
1650  * gtk_tree_view_column_clicked:
1651  * @tree_column: a #GtkTreeViewColumn
1652  * 
1653  * Emits the "clicked" signal on the column.  This function will only work if
1654  * the user could have conceivably clicked on the button.
1655  **/
1656 void
1657 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
1658 {
1659   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1660
1661   if (tree_column->visible &&
1662       tree_column->button &&
1663       tree_column->clickable)
1664     gtk_button_clicked (GTK_BUTTON (tree_column->button));
1665 }
1666
1667 /**
1668  * gtk_tree_view_column_set_title:
1669  * @tree_column: A #GtkTreeViewColumn.
1670  * @title: The title of the @tree_column.
1671  * 
1672  * Sets the title of the @tree_column.  If a custom widget has been set, then
1673  * this value is ignored.
1674  **/
1675 void
1676 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
1677                                 const gchar       *title)
1678 {
1679   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1680
1681   g_free (tree_column->title);
1682   if (title)
1683     tree_column->title = g_strdup (title);
1684   else
1685     tree_column->title = NULL;
1686
1687   gtk_tree_view_column_update_button (tree_column);
1688   g_object_notify (G_OBJECT (tree_column), "title");
1689 }
1690
1691 /**
1692  * gtk_tree_view_column_get_title:
1693  * @tree_column: A #GtkTreeViewColumn.
1694  * 
1695  * Returns the title of the widget.  This value should not be modified.
1696  * 
1697  * Return value: the title of the column.
1698  **/
1699 G_CONST_RETURN gchar *
1700 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
1701 {
1702   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1703
1704   return tree_column->title;
1705 }
1706
1707 /**
1708  * gtk_tree_view_column_set_clickable:
1709  * @tree_column: A #GtkTreeViewColumn.
1710  * @clickable: TRUE if the header is active.
1711  * 
1712  * Sets the header to be active if @active is TRUE.  When the header is active,
1713  * then it can take keyboard focus, and can be clicked.
1714  **/
1715 void
1716 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
1717                                     gboolean           clickable)
1718 {
1719   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1720
1721   if (tree_column->clickable == (clickable?TRUE:FALSE))
1722     return;
1723
1724   tree_column->clickable = (clickable?TRUE:FALSE);
1725   gtk_tree_view_column_update_button (tree_column);
1726   g_object_notify (G_OBJECT (tree_column), "clickable");
1727 }
1728
1729 /**
1730  * gtk_tree_view_column_get_clickable:
1731  * @tree_column: a #GtkTreeViewColumn
1732  * 
1733  * Returns %TRUE if the user can click on the header for the column.
1734  * 
1735  * Return value: whether the user can click the column header
1736  **/
1737 gboolean
1738 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1739 {
1740   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1741
1742   return tree_column->clickable;
1743 }
1744
1745 /**
1746  * gtk_tree_view_column_set_widget:
1747  * @tree_column: A #GtkTreeViewColumn.
1748  * @widget: A child #GtkWidget, or NULL.
1749  * 
1750  * Sets the widget in the header to be @widget.  If widget is NULL, then the
1751  * header button is set with a #GtkLabel set to the title of @tree_column.
1752  **/
1753 void
1754 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1755                                  GtkWidget         *widget)
1756 {
1757   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1758   g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1759
1760   if (widget)
1761     {
1762       gtk_object_ref (GTK_OBJECT (widget));
1763       gtk_object_sink (GTK_OBJECT (widget));
1764     }
1765
1766   if (tree_column->child)      
1767     gtk_object_unref (GTK_OBJECT (tree_column->child));
1768
1769   tree_column->child = widget;
1770   gtk_tree_view_column_update_button (tree_column);
1771   g_object_notify (G_OBJECT (tree_column), "widget");
1772 }
1773
1774 /**
1775  * gtk_tree_view_column_get_widget:
1776  * @tree_column: A #GtkTreeViewColumn.
1777  * 
1778  * Returns the #GtkWidget in the button in the column header.  If a custom
1779  * widget has not been set, then this will be a #GtkAlignment with a #GtkLabel
1780  * in it.
1781  * 
1782  * Return value: The #GtkWidget in the column header.
1783  **/
1784 GtkWidget *
1785 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1786 {
1787   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1788
1789   return tree_column->child;
1790 }
1791
1792 /**
1793  * gtk_tree_view_column_set_alignment:
1794  * @tree_column: A #GtkTreeViewColumn.
1795  * @xalign: alignment (0.0 for left, 0.5 for center, 1.0 for right)
1796  * 
1797  * Sets the alignment of the title or custom widget inside the column header.
1798  **/
1799 void
1800 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
1801                                     gfloat             xalign)
1802 {
1803   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1804
1805   if (tree_column->xalign == xalign)
1806     return;
1807
1808   tree_column->xalign = xalign;
1809   gtk_tree_view_column_update_button (tree_column);
1810   g_object_notify (G_OBJECT (tree_column), "alignment");
1811 }
1812
1813 /**
1814  * gtk_tree_view_column_get_alignment:
1815  * @tree_column: A #GtkTreeViewColumn.
1816  * 
1817  * Returns the current x alignment of @tree_column.  This value can range
1818  * between 0.0 and 1.0.
1819  * 
1820  * Return value: The current alignent of @tree_column.
1821  **/
1822 gfloat
1823 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
1824 {
1825   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
1826
1827   return tree_column->xalign;
1828 }
1829
1830 void
1831 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
1832                                       gboolean           reorderable)
1833 {
1834   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1835
1836   /*  if (reorderable)
1837       gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
1838
1839   if (tree_column->reorderable == (reorderable?TRUE:FALSE))
1840     return;
1841
1842   tree_column->reorderable = (reorderable?TRUE:FALSE);
1843   gtk_tree_view_column_update_button (tree_column);
1844   g_object_notify (G_OBJECT (tree_column), "reorderable");
1845 }
1846
1847 gboolean
1848 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
1849 {
1850   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1851
1852   return tree_column->reorderable;
1853 }
1854
1855
1856 /**
1857  * gtk_tree_view_column_set_sort_column_id:
1858  * @tree_column: a #GtkTreeViewColumn
1859  * @sort_column_id: The sort_column_id of the model to sort on.
1860  * 
1861  * Sets the logical sort_column_id that this column sorts on when this column is
1862  * selected for sorting.  Doing so makes the column header clickable.
1863  **/
1864 void
1865 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
1866                                          gint               sort_column_id)
1867 {
1868   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1869   g_return_if_fail (sort_column_id >= 0);
1870
1871   if (tree_column->sort_column_id == sort_column_id)
1872     return;
1873
1874   tree_column->sort_column_id = sort_column_id;
1875
1876   /* Handle unsetting the id */
1877   if (sort_column_id == -1)
1878     {
1879       if (tree_column->sort_clicked_signal)
1880         {
1881           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal);
1882           tree_column->sort_clicked_signal = 0;
1883         }
1884
1885       if (tree_column->sort_column_changed_signal)
1886         {
1887           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_column_changed_signal);
1888           tree_column->sort_column_changed_signal = 0;
1889         }
1890
1891       gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
1892       gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1893       return;
1894     }
1895
1896   gtk_tree_view_column_set_clickable (tree_column, TRUE);
1897
1898   if (! tree_column->sort_clicked_signal)
1899     tree_column->sort_clicked_signal = g_signal_connect (G_OBJECT (tree_column),
1900                                                          "clicked",
1901                                                          G_CALLBACK (gtk_tree_view_column_sort),
1902                                                          NULL);
1903
1904   gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
1905 }
1906
1907 /**
1908  * gtk_tree_view_column_get_sort_column_id:
1909  * @tree_column: a #GtkTreeViewColumn
1910  *
1911  * Gets the logical sort_column_id that the model sorts on when this
1912  * coumn is selected for sorting. See gtk_tree_view_column_set_sort_column_id().
1913  *
1914  * Return value: the current sort_column_id for this column, or -1 if
1915  *               this column can't be used for sorting.
1916  **/
1917 gint
1918 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
1919 {
1920   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1921
1922   return tree_column->sort_column_id;
1923 }
1924
1925 /**
1926  * gtk_tree_view_column_set_sort_indicator:
1927  * @tree_column: a #GtkTreeViewColumn
1928  * @setting: %TRUE to display an indicator that the column is sorted
1929  *
1930  * Call this function with a @setting of %TRUE to display an arrow in
1931  * the header button indicating the column is sorted. Call
1932  * gtk_tree_view_column_set_sort_order() to change the direction of
1933  * the arrow.
1934  * 
1935  **/
1936 void
1937 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn     *tree_column,
1938                                          gboolean               setting)
1939 {
1940   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1941
1942   setting = setting != FALSE;
1943
1944   if (setting == tree_column->show_sort_indicator)
1945     return;
1946
1947   tree_column->show_sort_indicator = setting;
1948   gtk_tree_view_column_update_button (tree_column);
1949   g_object_notify (G_OBJECT (tree_column), "sort_indicator");
1950 }
1951
1952 /**
1953  * gtk_tree_view_column_get_sort_indicator:
1954  * @tree_column: a #GtkTreeViewColumn
1955  * 
1956  * Gets the value set by gtk_tree_view_column_set_sort_indicator().
1957  * 
1958  * Return value: whether the sort indicator arrow is displayed
1959  **/
1960 gboolean
1961 gtk_tree_view_column_get_sort_indicator  (GtkTreeViewColumn     *tree_column)
1962 {
1963   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1964
1965   return tree_column->show_sort_indicator;
1966 }
1967
1968 /**
1969  * gtk_tree_view_column_set_sort_order:
1970  * @tree_column: a #GtkTreeViewColumn
1971  * @order: sort order that the sort indicator should indicate
1972  *
1973  * Changes the appearance of the sort indicator. (This <emphasis>does
1974  * not</emphasis> actually sort the model.  Use
1975  * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
1976  * support.  This function is primarily for custom sorting behavior, and should
1977  * be used in conjunction with #gtk_tree_sortable_set_sort_column() to do
1978  * that. For custom models, the mechanism will vary. The sort indicator changes
1979  * direction to indicate normal sort or reverse sort. Note that you must have
1980  * the sort indicator enabled to see anything when calling this function; see
1981  * gtk_tree_view_column_set_sort_indicator().
1982  * 
1983  **/
1984 void
1985 gtk_tree_view_column_set_sort_order      (GtkTreeViewColumn     *tree_column,
1986                                           GtkSortType            order)
1987 {
1988   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1989
1990   if (order == tree_column->sort_order)
1991     return;
1992
1993   tree_column->sort_order = order;
1994   gtk_tree_view_column_update_button (tree_column);
1995   g_object_notify (G_OBJECT (tree_column), "sort_order");
1996 }
1997
1998 /**
1999  * gtk_tree_view_column_get_sort_order:
2000  * @tree_column: a #GtkTreeViewColumn
2001  * 
2002  * Gets the value set by gtk_tree_view_column_set_sort_order().
2003  * 
2004  * Return value: the sort order the sort indicator is indicating
2005  **/
2006 GtkSortType
2007 gtk_tree_view_column_get_sort_order      (GtkTreeViewColumn     *tree_column)
2008 {
2009   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2010
2011   return tree_column->sort_order;
2012 }
2013
2014 /**
2015  * gtk_tree_view_column_cell_set_cell_data:
2016  * @tree_column: A #GtkTreeViewColumn.
2017  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2018  * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2019  * @is_expander: TRUE, if the row has children
2020  * @is_expanded: TRUE, if the row has visible children
2021  * 
2022  * Sets the cell renderer based on the @tree_model and @tree_node.  That is, for
2023  * every attribute mapping in @tree_column, it will get a value from the set
2024  * column on the @tree_node, and use that value to set the attribute on the cell
2025  * renderer.  This is used primarily by the GtkTreeView.
2026  **/
2027 void
2028 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2029                                          GtkTreeModel      *tree_model,
2030                                          GtkTreeIter       *iter,
2031                                          gboolean           is_expander,
2032                                          gboolean           is_expanded)
2033 {
2034   GSList *list;
2035   GValue value = { 0, };
2036   GList *cell_list;
2037
2038   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2039   g_return_if_fail (tree_column->cell_list != NULL);
2040
2041   if (tree_model == NULL)
2042     return;
2043
2044   for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2045     {
2046       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2047       GObject *cell = (GObject *) info->cell;
2048
2049       list = info->attributes;
2050
2051       g_object_freeze_notify (cell);
2052       g_object_set (cell, "is_expander", is_expander, "is_expanded", is_expanded, NULL);
2053
2054       while (list && list->next)
2055         {
2056           gtk_tree_model_get_value (tree_model, iter,
2057                                     GPOINTER_TO_INT (list->next->data),
2058                                     &value);
2059           g_object_set_property (cell, (gchar *) list->data, &value);
2060           g_value_unset (&value);
2061           list = list->next->next;
2062         }
2063
2064       if (info->func)
2065         (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2066       g_object_thaw_notify (G_OBJECT (info->cell));
2067     }
2068
2069 }
2070
2071 /**
2072  * gtk_tree_view_column_cell_get_size:
2073  * @tree_column: A #GtkTreeViewColumn.
2074  * @cell_area: The area a the column will be allocated, or %NULL
2075  * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
2076  * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
2077  * @width: location to return width needed to render a cell, or %NULL
2078  * @height: location to return height needed to render a cell, or %NULL
2079  * 
2080  * Obtains the width and height needed to render the column.  This is used
2081  * primarily by the GtkTreeView.
2082  **/
2083 void
2084 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2085                                     GdkRectangle      *cell_area,
2086                                     gint              *x_offset,
2087                                     gint              *y_offset,
2088                                     gint              *width,
2089                                     gint              *height)
2090 {
2091   GList *list;
2092   gboolean first_cell = TRUE;
2093
2094   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2095
2096   if (height)
2097     * height = 0;
2098   if (width)
2099     * width = 0;
2100
2101   for (list = tree_column->cell_list; list; list = list->next)
2102     {
2103       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2104       gboolean visible;
2105       gint new_height = 0;
2106       gint new_width = 0;
2107       g_object_get (info->cell, "visible", &visible, NULL);
2108
2109       if (visible == FALSE)
2110         continue;
2111
2112       if (first_cell == FALSE && *width)
2113         *width += tree_column->spacing;
2114
2115       gtk_cell_renderer_get_size (info->cell,
2116                                   tree_column->tree_view,
2117                                   cell_area,
2118                                   x_offset,
2119                                   y_offset,
2120                                   &new_width,
2121                                   &new_height);
2122
2123       if (height)
2124         * height = MAX (*height, new_height);
2125       info->requested_width = MAX (info->requested_width, new_width);
2126       if (width)
2127         * width += info->requested_width;
2128       first_cell = TRUE;
2129     }
2130 }
2131
2132 /**
2133  * gtk_tree_view_column_cell_render:
2134  * @tree_column: A #GtkTreeViewColumn.
2135  * @window: a #GdkDrawable to draw to
2136  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2137  * @cell_area: area normally rendered by a cell renderer
2138  * @expose_area: area that actually needs updating
2139  * @flags: flags that affect rendering
2140  * 
2141  * Renders the cell contained by #tree_column. This is used primarily by the
2142  * GtkTreeView.
2143  **/
2144 void
2145 gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
2146                                   GdkWindow         *window,
2147                                   GdkRectangle      *background_area,
2148                                   GdkRectangle      *cell_area,
2149                                   GdkRectangle      *expose_area,
2150                                   guint              flags)
2151 {
2152   GList *list;
2153   GdkRectangle real_cell_area;
2154   gint expand_cell_count = 0;
2155   gint full_requested_width = 0;
2156   gint extra_space;
2157
2158   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2159   g_return_if_fail (background_area != NULL);
2160   g_return_if_fail (cell_area != NULL);
2161   g_return_if_fail (expose_area != NULL);
2162
2163   real_cell_area = *cell_area;
2164     
2165   /* Find out how my extra space we have to allocate */
2166   for (list = tree_column->cell_list; list; list = list->next)
2167     {
2168       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2169       gboolean visible;
2170
2171       g_object_get (info->cell, "visible", &visible, NULL);
2172       if (visible == FALSE)
2173         continue;
2174
2175       if (info->expand == TRUE)
2176         expand_cell_count ++;
2177       full_requested_width += info->requested_width;
2178     }
2179
2180   extra_space = cell_area->width - full_requested_width;
2181   if (extra_space < 0)
2182     extra_space = 0;
2183
2184   for (list = tree_column->cell_list; list; list = list->next)
2185     {
2186       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2187       gboolean visible;
2188
2189       if (info->pack == GTK_PACK_END)
2190         continue;
2191
2192       g_object_get (info->cell, "visible", &visible, NULL);
2193       if (visible == FALSE)
2194         continue;
2195
2196       real_cell_area.width = info->requested_width +
2197         (info->expand?extra_space:0);
2198       gtk_cell_renderer_render (info->cell,
2199                                 window,
2200                                 tree_column->tree_view,
2201                                 background_area,
2202                                 &real_cell_area,
2203                                 expose_area,
2204                                 flags);
2205       real_cell_area.x += (info->requested_width + tree_column->spacing);
2206     }
2207   for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2208     {
2209       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2210       gboolean visible;
2211
2212       if (info->pack == GTK_PACK_START)
2213         continue;
2214
2215       g_object_get (info->cell, "visible", &visible, NULL);
2216       if (visible == FALSE)
2217         continue;
2218
2219       real_cell_area.width = info->requested_width +
2220         (info->expand?extra_space:0);
2221       gtk_cell_renderer_render (info->cell,
2222                                 window,
2223                                 tree_column->tree_view,
2224                                 background_area,
2225                                 &real_cell_area,
2226                                 expose_area,
2227                                 flags);
2228       real_cell_area.x += (info->requested_width + tree_column->spacing);
2229     }
2230 }
2231
2232 /**
2233  * gtk_tree_view_column_cell_event:
2234  * @tree_column: A #GtkTreeViewColumn.
2235  * @event: a #GdkEvent
2236  * @path_string: widget-dependent string representation of the event location; e.g. for #GtkTreeView, a string representation of #GtkTreePath
2237  * @background_area: background area as passed to gtk_cell_renderer_render()
2238  * @cell_area: cell area as passed to gtk_cell_renderer_render()
2239  * @flags: render flags
2240  * 
2241  * Handles an event.  This is used primarily by the GtkTreeView.
2242  * 
2243  * Return value: %TRUE if the event was consumed/handled
2244  **/
2245 gboolean
2246 gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
2247                                  GdkEvent          *event,
2248                                  gchar             *path_string,
2249                                  GdkRectangle      *background_area,
2250                                  GdkRectangle      *cell_area,
2251                                  guint              flags)
2252 {
2253   gboolean visible, can_activate;
2254
2255   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2256
2257   g_object_get (G_OBJECT (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell),
2258                 "visible", &visible,
2259                 "can_activate", &can_activate,
2260                 NULL);
2261   if (visible && can_activate)
2262     {
2263       if (gtk_cell_renderer_activate (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2264                                       event,
2265                                       tree_column->tree_view,
2266                                       path_string,
2267                                       background_area,
2268                                       cell_area,
2269                                       flags))
2270         return TRUE;
2271
2272     }
2273   return FALSE;
2274 }
2275
2276
2277 gboolean
2278 gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
2279                                  gint               direction,
2280                                  gboolean           unfocus)
2281 {
2282   if (unfocus)
2283     GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column = NULL;
2284   else
2285     GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column = tree_column;
2286   return TRUE;
2287 }
2288
2289 void
2290 gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn       *tree_column,
2291                                       GdkWindow               *window,
2292                                       GdkRectangle            *background_area,
2293                                       GdkRectangle            *cell_area,
2294                                       GdkRectangle            *expose_area,
2295                                       guint                    flags)
2296 {
2297   gtk_paint_focus (tree_column->tree_view->style,
2298                    window,
2299                    NULL,
2300                    tree_column->tree_view,
2301                    "treeview",
2302                    cell_area->x,
2303                    cell_area->y,
2304                    cell_area->width-1,
2305                    cell_area->height);
2306 }
2307
2308 gboolean
2309 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2310 {
2311   GList *list;
2312
2313   for (list = tree_column->cell_list; list; list = list->next)
2314     {
2315       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2316       gboolean visible;
2317
2318       g_object_get (G_OBJECT (info->cell), "visible", &visible, NULL);
2319
2320       if (visible)
2321         return TRUE;
2322     }
2323
2324   return FALSE;
2325 }
2326
2327 void
2328 gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column)
2329 {
2330   GList *list;
2331
2332   for (list = tree_column->cell_list; list; list = list->next)
2333     {
2334       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2335
2336       info->requested_width = 0;
2337     }
2338   tree_column->dirty = TRUE;
2339
2340   if (tree_column->tree_view)
2341     gtk_widget_queue_resize (tree_column->tree_view);
2342 }
2343