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