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