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