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