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