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