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