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