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