]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeviewcolumn.c
add _gtk_tree_view_column_get_editable_cell and
[~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
1716 /**
1717  * gtk_tree_view_column_get_min_width:
1718  * @tree_column: A #GtkTreeViewColumn.
1719  * 
1720  * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
1721  * width is set.
1722  * 
1723  * Return value: The minimum width of the @tree_column.
1724  **/
1725 gint
1726 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
1727 {
1728   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1729
1730   return tree_column->min_width;
1731 }
1732
1733 /**
1734  * gtk_tree_view_column_set_max_width:
1735  * @tree_column: A #GtkTreeViewColumn.
1736  * @max_width: The maximum width of the column in pixels, or -1.
1737  * 
1738  * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
1739  * maximum width is unset.  Note, the column can actually be wider than max
1740  * width if it's the last column in a view.  In this case, the column expands to
1741  * fill any extra space.
1742  **/
1743 void
1744 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
1745                                     gint               max_width)
1746 {
1747   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1748   g_return_if_fail (max_width >= -1);
1749
1750   if (max_width == tree_column->max_width)
1751     return;
1752
1753   if (tree_column->visible &&
1754       tree_column->tree_view != NULL &&
1755       GTK_WIDGET_REALIZED (tree_column->tree_view))
1756     {
1757       if (max_width != -1 && max_width < tree_column->width)
1758         gtk_widget_queue_resize (tree_column->tree_view);
1759     }
1760
1761   tree_column->max_width = max_width;
1762   g_object_freeze_notify (G_OBJECT (tree_column));
1763   if (max_width != -1 && max_width < tree_column->min_width)
1764     {
1765       tree_column->min_width = max_width;
1766       g_object_notify (G_OBJECT (tree_column), "min_width");
1767     }
1768   g_object_notify (G_OBJECT (tree_column), "max_width");
1769   g_object_thaw_notify (G_OBJECT (tree_column));
1770 }
1771
1772 /**
1773  * gtk_tree_view_column_get_max_width:
1774  * @tree_column: A #GtkTreeViewColumn.
1775  * 
1776  * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
1777  * width is set.
1778  * 
1779  * Return value: The maximum width of the @tree_column.
1780  **/
1781 gint
1782 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
1783 {
1784   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1785
1786   return tree_column->max_width;
1787 }
1788
1789 /**
1790  * gtk_tree_view_column_clicked:
1791  * @tree_column: a #GtkTreeViewColumn
1792  * 
1793  * Emits the "clicked" signal on the column.  This function will only work if
1794  * @tree_column is clickable.
1795  **/
1796 void
1797 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
1798 {
1799   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1800
1801   if (tree_column->visible &&
1802       tree_column->button &&
1803       tree_column->clickable)
1804     gtk_button_clicked (GTK_BUTTON (tree_column->button));
1805 }
1806
1807 /**
1808  * gtk_tree_view_column_set_title:
1809  * @tree_column: A #GtkTreeViewColumn.
1810  * @title: The title of the @tree_column.
1811  * 
1812  * Sets the title of the @tree_column.  If a custom widget has been set, then
1813  * this value is ignored.
1814  **/
1815 void
1816 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
1817                                 const gchar       *title)
1818 {
1819   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1820
1821   g_free (tree_column->title);
1822   if (title)
1823     tree_column->title = g_strdup (title);
1824   else
1825     tree_column->title = NULL;
1826
1827   gtk_tree_view_column_update_button (tree_column);
1828   g_object_notify (G_OBJECT (tree_column), "title");
1829 }
1830
1831 /**
1832  * gtk_tree_view_column_get_title:
1833  * @tree_column: A #GtkTreeViewColumn.
1834  * 
1835  * Returns the title of the widget.  This value should not be modified.
1836  * 
1837  * Return value: the title of the column.
1838  **/
1839 G_CONST_RETURN gchar *
1840 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
1841 {
1842   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1843
1844   return tree_column->title;
1845 }
1846
1847 /**
1848  * gtk_tree_view_column_set_clickable:
1849  * @tree_column: A #GtkTreeViewColumn.
1850  * @clickable: %TRUE if the header is active.
1851  * 
1852  * Sets the header to be active if @active is %TRUE.  When the header is active,
1853  * then it can take keyboard focus, and can be clicked.
1854  **/
1855 void
1856 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
1857                                     gboolean           clickable)
1858 {
1859   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1860
1861   clickable = !! clickable;
1862   if (tree_column->clickable == clickable)
1863     return;
1864
1865   tree_column->clickable = clickable;
1866   gtk_tree_view_column_update_button (tree_column);
1867   g_object_notify (G_OBJECT (tree_column), "clickable");
1868 }
1869
1870 /**
1871  * gtk_tree_view_column_get_clickable:
1872  * @tree_column: a #GtkTreeViewColumn
1873  * 
1874  * Returns %TRUE if the user can click on the header for the column.
1875  * 
1876  * Return value: %TRUE if user can click the column header.
1877  **/
1878 gboolean
1879 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1880 {
1881   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1882
1883   return tree_column->clickable;
1884 }
1885
1886 /**
1887  * gtk_tree_view_column_set_widget:
1888  * @tree_column: A #GtkTreeViewColumn.
1889  * @widget: A child #GtkWidget, or %NULL.
1890  * 
1891  * Sets the widget in the header to be @widget.  If widget is %NULL, then the
1892  * header button is set with a #GtkLabel set to the title of @tree_column.
1893  **/
1894 void
1895 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1896                                  GtkWidget         *widget)
1897 {
1898   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1899   g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1900
1901   if (widget)
1902     {
1903       gtk_object_ref (GTK_OBJECT (widget));
1904       gtk_object_sink (GTK_OBJECT (widget));
1905     }
1906
1907   if (tree_column->child)      
1908     gtk_object_unref (GTK_OBJECT (tree_column->child));
1909
1910   tree_column->child = widget;
1911   gtk_tree_view_column_update_button (tree_column);
1912   g_object_notify (G_OBJECT (tree_column), "widget");
1913 }
1914
1915 /**
1916  * gtk_tree_view_column_get_widget:
1917  * @tree_column: A #GtkTreeViewColumn.
1918  * 
1919  * Returns the #GtkWidget in the button on the column header.  If a custom
1920  * widget has not been set then %NULL is returned.
1921  * 
1922  * Return value: The #GtkWidget in the column header, or %NULL
1923  **/
1924 GtkWidget *
1925 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1926 {
1927   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1928
1929   return tree_column->child;
1930 }
1931
1932 /**
1933  * gtk_tree_view_column_set_alignment:
1934  * @tree_column: A #GtkTreeViewColumn.
1935  * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
1936  * 
1937  * Sets the alignment of the title or custom widget inside the column header.
1938  * The alignment determines its location inside the button -- 0.0 for left, 0.5
1939  * for center, 1.0 for right.
1940  **/
1941 void
1942 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
1943                                     gfloat             xalign)
1944 {
1945   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1946
1947   xalign = CLAMP (xalign, 0.0, 1.0);
1948
1949   if (tree_column->xalign == xalign)
1950     return;
1951
1952   tree_column->xalign = xalign;
1953   gtk_tree_view_column_update_button (tree_column);
1954   g_object_notify (G_OBJECT (tree_column), "alignment");
1955 }
1956
1957 /**
1958  * gtk_tree_view_column_get_alignment:
1959  * @tree_column: A #GtkTreeViewColumn.
1960  * 
1961  * Returns the current x alignment of @tree_column.  This value can range
1962  * between 0.0 and 1.0.
1963  * 
1964  * Return value: The current alignent of @tree_column.
1965  **/
1966 gfloat
1967 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
1968 {
1969   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
1970
1971   return tree_column->xalign;
1972 }
1973
1974 /**
1975  * gtk_tree_view_column_set_reorderable:
1976  * @tree_column: A #GtkTreeViewColumn
1977  * @reorderable: #TRUE, if the column can be reordered.
1978  * 
1979  * If @reorderable is #TRUE, then the column can be reordered by the end user
1980  * dragging the header.
1981  **/
1982 void
1983 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
1984                                       gboolean           reorderable)
1985 {
1986   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1987
1988   /*  if (reorderable)
1989       gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
1990
1991   if (tree_column->reorderable == (reorderable?TRUE:FALSE))
1992     return;
1993
1994   tree_column->reorderable = (reorderable?TRUE:FALSE);
1995   gtk_tree_view_column_update_button (tree_column);
1996   g_object_notify (G_OBJECT (tree_column), "reorderable");
1997 }
1998
1999 /**
2000  * gtk_tree_view_column_get_reorderable:
2001  * @tree_column: A #GtkTreeViewColumn
2002  * 
2003  * Returns #TRUE if the @tree_column can be reordered by the user.
2004  * 
2005  * Return value: #TRUE if the @tree_column can be reordered by the user.
2006  **/
2007 gboolean
2008 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
2009 {
2010   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2011
2012   return tree_column->reorderable;
2013 }
2014
2015
2016 /**
2017  * gtk_tree_view_column_set_sort_column_id:
2018  * @tree_column: a #GtkTreeViewColumn
2019  * @sort_column_id: The @sort_column_id of the model to sort on.
2020  * 
2021  * Sets the logical @sort_column_id that this column sorts on when this column 
2022  * is selected for sorting.  Doing so makes the column header clickable.
2023  **/
2024 void
2025 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
2026                                          gint               sort_column_id)
2027 {
2028   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2029   g_return_if_fail (sort_column_id >= 0);
2030
2031   if (tree_column->sort_column_id == sort_column_id)
2032     return;
2033
2034   tree_column->sort_column_id = sort_column_id;
2035
2036   /* Handle unsetting the id */
2037   if (sort_column_id == -1)
2038     {
2039       if (tree_column->sort_clicked_signal)
2040         {
2041           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal);
2042           tree_column->sort_clicked_signal = 0;
2043         }
2044
2045       if (tree_column->sort_column_changed_signal)
2046         {
2047           g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_column_changed_signal);
2048           tree_column->sort_column_changed_signal = 0;
2049         }
2050
2051       gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2052       gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
2053       return;
2054     }
2055
2056   gtk_tree_view_column_set_clickable (tree_column, TRUE);
2057
2058   if (! tree_column->sort_clicked_signal)
2059     tree_column->sort_clicked_signal = g_signal_connect (G_OBJECT (tree_column),
2060                                                          "clicked",
2061                                                          G_CALLBACK (gtk_tree_view_column_sort),
2062                                                          NULL);
2063
2064   gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
2065 }
2066
2067 /**
2068  * gtk_tree_view_column_get_sort_column_id:
2069  * @tree_column: a #GtkTreeViewColumn
2070  *
2071  * Gets the logical @sort_column_id that the model sorts on when this
2072  * column is selected for sorting. See gtk_tree_view_column_set_sort_column_id().
2073  *
2074  * Return value: the current @sort_column_id for this column, or -1 if
2075  *               this column can't be used for sorting.
2076  **/
2077 gint
2078 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
2079 {
2080   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2081
2082   return tree_column->sort_column_id;
2083 }
2084
2085 /**
2086  * gtk_tree_view_column_set_sort_indicator:
2087  * @tree_column: a #GtkTreeViewColumn
2088  * @setting: %TRUE to display an indicator that the column is sorted
2089  *
2090  * Call this function with a @setting of %TRUE to display an arrow in
2091  * the header button indicating the column is sorted. Call
2092  * gtk_tree_view_column_set_sort_order() to change the direction of
2093  * the arrow.
2094  * 
2095  **/
2096 void
2097 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn     *tree_column,
2098                                          gboolean               setting)
2099 {
2100   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2101
2102   setting = setting != FALSE;
2103
2104   if (setting == tree_column->show_sort_indicator)
2105     return;
2106
2107   tree_column->show_sort_indicator = setting;
2108   gtk_tree_view_column_update_button (tree_column);
2109   g_object_notify (G_OBJECT (tree_column), "sort_indicator");
2110 }
2111
2112 /**
2113  * gtk_tree_view_column_get_sort_indicator:
2114  * @tree_column: a #GtkTreeViewColumn
2115  * 
2116  * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2117  * 
2118  * Return value: whether the sort indicator arrow is displayed
2119  **/
2120 gboolean
2121 gtk_tree_view_column_get_sort_indicator  (GtkTreeViewColumn     *tree_column)
2122 {
2123   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2124
2125   return tree_column->show_sort_indicator;
2126 }
2127
2128 /**
2129  * gtk_tree_view_column_set_sort_order:
2130  * @tree_column: a #GtkTreeViewColumn
2131  * @order: sort order that the sort indicator should indicate
2132  *
2133  * Changes the appearance of the sort indicator. 
2134  * 
2135  * This <emphasis>does not</emphasis> actually sort the model.  Use
2136  * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2137  * support.  This function is primarily for custom sorting behavior, and should
2138  * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2139  * that. For custom models, the mechanism will vary. 
2140  * 
2141  * The sort indicator changes direction to indicate normal sort or reverse sort.
2142  * Note that you must have the sort indicator enabled to see anything when 
2143  * calling this function; see gtk_tree_view_column_set_sort_indicator().
2144  **/
2145 void
2146 gtk_tree_view_column_set_sort_order      (GtkTreeViewColumn     *tree_column,
2147                                           GtkSortType            order)
2148 {
2149   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2150
2151   if (order == tree_column->sort_order)
2152     return;
2153
2154   tree_column->sort_order = order;
2155   gtk_tree_view_column_update_button (tree_column);
2156   g_object_notify (G_OBJECT (tree_column), "sort_order");
2157 }
2158
2159 /**
2160  * gtk_tree_view_column_get_sort_order:
2161  * @tree_column: a #GtkTreeViewColumn
2162  * 
2163  * Gets the value set by gtk_tree_view_column_set_sort_order().
2164  * 
2165  * Return value: the sort order the sort indicator is indicating
2166  **/
2167 GtkSortType
2168 gtk_tree_view_column_get_sort_order      (GtkTreeViewColumn     *tree_column)
2169 {
2170   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2171
2172   return tree_column->sort_order;
2173 }
2174
2175 /**
2176  * gtk_tree_view_column_cell_set_cell_data:
2177  * @tree_column: A #GtkTreeViewColumn.
2178  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2179  * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2180  * @is_expander: %TRUE, if the row has children
2181  * @is_expanded: %TRUE, if the row has visible children
2182  * 
2183  * Sets the cell renderer based on the @tree_model and @tree_node.  That is, for
2184  * every attribute mapping in @tree_column, it will get a value from the set
2185  * column on the @tree_node, and use that value to set the attribute on the cell
2186  * renderer.  This is used primarily by the #GtkTreeView.
2187  **/
2188 void
2189 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2190                                          GtkTreeModel      *tree_model,
2191                                          GtkTreeIter       *iter,
2192                                          gboolean           is_expander,
2193                                          gboolean           is_expanded)
2194 {
2195   GSList *list;
2196   GValue value = { 0, };
2197   GList *cell_list;
2198
2199   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2200   g_return_if_fail (tree_column->cell_list != NULL);
2201
2202   if (tree_model == NULL)
2203     return;
2204
2205   for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2206     {
2207       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2208       GObject *cell = (GObject *) info->cell;
2209
2210       list = info->attributes;
2211
2212       g_object_freeze_notify (cell);
2213       g_object_set (cell, "is_expander", is_expander, "is_expanded", is_expanded, NULL);
2214
2215       while (list && list->next)
2216         {
2217           gtk_tree_model_get_value (tree_model, iter,
2218                                     GPOINTER_TO_INT (list->next->data),
2219                                     &value);
2220           g_object_set_property (cell, (gchar *) list->data, &value);
2221           g_value_unset (&value);
2222           list = list->next->next;
2223         }
2224
2225       if (info->func)
2226         (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2227       g_object_thaw_notify (G_OBJECT (info->cell));
2228     }
2229
2230 }
2231
2232 /**
2233  * gtk_tree_view_column_cell_get_size:
2234  * @tree_column: A #GtkTreeViewColumn.
2235  * @cell_area: The area a the column will be allocated, or %NULL
2236  * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
2237  * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
2238  * @width: location to return width needed to render a cell, or %NULL
2239  * @height: location to return height needed to render a cell, or %NULL
2240  * 
2241  * Obtains the width and height needed to render the column.  This is used
2242  * primarily by the #GtkTreeView.
2243  **/
2244 void
2245 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2246                                     GdkRectangle      *cell_area,
2247                                     gint              *x_offset,
2248                                     gint              *y_offset,
2249                                     gint              *width,
2250                                     gint              *height)
2251 {
2252   GList *list;
2253   gboolean first_cell = TRUE;
2254   gint focus_line_width;
2255
2256   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2257
2258   if (height)
2259     * height = 0;
2260   if (width)
2261     * width = 0;
2262
2263   gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
2264   
2265   for (list = tree_column->cell_list; list; list = list->next)
2266     {
2267       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2268       gboolean visible;
2269       gint new_height = 0;
2270       gint new_width = 0;
2271       g_object_get (info->cell, "visible", &visible, NULL);
2272
2273       if (visible == FALSE)
2274         continue;
2275
2276       if (first_cell == FALSE && *width)
2277         *width += tree_column->spacing;
2278
2279       gtk_cell_renderer_get_size (info->cell,
2280                                   tree_column->tree_view,
2281                                   cell_area,
2282                                   x_offset,
2283                                   y_offset,
2284                                   &new_width,
2285                                   &new_height);
2286
2287       if (height)
2288         * height = MAX (*height, new_height + focus_line_width * 2);
2289       info->requested_width = MAX (info->requested_width, new_width + focus_line_width * 2);
2290       if (width)
2291         * width += info->requested_width;
2292       first_cell = FALSE;
2293     }
2294 }
2295
2296 /* both rendering and rendering focus are somewhat complicated, and a bit of
2297  * code.  Rather than duplicate them, we put them together to keep the code in
2298  * one place
2299  */
2300 enum {
2301   CELL_ACTION_RENDER,
2302   CELL_ACTION_FOCUS,
2303   CELL_ACTION_EVENT
2304 };
2305
2306 static gboolean
2307 gtk_tree_view_column_cell_process_action (GtkTreeViewColumn  *tree_column,
2308                                           GdkWindow          *window,
2309                                           GdkRectangle       *background_area,
2310                                           GdkRectangle       *cell_area,
2311                                           guint               flags,
2312                                           gint                action,
2313                                           GdkRectangle       *expose_area,     /* RENDER */
2314                                           GdkRectangle       *focus_rectangle, /* FOCUS  */
2315                                           GtkCellEditable   **editable_widget, /* EVENT  */
2316                                           GdkEvent           *event,           /* EVENT  */
2317                                           gchar              *path_string)     /* EVENT  */
2318 {
2319   GList *list;
2320   GdkRectangle real_cell_area;
2321   gint expand_cell_count = 0;
2322   gint full_requested_width = 0;
2323   gint extra_space;
2324   gint min_x, min_y, max_x, max_y;
2325   gint focus_line_width;
2326
2327   min_x = G_MAXINT;
2328   min_y = G_MAXINT;
2329   max_x = 0;
2330   max_y = 0;
2331
2332   real_cell_area = *cell_area;
2333
2334   gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
2335                         "focus-line-width", &focus_line_width,
2336                         NULL);
2337   /* Find out how my extra space we have to allocate */
2338   for (list = tree_column->cell_list; list; list = list->next)
2339     {
2340       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2341
2342       if (! info->cell->visible)
2343         continue;
2344
2345       if (info->expand == TRUE)
2346         expand_cell_count ++;
2347       full_requested_width += info->requested_width;
2348     }
2349
2350   extra_space = cell_area->width - full_requested_width;
2351   if (extra_space < 0)
2352     extra_space = 0;
2353
2354   for (list = tree_column->cell_list; list; list = list->next)
2355     {
2356       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2357
2358       if (info->pack == GTK_PACK_END)
2359         continue;
2360
2361       if (! info->cell->visible)
2362         continue;
2363
2364       real_cell_area.width = info->requested_width +
2365         (info->expand?extra_space:0);
2366       info->real_width = real_cell_area.width;
2367       real_cell_area.x += focus_line_width;
2368       if (action == CELL_ACTION_RENDER)
2369         {
2370           gtk_cell_renderer_render (info->cell,
2371                                     window,
2372                                     tree_column->tree_view,
2373                                     background_area,
2374                                     &real_cell_area,
2375                                     expose_area,
2376                                     flags);
2377         }
2378       else if (action == CELL_ACTION_FOCUS)
2379         {
2380           gint x_offset, y_offset, width, height;
2381
2382           gtk_cell_renderer_get_size (info->cell,
2383                                       tree_column->tree_view,
2384                                       &real_cell_area,
2385                                       &x_offset, &y_offset,
2386                                       &width, &height);
2387
2388           if (min_x > (real_cell_area.x + x_offset))
2389             min_x = real_cell_area.x + x_offset;
2390           if (max_x < real_cell_area.x + x_offset + width)
2391             max_x = real_cell_area.x + x_offset + width;
2392           if (min_y > (real_cell_area.y + y_offset))
2393             min_y = real_cell_area.y + y_offset;
2394           if (max_y < real_cell_area.y + y_offset + height)
2395             max_y = real_cell_area.y + y_offset + height;
2396         }
2397       else if (action == CELL_ACTION_EVENT)
2398         {
2399           gboolean try_event = FALSE;
2400
2401           if (event)
2402             {
2403               if (real_cell_area.x <= ((GdkEventButton *)event)->x &&
2404                   real_cell_area.x + real_cell_area.width > ((GdkEventButton *)event)->x)
2405                 try_event = TRUE;
2406             }
2407           else /* if (info->has_focus)*/
2408             /* FIXME 73676: allow focusing individual cells */
2409             {
2410               try_event = TRUE;
2411             }
2412           if (try_event)
2413             {
2414               gboolean visible, mode;
2415
2416               g_object_get (G_OBJECT (info->cell),
2417                             "visible", &visible,
2418                             "mode", &mode,
2419                             NULL);
2420               if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2421                 {
2422                   if (gtk_cell_renderer_activate (info->cell,
2423                                                   event,
2424                                                   tree_column->tree_view,
2425                                                   path_string,
2426                                                   background_area,
2427                                                   cell_area,
2428                                                   flags))
2429                     return TRUE;
2430                 }
2431               else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2432                 {
2433                   *editable_widget =
2434                     gtk_cell_renderer_start_editing (info->cell,
2435                                                      event,
2436                                                      tree_column->tree_view,
2437                                                      path_string,
2438                                                      background_area,
2439                                                      cell_area,
2440                                                      flags);
2441
2442                   if (*editable_widget != NULL)
2443                     {
2444                       g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2445                       
2446                       return TRUE;
2447                     }
2448                 }
2449             }
2450         }
2451       real_cell_area.x += (info->requested_width + tree_column->spacing);
2452     }
2453   for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2454     {
2455       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2456
2457       if (info->pack == GTK_PACK_START)
2458         continue;
2459
2460       if (! info->cell->visible)
2461         continue;
2462
2463       real_cell_area.width = info->requested_width +
2464         (info->expand?extra_space:0);
2465       info->real_width = real_cell_area.width;
2466       if (action == CELL_ACTION_RENDER)
2467         {
2468           gtk_cell_renderer_render (info->cell,
2469                                     window,
2470                                     tree_column->tree_view,
2471                                     background_area,
2472                                     &real_cell_area,
2473                                     expose_area,
2474                                     flags);
2475         }
2476       else if (action == CELL_ACTION_FOCUS)
2477         {
2478           gint x_offset, y_offset, width, height;
2479
2480           gtk_cell_renderer_get_size (info->cell,
2481                                       tree_column->tree_view,
2482                                       &real_cell_area,
2483                                       &x_offset, &y_offset,
2484                                       &width, &height);
2485
2486           if (min_x > (real_cell_area.x + x_offset))
2487             min_x = real_cell_area.x + x_offset;
2488           if (max_x < real_cell_area.x + x_offset + width)
2489             max_x = real_cell_area.x + x_offset + width;
2490           if (min_y > (real_cell_area.y + y_offset))
2491             min_y = real_cell_area.y + y_offset;
2492           if (max_y < real_cell_area.y + y_offset + height)
2493             max_y = real_cell_area.y + y_offset + height;
2494         }
2495       real_cell_area.x += (info->requested_width + tree_column->spacing);
2496     }
2497
2498   if (action == CELL_ACTION_FOCUS)
2499     {
2500       if (min_x >= max_x || min_y >= max_y)
2501         {
2502           *focus_rectangle = *cell_area;
2503           /* don't change the focus_rectangle, just draw it nicely inside
2504            * the cell area */
2505         }
2506       else
2507         {
2508           focus_rectangle->x = min_x - focus_line_width;
2509           focus_rectangle->y = min_y - focus_line_width;
2510           focus_rectangle->width = (max_x - min_x) + 2 * focus_line_width;
2511           focus_rectangle->height = (max_y - min_y) + 2 * focus_line_width;
2512         }
2513     }
2514
2515   return FALSE;
2516 }
2517
2518 /**
2519  * gtk_tree_view_column_cell_render:
2520  * @tree_column: A #GtkTreeViewColumn.
2521  * @window: a #GdkDrawable to draw to
2522  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2523  * @cell_area: area normally rendered by a cell renderer
2524  * @expose_area: area that actually needs updating
2525  * @flags: flags that affect rendering
2526  * 
2527  * Renders the cell contained by #tree_column. This is used primarily by the
2528  * #GtkTreeView.
2529  **/
2530 void
2531 _gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
2532                                    GdkWindow         *window,
2533                                    GdkRectangle      *background_area,
2534                                    GdkRectangle      *cell_area,
2535                                    GdkRectangle      *expose_area,
2536                                    guint              flags)
2537 {
2538   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2539   g_return_if_fail (background_area != NULL);
2540   g_return_if_fail (cell_area != NULL);
2541   g_return_if_fail (expose_area != NULL);
2542
2543   gtk_tree_view_column_cell_process_action (tree_column,
2544                                             window,
2545                                             background_area,
2546                                             cell_area,
2547                                             flags,
2548                                             CELL_ACTION_RENDER,
2549                                             expose_area,
2550                                             NULL, NULL, NULL, NULL);
2551 }
2552
2553 gboolean
2554 _gtk_tree_view_column_cell_event (GtkTreeViewColumn  *tree_column,
2555                                   GtkCellEditable   **editable_widget,
2556                                   GdkEvent           *event,
2557                                   gchar              *path_string,
2558                                   GdkRectangle       *background_area,
2559                                   GdkRectangle       *cell_area,
2560                                   guint               flags)
2561 {
2562   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2563
2564   return gtk_tree_view_column_cell_process_action (tree_column,
2565                                                    NULL,
2566                                                    background_area,
2567                                                    cell_area,
2568                                                    flags,
2569                                                    CELL_ACTION_EVENT,
2570                                                    NULL, NULL,
2571                                                    editable_widget,
2572                                                    event,
2573                                                    path_string);
2574 }
2575
2576
2577 gboolean
2578 _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
2579                                   gint               direction)
2580 {
2581   /* FIXME 73676: allow focusing individual cells */
2582   if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
2583     return FALSE;
2584   return TRUE;
2585 }
2586
2587 void
2588 _gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn       *tree_column,
2589                                        GdkWindow               *window,
2590                                        GdkRectangle            *background_area,
2591                                        GdkRectangle            *cell_area,
2592                                        GdkRectangle            *expose_area,
2593                                        guint                    flags)
2594 {
2595   gint focus_line_width;
2596   GtkStateType cell_state;
2597   
2598   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2599   gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
2600                         "focus-line-width", &focus_line_width, NULL);
2601   if (tree_column->editable_widget)
2602     {
2603       /* This function is only called on the editable row when editing.
2604        */
2605 #if 0
2606       gtk_paint_focus (tree_column->tree_view->style,
2607                        window,
2608                        GTK_WIDGET_STATE (tree_column->tree_view),
2609                        NULL,
2610                        tree_column->tree_view,
2611                        "treeview",
2612                        cell_area->x - focus_line_width,
2613                        cell_area->y - focus_line_width,
2614                        cell_area->width + 2 * focus_line_width,
2615                        cell_area->height + 2 * focus_line_width);
2616 #endif      
2617     }
2618   else
2619     {
2620       GdkRectangle focus_rectangle;
2621       gtk_tree_view_column_cell_process_action (tree_column,
2622                                                 window,
2623                                                 background_area,
2624                                                 cell_area,
2625                                                 flags,
2626                                                 CELL_ACTION_FOCUS,
2627                                                 expose_area,
2628                                                 &focus_rectangle,
2629                                                 NULL, NULL, NULL);
2630
2631       cell_state = flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
2632               (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
2633               (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL));
2634       gtk_paint_focus (tree_column->tree_view->style,
2635                        window,
2636                        cell_state,
2637                        NULL,
2638                        tree_column->tree_view,
2639                        "treeview",
2640                        focus_rectangle.x,
2641                        focus_rectangle.y,
2642                        focus_rectangle.width,
2643                        focus_rectangle.height);
2644     }
2645 }
2646
2647 /**
2648  * gtk_tree_view_column_cell_is_visible:
2649  * @tree_column: A #GtkTreeViewColumn
2650  * 
2651  * Returns #TRUE if any of the cells packed into the @tree_column are visible.
2652  * For this to be meaningful, you must first initialize the cells with
2653  * gtk_tree_view_column_cell_set_cell_data()
2654  * 
2655  * Return value: #TRUE, if any of the cells packed into the @tree_column are currently visible
2656  **/
2657 gboolean
2658 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2659 {
2660   GList *list;
2661
2662   for (list = tree_column->cell_list; list; list = list->next)
2663     {
2664       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2665
2666       if (info->cell->visible)
2667         return TRUE;
2668     }
2669
2670   return FALSE;
2671 }
2672
2673 void
2674 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
2675                                       gboolean           install_handler)
2676 {
2677   GList *list;
2678
2679   for (list = tree_column->cell_list; list; list = list->next)
2680     {
2681       GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2682
2683       info->requested_width = 0;
2684     }
2685   tree_column->dirty = TRUE;
2686   tree_column->resized_width = MAX (tree_column->requested_width, tree_column->button_request);
2687   tree_column->requested_width = -1;
2688   tree_column->width = 0;
2689
2690   if (tree_column->tree_view &&
2691       GTK_WIDGET_REALIZED (tree_column->tree_view))
2692     {
2693       if (install_handler)
2694         _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (tree_column->tree_view));
2695       else
2696         GTK_TREE_VIEW (tree_column->tree_view)->priv->mark_rows_col_dirty = TRUE;
2697       gtk_widget_queue_resize (tree_column->tree_view);
2698     }
2699 }
2700
2701 void
2702 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
2703                                      GtkCellEditable   *cell_editable)
2704 {
2705   g_return_if_fail (tree_column->editable_widget == NULL);
2706
2707   tree_column->editable_widget = cell_editable;
2708 }
2709
2710 void
2711 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
2712 {
2713   g_return_if_fail (tree_column->editable_widget != NULL);
2714
2715   tree_column->editable_widget = NULL;
2716 }
2717
2718 void
2719 _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
2720                                           GtkCellRenderer   *cell,
2721                                           gint              *left,
2722                                           gint              *right)
2723 {
2724   GList *list;
2725
2726   if (left)
2727     {
2728       *left = 0;
2729
2730       for (list = column->cell_list; list; list = list->next)
2731         {
2732           GtkTreeViewColumnCellInfo *info =
2733             (GtkTreeViewColumnCellInfo *)list->data;
2734
2735           if (info->cell == cell)
2736             break;
2737
2738           *left += info->real_width;
2739         }
2740     }
2741
2742   if (right)
2743     {
2744       *right = 0;
2745
2746       for (list = column->cell_list; list; list = list->next)
2747         {
2748           GtkTreeViewColumnCellInfo *info =
2749             (GtkTreeViewColumnCellInfo *)list->data;
2750
2751           if (info->cell == cell)
2752             break;
2753         }
2754
2755       /* skip cell */
2756       if (list && list->next)
2757         {
2758           list = list->next;
2759           for ( ; list; list = list->next)
2760             {
2761               GtkTreeViewColumnCellInfo *info =
2762                 (GtkTreeViewColumnCellInfo *)list->data;
2763
2764               *right += info->real_width;
2765             }
2766         }
2767     }
2768 }