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