]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeviewcolumn.c
Fix docs for gtk_tree_view_column_set_sort_order. (#62647)
[~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             {
699               gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
700             }
701         }
702     }
703
704   gtk_tree_view_column_cell_set_dirty (tree_column);
705 }
706
707 /* Button signal handlers
708  */
709
710 static gint
711 gtk_tree_view_column_button_event (GtkWidget *widget,
712                                    GdkEvent  *event,
713                                    gpointer   data)
714 {
715   GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
716
717   g_return_val_if_fail (event != NULL, FALSE);
718
719   if (event->type == GDK_BUTTON_PRESS &&
720       column->reorderable)
721     {
722       column->maybe_reordered = TRUE;
723       gdk_window_get_pointer (widget->window,
724                               &column->drag_x,
725                               &column->drag_y,
726                               NULL);
727       gtk_widget_grab_focus (widget);
728     }
729
730   if (event->type == GDK_BUTTON_RELEASE &&
731       column->maybe_reordered)
732     column->maybe_reordered = FALSE;
733
734   if (event->type == GDK_MOTION_NOTIFY &&
735       (column->maybe_reordered) &&
736       (gtk_drag_check_threshold (widget,
737                                  column->drag_x,
738                                  column->drag_y,
739                                  (gint) ((GdkEventMotion *)event)->x,
740                                  (gint) ((GdkEventMotion *)event)->y)))
741     {
742       column->maybe_reordered = FALSE;
743       _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
744       return TRUE;
745     }
746   if (column->clickable == FALSE)
747     {
748       switch (event->type)
749         {
750         case GDK_BUTTON_PRESS:
751         case GDK_2BUTTON_PRESS:
752         case GDK_3BUTTON_PRESS:
753         case GDK_MOTION_NOTIFY:
754         case GDK_BUTTON_RELEASE:
755         case GDK_ENTER_NOTIFY:
756         case GDK_LEAVE_NOTIFY:
757           return TRUE;
758         default:
759           return FALSE;
760         }
761     }
762   return FALSE;
763 }
764
765 static void
766 gtk_tree_view_column_button_realize (GtkWidget *widget, gpointer data)
767 {
768   gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | GDK_POINTER_MOTION_MASK);
769 }
770
771 static void
772 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
773 {
774   g_signal_emit_by_name (G_OBJECT (data), "clicked");
775 }
776
777 static void
778 gtk_tree_view_model_sort_column_changed (GtkTreeSortable   *sortable,
779                                           GtkTreeViewColumn *column)
780 {
781   gint sort_column_id;
782   GtkSortType order;
783
784   if (gtk_tree_sortable_get_sort_column_id (sortable,
785                                             &sort_column_id,
786                                             &order))
787     {
788       if (sort_column_id == column->sort_column_id)
789         {
790           gtk_tree_view_column_set_sort_indicator (column, TRUE);
791           gtk_tree_view_column_set_sort_order (column, order);
792         }
793       else
794         {
795           gtk_tree_view_column_set_sort_indicator (column, FALSE);
796         }
797     }
798   else
799     {
800       gtk_tree_view_column_set_sort_indicator (column, FALSE);
801     }
802 }
803
804 static void
805 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
806                            gpointer           data)
807 {
808   gint sort_column_id;
809   GtkSortType order;
810   gboolean has_sort_column;
811   gboolean has_default_sort_func;
812
813   g_return_if_fail (tree_column->tree_view != NULL);
814
815   has_sort_column =
816     gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
817                                           &sort_column_id,
818                                           &order);
819   has_default_sort_func =
820     gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model));
821
822   if (has_sort_column &&
823       sort_column_id == tree_column->sort_column_id)
824     {
825       if (order == GTK_SORT_ASCENDING)
826         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
827                                               tree_column->sort_column_id,
828                                               GTK_SORT_DESCENDING);
829       else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
830         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
831                                               GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
832                                               GTK_SORT_ASCENDING);
833       else
834         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
835                                               tree_column->sort_column_id,
836                                               GTK_SORT_ASCENDING);
837     }
838   else
839     {
840       gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
841                                             tree_column->sort_column_id,
842                                             GTK_SORT_ASCENDING);
843     }
844 }
845
846
847 static void
848 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
849 {
850   GtkTreeModel *model;
851
852   if (tree_column->tree_view == NULL)
853     return;
854
855   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
856
857   if (model == NULL)
858     return;
859
860   if (GTK_IS_TREE_SORTABLE (model) &&
861       tree_column->sort_column_id != -1)
862     {
863       gint real_sort_column_id;
864       GtkSortType real_order;
865
866       if (tree_column->sort_column_changed_signal == 0)
867         tree_column->sort_column_changed_signal =
868           g_signal_connect (G_OBJECT (model), "sort_column_changed",
869                             GTK_SIGNAL_FUNC (gtk_tree_view_model_sort_column_changed),
870                             tree_column);
871       
872       if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
873                                                 &real_sort_column_id,
874                                                 &real_order) &&
875           (real_sort_column_id == tree_column->sort_column_id))
876         {
877           gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
878           gtk_tree_view_column_set_sort_order (tree_column, real_order);
879
880           return;
881         }
882     }
883 }
884
885
886 /* Exported Private Functions.
887  * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
888  */
889
890 void
891 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
892 {
893   GtkTreeView *tree_view;
894   GdkWindowAttr attr;
895   guint attributes_mask;
896
897   tree_view = (GtkTreeView *)column->tree_view;
898
899   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
900   g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
901   g_return_if_fail (tree_view->priv->header_window != NULL);
902   g_return_if_fail (column->button != NULL);
903
904   gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
905
906   if (column->visible)
907     gtk_widget_show (column->button);
908
909   attr.window_type = GDK_WINDOW_CHILD;
910   attr.wclass = GDK_INPUT_ONLY;
911   attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
912   attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
913   attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view));
914   attr.event_mask = (GDK_BUTTON_PRESS_MASK |
915                      GDK_BUTTON_RELEASE_MASK |
916                      GDK_POINTER_MOTION_MASK |
917                      GDK_POINTER_MOTION_HINT_MASK |
918                      GDK_KEY_PRESS_MASK);
919   attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
920   attr.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
921   tree_view->priv->cursor_drag = attr.cursor;
922
923   attr.y = 0;
924   attr.width = TREE_VIEW_DRAG_WIDTH;
925   attr.height = tree_view->priv->header_height;
926
927   attr.x = (column->button->allocation.x + column->button->allocation.width) - 3;
928           
929   column->window = gdk_window_new (tree_view->priv->header_window,
930                                    &attr, attributes_mask);
931   gdk_window_set_user_data (column->window, tree_view);
932
933   gtk_tree_view_column_update_button (column);
934 }
935
936 void
937 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
938 {
939   g_return_if_fail (column != NULL);
940   g_return_if_fail (column->window != NULL);
941
942   gdk_window_set_user_data (column->window, NULL);
943   gdk_window_destroy (column->window);
944   column->window = NULL;
945 }
946
947 void
948 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
949                                      GtkTreeView       *tree_view)
950 {
951   g_assert (column->tree_view == NULL);
952
953   column->tree_view = GTK_WIDGET (tree_view);
954   gtk_tree_view_column_create_button (column);
955
956   column->property_changed_signal =
957           g_signal_connect_swapped (GTK_OBJECT (tree_view),
958                                     "notify::model",
959                                     GTK_SIGNAL_FUNC (gtk_tree_view_column_setup_sort_column_id_callback),
960                                     column);
961
962   gtk_tree_view_column_setup_sort_column_id_callback (column);
963 }
964
965 void
966 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
967 {
968   if (column->tree_view && column->button)
969     {
970       gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
971     }
972   if (column->property_changed_signal)
973     {
974       g_signal_handler_disconnect (G_OBJECT (column->tree_view), column->property_changed_signal);
975       column->property_changed_signal = 0;
976     }
977
978   if (column->sort_column_changed_signal)
979     {
980       g_signal_handler_disconnect (G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view))),
981                                    column->sort_column_changed_signal);
982       column->sort_column_changed_signal = 0;
983     }
984
985   column->tree_view = NULL;
986   column->button = NULL;
987 }
988
989 void
990 _gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
991                                  gint               width)
992 {
993   if (tree_column->min_width != -1 &&
994       width <= tree_column->min_width)
995     width = tree_column->min_width;
996   else if (tree_column->max_width != -1 &&
997            width > tree_column->max_width)
998     width = tree_column->max_width;
999   
1000   if (tree_column->width == width)
1001     return;
1002   
1003   tree_column->width = width;
1004
1005   g_object_notify (G_OBJECT (tree_column), "width");
1006
1007   if (tree_column->tree_view != NULL)
1008     gtk_widget_queue_resize (tree_column->tree_view);
1009
1010 }
1011
1012 /* Public Functions */
1013
1014
1015 /**
1016  * gtk_tree_view_column_new:
1017  * 
1018  * Creates a new #GtkTreeViewColumn.
1019  * 
1020  * Return value: A newly created #GtkTreeViewColumn.
1021  **/
1022 GtkTreeViewColumn *
1023 gtk_tree_view_column_new (void)
1024 {
1025   GtkTreeViewColumn *tree_column;
1026
1027   tree_column = GTK_TREE_VIEW_COLUMN (gtk_type_new (GTK_TYPE_TREE_VIEW_COLUMN));
1028
1029   return tree_column;
1030 }
1031
1032 /**
1033  * gtk_tree_view_column_new_with_attributes:
1034  * @title: The title to set the header to.
1035  * @cell: The #GtkCellRenderer.
1036  * @Varargs: A NULL terminated list of attributes.
1037  * 
1038  * Creates a new #GtkTreeViewColumn with a number of default values.  This is
1039  * equivalent to calling @gtk_tree_view_column_set_title,
1040  * @gtk_tree_view_column_pack_start, and
1041  * @gtk_tree_view_column_set_attributes on the newly created #GtkTreeViewColumn.
1042  * 
1043  * Return value: A newly created #GtkTreeViewColumn.
1044  **/
1045 GtkTreeViewColumn *
1046 gtk_tree_view_column_new_with_attributes (const gchar     *title,
1047                                           GtkCellRenderer *cell,
1048                                           ...)
1049 {
1050   GtkTreeViewColumn *retval;
1051   va_list args;
1052
1053   retval = gtk_tree_view_column_new ();
1054
1055   gtk_tree_view_column_set_title (retval, title);
1056   gtk_tree_view_column_pack_start (retval, cell, TRUE);
1057
1058   va_start (args, cell);
1059   gtk_tree_view_column_set_attributesv (retval, cell, args);
1060   va_end (args);
1061
1062   return retval;
1063 }
1064
1065 static GtkTreeViewColumnCellInfo *
1066 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1067                                     GtkCellRenderer   *cell_renderer)
1068 {
1069   GList *list;
1070   for (list = tree_column->cell_list; list; list = list->next)
1071     if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1072       return (GtkTreeViewColumnCellInfo *) list->data;
1073   return NULL;
1074 }
1075
1076
1077 /**
1078  * gtk_tree_view_column_pack_start:
1079  * @tree_column: A #GtkTreeViewColumn.
1080  * @cell: The #GtkCellRenderer, 
1081  * @expand: TRUE if @cell is to be given extra space allocated to box.
1082  * 
1083  **/
1084 void
1085 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1086                                  GtkCellRenderer   *cell,
1087                                  gboolean           expand)
1088 {
1089   GtkTreeViewColumnCellInfo *cell_info;
1090
1091   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1092   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1093   g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1094
1095   g_object_ref (G_OBJECT (cell));
1096   gtk_object_sink (GTK_OBJECT (cell));
1097
1098   cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
1099   cell_info->cell = cell;
1100   cell_info->expand = expand ? TRUE : FALSE;
1101   cell_info->pack = GTK_PACK_START;
1102   cell_info->has_focus = 0;
1103   cell_info->attributes = NULL;
1104
1105   tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1106 }
1107
1108 void
1109 gtk_tree_view_column_pack_end (GtkTreeViewColumn  *tree_column,
1110                                GtkCellRenderer    *cell,
1111                                gboolean            expand)
1112 {
1113   GtkTreeViewColumnCellInfo *cell_info;
1114
1115   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1116   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1117   g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1118
1119   g_object_ref (G_OBJECT (cell));
1120   gtk_object_sink (GTK_OBJECT (cell));
1121
1122   cell_info = g_new (GtkTreeViewColumnCellInfo, 1);
1123   cell_info->cell = cell;
1124   cell_info->expand = expand ? TRUE : FALSE;
1125   cell_info->pack = GTK_PACK_END;
1126   cell_info->has_focus = 0;
1127   cell_info->attributes = NULL;
1128
1129   tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1130 }
1131
1132
1133 void
1134 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1135 {
1136   GList *list;
1137   g_return_if_fail (tree_column != NULL);
1138
1139   for (list = tree_column->cell_list; list; list = list->next)
1140     {
1141       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1142
1143       g_object_unref (G_OBJECT (info->cell));
1144       gtk_tree_view_column_clear_attributes (tree_column, info->cell);
1145       g_free (info);
1146     }
1147
1148   g_list_free (tree_column->cell_list);
1149   tree_column->cell_list = NULL;
1150 }
1151
1152 GList *
1153 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1154 {
1155   GList *retval = NULL, *list;
1156
1157   g_return_val_if_fail (tree_column != NULL, NULL);
1158
1159   for (list = tree_column->cell_list; list; list = list->next)
1160     {
1161       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1162
1163       retval = g_list_append (retval, info->cell);
1164     }
1165
1166   return retval;
1167 }
1168
1169 /**
1170  * gtk_tree_view_column_add_attribute:
1171  * @tree_column: A #GtkTreeViewColumn.
1172  * @cell_renderer: the #GtkCellRenderer to set attributes on
1173  * @attribute: An attribute on the renderer
1174  * @column: The column position on the model to get the attribute from.
1175  * 
1176  * Adds an attribute mapping to the list in @tree_column.  The @column is the
1177  * column of the model to get a value from, and the @attribute is the
1178  * parameter on @cell_renderer to be set from the value. So for example
1179  * if column 2 of the model contains strings, you could have the
1180  * "text" attribute of a #GtkCellRendererText get its values from
1181  * column 2.
1182  **/
1183 void
1184 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1185                                     GtkCellRenderer   *cell_renderer,
1186                                     const gchar       *attribute,
1187                                     gint               column)
1188 {
1189   GtkTreeViewColumnCellInfo *info;
1190
1191   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1192   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1193   g_return_if_fail (info != NULL);
1194
1195   info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
1196   info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
1197
1198   if (tree_column->tree_view)
1199     gtk_tree_view_column_cell_set_dirty (tree_column);
1200
1201 }
1202
1203 static void
1204 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1205                                       GtkCellRenderer   *cell_renderer,
1206                                       va_list            args)
1207 {
1208   gchar *attribute;
1209   gint column;
1210
1211   attribute = va_arg (args, gchar *);
1212
1213   gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1214   
1215   while (attribute != NULL)
1216     {
1217       column = va_arg (args, gint);
1218       gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1219       attribute = va_arg (args, gchar *);
1220     }
1221 }
1222
1223 /**
1224  * gtk_tree_view_column_set_attributes:
1225  * @tree_column: A #GtkTreeViewColumn.
1226  * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1227  * @Varargs: A NULL terminated listing of attributes.
1228  * 
1229  * Sets the attributes in the list as the attributes of @tree_column.
1230  * The attributes should be in attribute/column order, as in
1231  * @gtk_tree_view_column_add_attribute. All existing attributes
1232  * are removed, and replaced with the new attributes.
1233  **/
1234 void
1235 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1236                                      GtkCellRenderer   *cell_renderer,
1237                                      ...)
1238 {
1239   va_list args;
1240
1241   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1242   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1243   g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1244
1245   va_start (args, cell_renderer);
1246   gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1247   va_end (args);
1248 }
1249
1250
1251 /**
1252  * gtk_tree_view_column_set_cell_data_func:
1253  * @tree_column: A #GtkTreeViewColumn
1254  * @cell_renderer: A #GtkCellRenderer
1255  * @func: The #GtkTreeViewColumnFunc to use. 
1256  * @func_data: The user data for @func.
1257  * @destroy: The destroy notification for @func_data
1258  * 
1259  * Sets the #GtkTreeViewColumnFunc to use for the column.  This
1260  * function is used instead of the standard attributes mapping for
1261  * setting the column value, and should set the value of @tree_column's
1262  * cell renderer as appropriate.  @func may be NULL to remove an
1263  * older one.
1264  **/
1265 void
1266 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn   *tree_column,
1267                                          GtkCellRenderer     *cell_renderer,
1268                                          GtkTreeCellDataFunc  func,
1269                                          gpointer             func_data,
1270                                          GtkDestroyNotify     destroy)
1271 {
1272   GtkTreeViewColumnCellInfo *info;
1273
1274   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1275   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1276   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1277
1278   g_return_if_fail (info != NULL);
1279
1280   if (func == info->func &&
1281       func_data == info->func_data &&
1282       destroy == info->destroy)
1283     return;
1284
1285   if (info->func_data && info->destroy)
1286     (info->destroy) (info->func_data);
1287
1288   info->func = func;
1289   info->func_data = func_data;
1290   info->destroy = destroy;
1291
1292   if (tree_column->tree_view)
1293     gtk_tree_view_column_cell_set_dirty (tree_column);
1294 }
1295
1296
1297 /**
1298  * gtk_tree_view_column_clear_attributes:
1299  * @tree_column: a #GtkTreeViewColumn
1300  *@cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1301  * 
1302  * Clears all existing attributes previously set with
1303  * gtk_tree_view_column_set_attributes().
1304  **/
1305 void
1306 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1307                                        GtkCellRenderer   *cell_renderer)
1308 {
1309   GtkTreeViewColumnCellInfo *info;
1310   GSList *list;
1311
1312   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1313   g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1314   info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1315
1316   list = info->attributes;
1317
1318   while (list && list->next)
1319     {
1320       g_free (list->data);
1321       list = list->next->next;
1322     }
1323   g_slist_free (info->attributes);
1324   info->attributes = NULL;
1325
1326   if (tree_column->tree_view)
1327     gtk_tree_view_column_cell_set_dirty (tree_column);
1328 }
1329
1330
1331 /**
1332  * gtk_tree_view_column_set_spacing:
1333  * @tree_column: A #GtkTreeViewColumn.
1334  * @spacing: distance between cell renderers in pixels.
1335  * 
1336  * Sets the spacing field of @tree_column, which is the number of pixels to
1337  * place between cell renderers packed into it.
1338  **/
1339 void
1340 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1341                                   gint               spacing)
1342 {
1343   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1344   g_return_if_fail (spacing >= 0);
1345
1346   if (tree_column->spacing == spacing)
1347     return;
1348
1349   tree_column->spacing = spacing;
1350   if (tree_column->tree_view)
1351     gtk_tree_view_column_cell_set_dirty (tree_column);
1352 }
1353
1354 /**
1355  * gtk_tree_view_column_get_spacing:
1356  * @tree_column: A #GtkTreeViewColumn.
1357  * 
1358  * Returns the spacing of @tree_column.
1359  **/
1360 gint
1361 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1362 {
1363   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1364
1365   return tree_column->spacing;
1366 }
1367
1368 /* Options for manipulating the columns */
1369
1370 /**
1371  * gtk_tree_view_column_set_visible:
1372  * @tree_column: A #GtkTreeViewColumn.
1373  * @visible: TRUE if the @tree_column is visible.
1374  * 
1375  * Sets the visibility of @tree_column.
1376  **/
1377 void
1378 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1379                                   gboolean           visible)
1380 {
1381   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1382
1383   visible = !! visible;
1384   
1385   if (tree_column->visible == visible)
1386     return;
1387
1388   tree_column->visible = visible;
1389
1390   gtk_tree_view_column_update_button (tree_column);
1391   g_object_notify (G_OBJECT (tree_column), "visible");
1392 }
1393
1394 /**
1395  * gtk_tree_view_column_get_visible:
1396  * @tree_column: A #GtkTreeViewColumn.
1397  * 
1398  * Returns TRUE if @tree_column is visible.
1399  * 
1400  * Return value: whether the column is visible or not.  If it is visible, then
1401  * the tree will show the column.
1402  **/
1403 gboolean
1404 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1405 {
1406   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1407
1408   return tree_column->visible;
1409 }
1410
1411 /**
1412  * gtk_tree_view_column_set_sizing:
1413  * @tree_column: A #GtkTreeViewColumn.
1414  * @type: The #GtkTreeViewColumnSizing.
1415  * 
1416  * Sets the growth behavior of @tree_column to @type.
1417  **/
1418 void
1419 gtk_tree_view_column_set_sizing (GtkTreeViewColumn       *tree_column,
1420                                  GtkTreeViewColumnSizing  type)
1421 {
1422   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1423
1424   if (type == tree_column->column_type)
1425     return;
1426
1427   if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1428       tree_column->requested_width != -1)
1429     {
1430       gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1431     }
1432   tree_column->column_type = type;
1433
1434   gtk_tree_view_column_update_button (tree_column);
1435
1436   if (type != GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1437   g_object_notify (G_OBJECT (tree_column), "sizing");
1438 }
1439
1440 /**
1441  * gtk_tree_view_column_get_sizing:
1442  * @tree_column: A #GtkTreeViewColumn.
1443  * 
1444  * Returns the current type of @tree_column.
1445  * 
1446  * Return value: The type of @tree_column.
1447  **/
1448 GtkTreeViewColumnSizing
1449 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1450 {
1451   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1452
1453   return tree_column->column_type;
1454 }
1455
1456 /**
1457  * gtk_tree_view_column_get_width:
1458  * @tree_column: A #GtkTreeViewColumn.
1459  * 
1460  * Returns the current size of the @tree_column in pixels.
1461  * 
1462  * Return value: The current width of the @tree_column.
1463  **/
1464 gint
1465 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1466 {
1467   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1468
1469   return tree_column->width;
1470 }
1471
1472 /**
1473  * gtk_tree_view_column_set_fixed_width:
1474  * @tree_column: A #GtkTreeViewColumn.
1475  * @fixed_width: The size to set the @tree_column to. Must be greater than 0.
1476  * 
1477  * Sets the size of the column in pixels.  This is meaningful only if the sizing
1478  * type is #GTK_TREE_VIEW_COLUMN_FIXED.  In this case, the value is discarded
1479  * as the size of the column is based on the calculated width of the column. The
1480  * width is clamped to the min/max width for the column.
1481  **/
1482 void
1483 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1484                                       gint               fixed_width)
1485 {
1486   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1487   g_return_if_fail (fixed_width > 0);
1488
1489   if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1490     return;
1491
1492   tree_column->fixed_width = fixed_width;
1493   tree_column->requested_width = fixed_width;
1494   _gtk_tree_view_column_set_width (tree_column, fixed_width);
1495 }
1496
1497 /**
1498  * gtk_tree_view_column_get_fixed_width:
1499  * @tree_column: a #GtkTreeViewColumn
1500  * 
1501  * Gets the fixed width of the column.  This value is only meaning may not be the
1502  * actual width of the column on the screen, just what is requested.
1503  * 
1504  * Return value: the fixed width of the column
1505  **/
1506 gint
1507 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1508 {
1509   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1510
1511   return tree_column->fixed_width;
1512 }
1513
1514 /**
1515  * gtk_tree_view_column_set_min_width:
1516  * @tree_column: A #GtkTreeViewColumn.
1517  * @min_width: The minimum width of the column in pixels, or -1.
1518  * 
1519  * Sets the minimum width of the @tree_column.  If @min_width is -1, then the
1520  * minimum width is unset.
1521  **/
1522 void
1523 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1524                                     gint               min_width)
1525 {
1526   gint real_min_width;
1527
1528   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1529   g_return_if_fail (min_width >= -1);
1530
1531   if (min_width == tree_column->min_width)
1532     return;
1533
1534   if (tree_column->tree_view == NULL)
1535     {
1536       tree_column->min_width = min_width;
1537       return;
1538     }
1539
1540   real_min_width = (tree_column->min_width == -1) ?
1541     tree_column->button->requisition.width : tree_column->min_width;
1542
1543   /* We want to queue a resize if the either the old min_size or the
1544    * new min_size determined the size of the column */
1545   if (GTK_WIDGET_REALIZED (tree_column->tree_view))
1546     {
1547       if ((tree_column->min_width > tree_column->width) ||
1548           (tree_column->min_width == -1 &&
1549            tree_column->button->requisition.width > tree_column->width) ||
1550           (min_width > tree_column->width) ||
1551           (min_width == -1 &&
1552            tree_column->button->requisition.width > tree_column->width))
1553         gtk_widget_queue_resize (tree_column->tree_view);
1554     }
1555
1556   if (tree_column->max_width != -1 && tree_column->max_width < real_min_width)
1557     tree_column->max_width = real_min_width;
1558
1559   tree_column->min_width = min_width;
1560
1561   g_object_notify (G_OBJECT (tree_column), "min_width");
1562 }
1563
1564 /**
1565  * gtk_tree_view_column_get_min_width:
1566  * @tree_column: A #GtkTreeViewColumn.
1567  * 
1568  * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
1569  * width is set.
1570  * 
1571  * Return value: The minimum width of the @tree_column.
1572  **/
1573 gint
1574 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
1575 {
1576   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1577
1578   return tree_column->min_width;
1579 }
1580
1581 /**
1582  * gtk_tree_view_column_set_max_width:
1583  * @tree_column: A #GtkTreeViewColumn.
1584  * @max_width: The maximum width of the column in pixels, or -1.
1585  * 
1586  * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
1587  * maximum width is unset.  Note, the column can actually be wider than max
1588  * width if it's the last column in a view.  In this case, the column expands to
1589  * fill the view.
1590  **/
1591 void
1592 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
1593                                     gint               max_width)
1594 {
1595   gint real_max_width;
1596
1597   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1598   g_return_if_fail (max_width >= -1);
1599
1600   if (max_width == tree_column->max_width)
1601     return;
1602
1603   if (tree_column->tree_view == NULL)
1604     {
1605       tree_column->max_width = max_width;
1606       return;
1607     }
1608
1609   real_max_width = tree_column->max_width == -1 ?
1610     tree_column->button->requisition.width : tree_column->max_width;
1611
1612   if (tree_column->tree_view &&
1613       GTK_WIDGET_REALIZED (tree_column->tree_view) &&
1614       ((tree_column->max_width < tree_column->width) ||
1615        (max_width != -1 && max_width < tree_column->width)))
1616     gtk_widget_queue_resize (tree_column->tree_view);
1617
1618   tree_column->max_width = max_width;
1619
1620   if (real_max_width > max_width)
1621     tree_column->max_width = max_width;
1622
1623   g_object_notify (G_OBJECT (tree_column), "max_width");
1624 }
1625
1626 /**
1627  * gtk_tree_view_column_get_max_width:
1628  * @tree_column: A #GtkTreeViewColumn.
1629  * 
1630  * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
1631  * width is set.
1632  * 
1633  * Return value: The maximum width of the @tree_column.
1634  **/
1635 gint
1636 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
1637 {
1638   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1639
1640   return tree_column->max_width;
1641 }
1642
1643 /**
1644  * gtk_tree_view_column_clicked:
1645  * @tree_column: a #GtkTreeViewColumn
1646  * 
1647  * Emits the "clicked" signal on the column.  This function will only work if
1648  * the user could have conceivably clicked on the button.
1649  **/
1650 void
1651 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
1652 {
1653   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1654
1655   if (tree_column->visible &&
1656       tree_column->button &&
1657       tree_column->clickable)
1658     gtk_button_clicked (GTK_BUTTON (tree_column->button));
1659 }
1660
1661 /**
1662  * gtk_tree_view_column_set_title:
1663  * @tree_column: A #GtkTreeViewColumn.
1664  * @title: The title of the @tree_column.
1665  * 
1666  * Sets the title of the @tree_column.  If a custom widget has been set, then
1667  * this value is ignored.
1668  **/
1669 void
1670 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
1671                                 const gchar       *title)
1672 {
1673   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1674
1675   g_free (tree_column->title);
1676   if (title)
1677     tree_column->title = g_strdup (title);
1678   else
1679     tree_column->title = NULL;
1680
1681   gtk_tree_view_column_update_button (tree_column);
1682   g_object_notify (G_OBJECT (tree_column), "title");
1683 }
1684
1685 /**
1686  * gtk_tree_view_column_get_title:
1687  * @tree_column: A #GtkTreeViewColumn.
1688  * 
1689  * Returns the title of the widget.  This value should not be modified.
1690  * 
1691  * Return value: the title of the column.
1692  **/
1693 G_CONST_RETURN gchar *
1694 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
1695 {
1696   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1697
1698   return tree_column->title;
1699 }
1700
1701 /**
1702  * gtk_tree_view_column_set_clickable:
1703  * @tree_column: A #GtkTreeViewColumn.
1704  * @clickable: TRUE if the header is active.
1705  * 
1706  * Sets the header to be active if @active is TRUE.  When the header is active,
1707  * then it can take keyboard focus, and can be clicked.
1708  **/
1709 void
1710 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
1711                                     gboolean           clickable)
1712 {
1713   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1714
1715   if (tree_column->clickable == (clickable?TRUE:FALSE))
1716     return;
1717
1718   tree_column->clickable = (clickable?TRUE:FALSE);
1719   gtk_tree_view_column_update_button (tree_column);
1720   g_object_notify (G_OBJECT (tree_column), "clickable");
1721 }
1722
1723 /**
1724  * gtk_tree_view_column_get_clickable:
1725  * @tree_column: a #GtkTreeViewColumn
1726  * 
1727  * Returns %TRUE if the user can click on the header for the column.
1728  * 
1729  * Return value: whether the user can click the column header
1730  **/
1731 gboolean
1732 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1733 {
1734   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1735
1736   return tree_column->clickable;
1737 }
1738
1739 /**
1740  * gtk_tree_view_column_set_widget:
1741  * @tree_column: A #GtkTreeViewColumn.
1742  * @widget: A child #GtkWidget, or NULL.
1743  * 
1744  * Sets the widget in the header to be @widget.  If widget is NULL, then the
1745  * header button is set with a #GtkLabel set to the title of @tree_column.
1746  **/
1747 void
1748 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1749                                  GtkWidget         *widget)
1750 {
1751   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1752   g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1753
1754   if (widget)
1755     {
1756       gtk_object_ref (GTK_OBJECT (widget));
1757       gtk_object_sink (GTK_OBJECT (widget));
1758     }
1759
1760   if (tree_column->child)      
1761     gtk_object_unref (GTK_OBJECT (tree_column->child));
1762
1763   tree_column->child = widget;
1764   gtk_tree_view_column_update_button (tree_column);
1765   g_object_notify (G_OBJECT (tree_column), "widget");
1766 }
1767
1768 /**
1769  * gtk_tree_view_column_get_widget:
1770  * @tree_column: A #GtkTreeViewColumn.
1771  * 
1772  * Returns the #GtkWidget in the button in the column header.  If a custom
1773  * widget has not been set, then this will be a #GtkAlignment with a #GtkLabel
1774  * in it.
1775  * 
1776  * Return value: The #GtkWidget in the column header.
1777  **/
1778 GtkWidget *
1779 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1780 {
1781   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1782
1783   return tree_column->child;
1784 }
1785
1786 /**
1787  * gtk_tree_view_column_set_alignment:
1788  * @tree_column: A #GtkTreeViewColumn.
1789  * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
1790  * 
1791  * Sets the alignment of the title or custom widget inside the column header.
1792  * The alignment determines its location inside the button -- 0.0 for left, 0.5
1793  * for center, 1.0 for right.
1794  **/
1795 void
1796 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
1797                                     gfloat             xalign)
1798 {
1799   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1800
1801   xalign = CLAMP (xalign, 0.0, 1.0);
1802
1803   if (tree_column->xalign == xalign)
1804     return;
1805
1806   tree_column->xalign = xalign;
1807   gtk_tree_view_column_update_button (tree_column);
1808   g_object_notify (G_OBJECT (tree_column), "alignment");
1809 }
1810
1811 /**
1812  * gtk_tree_view_column_get_alignment:
1813  * @tree_column: A #GtkTreeViewColumn.
1814  * 
1815  * Returns the current x alignment of @tree_column.  This value can range
1816  * between 0.0 and 1.0.
1817  * 
1818  * Return value: The current alignent of @tree_column.
1819  **/
1820 gfloat
1821 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
1822 {
1823   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
1824
1825   return tree_column->xalign;
1826 }
1827
1828 void
1829 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
1830                                       gboolean           reorderable)
1831 {
1832   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1833
1834   /*  if (reorderable)
1835       gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
1836
1837   if (tree_column->reorderable == (reorderable?TRUE:FALSE))
1838     return;
1839
1840   tree_column->reorderable = (reorderable?TRUE:FALSE);
1841   gtk_tree_view_column_update_button (tree_column);
1842   g_object_notify (G_OBJECT (tree_column), "reorderable");
1843 }
1844
1845 gboolean
1846 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
1847 {
1848   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1849
1850   return tree_column->reorderable;
1851 }
1852
1853
1854 /**
1855  * gtk_tree_view_column_set_sort_column_id:
1856  * @tree_column: a #GtkTreeViewColumn
1857  * @sort_column_id: The sort_column_id of the model to sort on.
1858  * 
1859  * Sets the logical sort_column_id that this column sorts on when this column is
1860  * selected for sorting.  Doing so makes the column header clickable.
1861  **/
1862 void
1863 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
1864                                          gint               sort_column_id)
1865 {
1866   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1867   g_return_if_fail (sort_column_id >= 0);
1868
1869   if (tree_column->sort_column_id == sort_column_id)
1870     return;
1871
1872   tree_column->sort_column_id = sort_column_id;
1873
1874   /* Handle unsetting the id */
1875   if (sort_column_id == -1)
1876     {
1877       if (tree_column->sort_clicked_signal)
1878         {
1879           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal);
1880           tree_column->sort_clicked_signal = 0;
1881         }
1882
1883       if (tree_column->sort_column_changed_signal)
1884         {
1885           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_column_changed_signal);
1886           tree_column->sort_column_changed_signal = 0;
1887         }
1888
1889       gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
1890       gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1891       return;
1892     }
1893
1894   gtk_tree_view_column_set_clickable (tree_column, TRUE);
1895
1896   if (! tree_column->sort_clicked_signal)
1897     tree_column->sort_clicked_signal = g_signal_connect (G_OBJECT (tree_column),
1898                                                          "clicked",
1899                                                          G_CALLBACK (gtk_tree_view_column_sort),
1900                                                          NULL);
1901
1902   gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
1903 }
1904
1905 /**
1906  * gtk_tree_view_column_get_sort_column_id:
1907  * @tree_column: a #GtkTreeViewColumn
1908  *
1909  * Gets the logical sort_column_id that the model sorts on when this
1910  * coumn is selected for sorting. See gtk_tree_view_column_set_sort_column_id().
1911  *
1912  * Return value: the current sort_column_id for this column, or -1 if
1913  *               this column can't be used for sorting.
1914  **/
1915 gint
1916 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
1917 {
1918   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1919
1920   return tree_column->sort_column_id;
1921 }
1922
1923 /**
1924  * gtk_tree_view_column_set_sort_indicator:
1925  * @tree_column: a #GtkTreeViewColumn
1926  * @setting: %TRUE to display an indicator that the column is sorted
1927  *
1928  * Call this function with a @setting of %TRUE to display an arrow in
1929  * the header button indicating the column is sorted. Call
1930  * gtk_tree_view_column_set_sort_order() to change the direction of
1931  * the arrow.
1932  * 
1933  **/
1934 void
1935 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn     *tree_column,
1936                                          gboolean               setting)
1937 {
1938   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1939
1940   setting = setting != FALSE;
1941
1942   if (setting == tree_column->show_sort_indicator)
1943     return;
1944
1945   tree_column->show_sort_indicator = setting;
1946   gtk_tree_view_column_update_button (tree_column);
1947   g_object_notify (G_OBJECT (tree_column), "sort_indicator");
1948 }
1949
1950 /**
1951  * gtk_tree_view_column_get_sort_indicator:
1952  * @tree_column: a #GtkTreeViewColumn
1953  * 
1954  * Gets the value set by gtk_tree_view_column_set_sort_indicator().
1955  * 
1956  * Return value: whether the sort indicator arrow is displayed
1957  **/
1958 gboolean
1959 gtk_tree_view_column_get_sort_indicator  (GtkTreeViewColumn     *tree_column)
1960 {
1961   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1962
1963   return tree_column->show_sort_indicator;
1964 }
1965
1966 /**
1967  * gtk_tree_view_column_set_sort_order:
1968  * @tree_column: a #GtkTreeViewColumn
1969  * @order: sort order that the sort indicator should indicate
1970  *
1971  * Changes the appearance of the sort indicator. 
1972  * 
1973  * This <emphasis>does not</emphasis> actually sort the model.  Use
1974  * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
1975  * support.  This function is primarily for custom sorting behavior, and should
1976  * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
1977  * that. For custom models, the mechanism will vary. 
1978  * 
1979  * The sort indicator changes direction to indicate normal sort or reverse sort.
1980  * Note that you must have the sort indicator enabled to see anything when 
1981  * calling this function; see gtk_tree_view_column_set_sort_indicator().
1982  **/
1983 void
1984 gtk_tree_view_column_set_sort_order      (GtkTreeViewColumn     *tree_column,
1985                                           GtkSortType            order)
1986 {
1987   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1988
1989   if (order == tree_column->sort_order)
1990     return;
1991
1992   tree_column->sort_order = order;
1993   gtk_tree_view_column_update_button (tree_column);
1994   g_object_notify (G_OBJECT (tree_column), "sort_order");
1995 }
1996
1997 /**
1998  * gtk_tree_view_column_get_sort_order:
1999  * @tree_column: a #GtkTreeViewColumn
2000  * 
2001  * Gets the value set by gtk_tree_view_column_set_sort_order().
2002  * 
2003  * Return value: the sort order the sort indicator is indicating
2004  **/
2005 GtkSortType
2006 gtk_tree_view_column_get_sort_order      (GtkTreeViewColumn     *tree_column)
2007 {
2008   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2009
2010   return tree_column->sort_order;
2011 }
2012
2013 /**
2014  * gtk_tree_view_column_cell_set_cell_data:
2015  * @tree_column: A #GtkTreeViewColumn.
2016  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2017  * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2018  * @is_expander: TRUE, if the row has children
2019  * @is_expanded: TRUE, if the row has visible children
2020  * 
2021  * Sets the cell renderer based on the @tree_model and @tree_node.  That is, for
2022  * every attribute mapping in @tree_column, it will get a value from the set
2023  * column on the @tree_node, and use that value to set the attribute on the cell
2024  * renderer.  This is used primarily by the GtkTreeView.
2025  **/
2026 void
2027 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2028                                          GtkTreeModel      *tree_model,
2029                                          GtkTreeIter       *iter,
2030                                          gboolean           is_expander,
2031                                          gboolean           is_expanded)
2032 {
2033   GSList *list;
2034   GValue value = { 0, };
2035   GList *cell_list;
2036
2037   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2038   g_return_if_fail (tree_column->cell_list != NULL);
2039
2040   if (tree_model == NULL)
2041     return;
2042
2043   for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2044     {
2045       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2046       GObject *cell = (GObject *) info->cell;
2047
2048       list = info->attributes;
2049
2050       g_object_freeze_notify (cell);
2051       g_object_set (cell, "is_expander", is_expander, "is_expanded", is_expanded, NULL);
2052
2053       while (list && list->next)
2054         {
2055           gtk_tree_model_get_value (tree_model, iter,
2056                                     GPOINTER_TO_INT (list->next->data),
2057                                     &value);
2058           g_object_set_property (cell, (gchar *) list->data, &value);
2059           g_value_unset (&value);
2060           list = list->next->next;
2061         }
2062
2063       if (info->func)
2064         (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2065       g_object_thaw_notify (G_OBJECT (info->cell));
2066     }
2067
2068 }
2069
2070 /**
2071  * gtk_tree_view_column_cell_get_size:
2072  * @tree_column: A #GtkTreeViewColumn.
2073  * @cell_area: The area a the column will be allocated, or %NULL
2074  * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
2075  * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
2076  * @width: location to return width needed to render a cell, or %NULL
2077  * @height: location to return height needed to render a cell, or %NULL
2078  * 
2079  * Obtains the width and height needed to render the column.  This is used
2080  * primarily by the GtkTreeView.
2081  **/
2082 void
2083 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2084                                     GdkRectangle      *cell_area,
2085                                     gint              *x_offset,
2086                                     gint              *y_offset,
2087                                     gint              *width,
2088                                     gint              *height)
2089 {
2090   GList *list;
2091   gboolean first_cell = TRUE;
2092
2093   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2094
2095   if (height)
2096     * height = 0;
2097   if (width)
2098     * width = 0;
2099
2100   for (list = tree_column->cell_list; list; list = list->next)
2101     {
2102       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2103       gboolean visible;
2104       gint new_height = 0;
2105       gint new_width = 0;
2106       g_object_get (info->cell, "visible", &visible, NULL);
2107
2108       if (visible == FALSE)
2109         continue;
2110
2111       if (first_cell == FALSE && *width)
2112         *width += tree_column->spacing;
2113
2114       gtk_cell_renderer_get_size (info->cell,
2115                                   tree_column->tree_view,
2116                                   cell_area,
2117                                   x_offset,
2118                                   y_offset,
2119                                   &new_width,
2120                                   &new_height);
2121
2122       if (height)
2123         * height = MAX (*height, new_height);
2124       info->requested_width = MAX (info->requested_width, new_width);
2125       if (width)
2126         * width += info->requested_width;
2127       first_cell = TRUE;
2128     }
2129 }
2130
2131 /* both rendering and rendering focus are somewhat complicated, and a bit of
2132  * code.  Rather than duplicate them, we put them together to keep the code in
2133  * one place
2134  */
2135 static void
2136 gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
2137                                            GdkWindow         *window,
2138                                            GdkRectangle      *background_area,
2139                                            GdkRectangle      *cell_area,
2140                                            GdkRectangle      *expose_area,
2141                                            guint              flags,
2142                                            gboolean           render,
2143                                            GdkRectangle      *focus_rectangle)
2144 {
2145   GList *list;
2146   GdkRectangle real_cell_area;
2147   gint expand_cell_count = 0;
2148   gint full_requested_width = 0;
2149   gint extra_space;
2150   gint min_x, min_y, max_x, max_y;
2151
2152   min_x = G_MAXINT;
2153   min_y = G_MAXINT;
2154   max_x = 0;
2155   max_y = 0;
2156
2157   real_cell_area = *cell_area;
2158
2159   /* Find out how my extra space we have to allocate */
2160   for (list = tree_column->cell_list; list; list = list->next)
2161     {
2162       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2163       gboolean visible;
2164
2165       g_object_get (info->cell, "visible", &visible, NULL);
2166       if (visible == FALSE)
2167         continue;
2168
2169       if (info->expand == TRUE)
2170         expand_cell_count ++;
2171       full_requested_width += info->requested_width;
2172     }
2173
2174   extra_space = cell_area->width - full_requested_width;
2175   if (extra_space < 0)
2176     extra_space = 0;
2177
2178   for (list = tree_column->cell_list; list; list = list->next)
2179     {
2180       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2181       gboolean visible;
2182
2183       if (info->pack == GTK_PACK_END)
2184         continue;
2185
2186       g_object_get (info->cell, "visible", &visible, NULL);
2187       if (visible == FALSE)
2188         continue;
2189
2190       real_cell_area.width = info->requested_width +
2191         (info->expand?extra_space:0);
2192       if (render)
2193         {
2194           gtk_cell_renderer_render (info->cell,
2195                                     window,
2196                                     tree_column->tree_view,
2197                                     background_area,
2198                                     &real_cell_area,
2199                                     expose_area,
2200                                     flags);
2201         }
2202       else
2203         {
2204           gint x_offset, y_offset, width, height;
2205
2206           gtk_cell_renderer_get_size (info->cell,
2207                                       tree_column->tree_view,
2208                                       &real_cell_area,
2209                                       &x_offset, &y_offset,
2210                                       &width, &height);
2211
2212           if (min_x > (real_cell_area.x + x_offset))
2213             min_x = real_cell_area.x + x_offset;
2214           if (max_x < real_cell_area.x + x_offset + width)
2215             max_x = real_cell_area.x + x_offset + width;
2216           if (min_y > (real_cell_area.y + y_offset))
2217             min_y = real_cell_area.y + y_offset;
2218           if (max_y < real_cell_area.y + y_offset + height)
2219             max_y = real_cell_area.y + y_offset + height;
2220         }
2221       real_cell_area.x += (info->requested_width + tree_column->spacing);
2222     }
2223   for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2224     {
2225       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2226       gboolean visible;
2227
2228       if (info->pack == GTK_PACK_START)
2229         continue;
2230
2231       g_object_get (info->cell, "visible", &visible, NULL);
2232       if (visible == FALSE)
2233         continue;
2234
2235       real_cell_area.width = info->requested_width +
2236         (info->expand?extra_space:0);
2237       gtk_cell_renderer_render (info->cell,
2238                                 window,
2239                                 tree_column->tree_view,
2240                                 background_area,
2241                                 &real_cell_area,
2242                                 expose_area,
2243                                 flags);
2244       real_cell_area.x += (info->requested_width + tree_column->spacing);
2245     }
2246   if (! render)
2247     {
2248       if (min_x >= max_x || min_y >= max_y)
2249         {
2250           *focus_rectangle = *cell_area;
2251           focus_rectangle->x -= 1;
2252           focus_rectangle->y -= 1;
2253           focus_rectangle->width += 2;
2254           focus_rectangle->height += 2;
2255         }
2256       else
2257         {
2258           focus_rectangle->x = min_x - 1;
2259           focus_rectangle->y = min_y - 1;
2260           focus_rectangle->width = (max_x - min_x) + 2;
2261           focus_rectangle->height = (max_y - min_y) + 2;
2262         }
2263     }
2264 }
2265
2266 /**
2267  * gtk_tree_view_column_cell_render:
2268  * @tree_column: A #GtkTreeViewColumn.
2269  * @window: a #GdkDrawable to draw to
2270  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2271  * @cell_area: area normally rendered by a cell renderer
2272  * @expose_area: area that actually needs updating
2273  * @flags: flags that affect rendering
2274  * 
2275  * Renders the cell contained by #tree_column. This is used primarily by the
2276  * GtkTreeView.
2277  **/
2278 void
2279 gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
2280                                   GdkWindow         *window,
2281                                   GdkRectangle      *background_area,
2282                                   GdkRectangle      *cell_area,
2283                                   GdkRectangle      *expose_area,
2284                                   guint              flags)
2285 {
2286   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2287   g_return_if_fail (background_area != NULL);
2288   g_return_if_fail (cell_area != NULL);
2289   g_return_if_fail (expose_area != NULL);
2290
2291   gtk_tree_view_column_cell_render_or_focus (tree_column,
2292                                              window,
2293                                              background_area,
2294                                              cell_area,
2295                                              expose_area,
2296                                              flags,
2297                                              TRUE,
2298                                              NULL);
2299 }
2300
2301 gboolean
2302 _gtk_tree_view_column_cell_event (GtkTreeViewColumn  *tree_column,
2303                                   GtkCellEditable   **editable_widget,
2304                                   GdkEvent           *event,
2305                                   gchar              *path_string,
2306                                   GdkRectangle       *background_area,
2307                                   GdkRectangle       *cell_area,
2308                                   guint               flags)
2309 {
2310   gboolean visible, mode;
2311
2312   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2313
2314   g_object_get (G_OBJECT (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell),
2315                 "visible", &visible,
2316                 "mode", &mode,
2317                 NULL);
2318   if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2319     {
2320       if (gtk_cell_renderer_activate (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2321                                       event,
2322                                       tree_column->tree_view,
2323                                       path_string,
2324                                       background_area,
2325                                       cell_area,
2326                                       flags))
2327         return TRUE;
2328     }
2329   else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2330     {
2331       *editable_widget = gtk_cell_renderer_start_editing (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2332                                                           event,
2333                                                           tree_column->tree_view,
2334                                                           path_string,
2335                                                           background_area,
2336                                                           cell_area,
2337                                                           flags);
2338
2339       if (*editable_widget != NULL)
2340         {
2341           g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2342
2343           return TRUE;
2344         }
2345     }
2346   return FALSE;
2347 }
2348
2349
2350 gboolean
2351 gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
2352                                  gint               direction)
2353 {
2354   if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
2355     return FALSE;
2356   return TRUE;
2357 }
2358
2359 void
2360 gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn       *tree_column,
2361                                       GdkWindow               *window,
2362                                       GdkRectangle            *background_area,
2363                                       GdkRectangle            *cell_area,
2364                                       GdkRectangle            *expose_area,
2365                                       guint                    flags)
2366 {
2367   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2368   if (tree_column->editable_widget)
2369     {
2370       /* This function is only called on the editable row when editing.
2371        */
2372
2373       gtk_paint_focus (tree_column->tree_view->style,
2374                        window,
2375                        NULL,
2376                        tree_column->tree_view,
2377                        "treeview",
2378                        cell_area->x - 1,
2379                        cell_area->y - 1,
2380                        cell_area->width + 2 - 1,
2381                        cell_area->height + 2 - 1);
2382       
2383     }
2384   else
2385     {
2386       GdkRectangle focus_rectangle;
2387       gtk_tree_view_column_cell_render_or_focus (tree_column,
2388                                                  window,
2389                                                  background_area,
2390                                                  cell_area,
2391                                                  expose_area,
2392                                                  flags,
2393                                                  FALSE,
2394                                                  &focus_rectangle);
2395       
2396       gtk_paint_focus (tree_column->tree_view->style,
2397                        window,
2398                        NULL,
2399                        tree_column->tree_view,
2400                        "treeview",
2401                        focus_rectangle.x,
2402                        focus_rectangle.y,
2403                        focus_rectangle.width - 1,
2404                        focus_rectangle.height - 1);
2405     }
2406 }
2407
2408 gboolean
2409 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2410 {
2411   GList *list;
2412
2413   for (list = tree_column->cell_list; list; list = list->next)
2414     {
2415       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2416       gboolean visible;
2417
2418       g_object_get (G_OBJECT (info->cell), "visible", &visible, NULL);
2419
2420       if (visible)
2421         return TRUE;
2422     }
2423
2424   return FALSE;
2425 }
2426
2427 void
2428 gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column)
2429 {
2430   GList *list;
2431
2432   for (list = tree_column->cell_list; list; list = list->next)
2433     {
2434       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2435
2436       info->requested_width = 0;
2437     }
2438   tree_column->dirty = TRUE;
2439
2440   if (tree_column->tree_view)
2441     gtk_widget_queue_resize (tree_column->tree_view);
2442 }
2443
2444 void
2445 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
2446                                      GtkCellEditable   *cell_editable)
2447 {
2448   g_return_if_fail (tree_column->editable_widget == NULL);
2449
2450   tree_column->editable_widget = cell_editable;
2451 }
2452
2453 void
2454 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
2455 {
2456   g_return_if_fail (tree_column->editable_widget != NULL);
2457
2458   tree_column->editable_widget = NULL;
2459 }