]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeviewcolumn.c
Bandaid fix for icon view subclassing
[~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   _gtk_tree_view_reset_header_styles (GTK_TREE_VIEW (priv->tree_view));
1915
1916   gtk_tree_view_column_update_button (tree_column);
1917   g_object_notify (G_OBJECT (tree_column), "visible");
1918 }
1919
1920 /**
1921  * gtk_tree_view_column_get_visible:
1922  * @tree_column: A #GtkTreeViewColumn.
1923  * 
1924  * Returns %TRUE if @tree_column is visible.
1925  * 
1926  * Return value: whether the column is visible or not.  If it is visible, then
1927  * the tree will show the column.
1928  **/
1929 gboolean
1930 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1931 {
1932   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1933
1934   return tree_column->priv->visible;
1935 }
1936
1937 /**
1938  * gtk_tree_view_column_set_resizable:
1939  * @tree_column: A #GtkTreeViewColumn
1940  * @resizable: %TRUE, if the column can be resized
1941  * 
1942  * If @resizable is %TRUE, then the user can explicitly resize the column by
1943  * grabbing the outer edge of the column button.  If resizable is %TRUE and
1944  * sizing mode of the column is #GTK_TREE_VIEW_COLUMN_AUTOSIZE, then the sizing
1945  * mode is changed to #GTK_TREE_VIEW_COLUMN_GROW_ONLY.
1946  **/
1947 void
1948 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1949                                     gboolean           resizable)
1950 {
1951   GtkTreeViewColumnPrivate *priv;
1952
1953   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1954
1955   priv      = tree_column->priv;
1956   resizable = !! resizable;
1957
1958   if (priv->resizable == resizable)
1959     return;
1960
1961   priv->resizable = resizable;
1962
1963   if (resizable && priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1964     gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1965
1966   gtk_tree_view_column_update_button (tree_column);
1967
1968   g_object_notify (G_OBJECT (tree_column), "resizable");
1969 }
1970
1971 /**
1972  * gtk_tree_view_column_get_resizable:
1973  * @tree_column: A #GtkTreeViewColumn
1974  * 
1975  * Returns %TRUE if the @tree_column can be resized by the end user.
1976  * 
1977  * Return value: %TRUE, if the @tree_column can be resized.
1978  **/
1979 gboolean
1980 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1981 {
1982   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1983
1984   return tree_column->priv->resizable;
1985 }
1986
1987
1988 /**
1989  * gtk_tree_view_column_set_sizing:
1990  * @tree_column: A #GtkTreeViewColumn.
1991  * @type: The #GtkTreeViewColumnSizing.
1992  * 
1993  * Sets the growth behavior of @tree_column to @type.
1994  **/
1995 void
1996 gtk_tree_view_column_set_sizing (GtkTreeViewColumn       *tree_column,
1997                                  GtkTreeViewColumnSizing  type)
1998 {
1999   GtkTreeViewColumnPrivate *priv;
2000
2001   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2002
2003   priv      = tree_column->priv;
2004
2005   if (type == priv->column_type)
2006     return;
2007
2008   if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2009     gtk_tree_view_column_set_resizable (tree_column, FALSE);
2010
2011   priv->column_type = type;
2012
2013   gtk_tree_view_column_update_button (tree_column);
2014
2015   g_object_notify (G_OBJECT (tree_column), "sizing");
2016 }
2017
2018 /**
2019  * gtk_tree_view_column_get_sizing:
2020  * @tree_column: A #GtkTreeViewColumn.
2021  * 
2022  * Returns the current type of @tree_column.
2023  * 
2024  * Return value: The type of @tree_column.
2025  **/
2026 GtkTreeViewColumnSizing
2027 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
2028 {
2029   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2030
2031   return tree_column->priv->column_type;
2032 }
2033
2034 /**
2035  * gtk_tree_view_column_get_width:
2036  * @tree_column: A #GtkTreeViewColumn.
2037  * 
2038  * Returns the current size of @tree_column in pixels.
2039  * 
2040  * Return value: The current width of @tree_column.
2041  **/
2042 gint
2043 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
2044 {
2045   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2046
2047   return tree_column->priv->width;
2048 }
2049
2050 gint
2051 _gtk_tree_view_column_request_width (GtkTreeViewColumn *tree_column)
2052 {
2053   GtkTreeViewColumnPrivate *priv;
2054   gint real_requested_width;
2055
2056   priv = tree_column->priv;
2057
2058   if (priv->use_resized_width)
2059     {
2060       real_requested_width = priv->resized_width;
2061     }
2062   else if (priv->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2063     {
2064       real_requested_width = priv->fixed_width;
2065     }
2066   else if (gtk_tree_view_get_headers_visible (GTK_TREE_VIEW (priv->tree_view)))
2067     {
2068       gint button_request;
2069       gint requested_width;
2070
2071       gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL);
2072       requested_width += priv->padding;
2073
2074       gtk_widget_get_preferred_width (priv->button, &button_request, NULL);
2075       real_requested_width = MAX (requested_width, button_request);
2076     }
2077   else
2078     {
2079       gint requested_width;
2080
2081       gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &requested_width, NULL);
2082       requested_width += priv->padding;
2083
2084       real_requested_width = requested_width;
2085       if (real_requested_width < 0)
2086         real_requested_width = 0;
2087     }
2088
2089   if (priv->min_width != -1)
2090     real_requested_width = MAX (real_requested_width, priv->min_width);
2091
2092   if (priv->max_width != -1)
2093     real_requested_width = MIN (real_requested_width, priv->max_width);
2094
2095   return real_requested_width;
2096 }
2097
2098 void
2099 _gtk_tree_view_column_allocate (GtkTreeViewColumn *tree_column,
2100                                 int                x_offset,
2101                                 int                width)
2102 {
2103   GtkTreeViewColumnPrivate *priv;
2104   GtkAllocation             allocation;
2105   gboolean                  rtl;
2106
2107   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2108
2109   priv = tree_column->priv;
2110
2111   priv->width = width;
2112
2113   gtk_cell_area_context_allocate (priv->cell_area_context, priv->width - priv->padding, -1);
2114
2115   allocation.x      = x_offset;
2116   allocation.y      = 0;
2117   allocation.width  = width;
2118   allocation.height = _gtk_tree_view_get_header_height (GTK_TREE_VIEW (priv->tree_view));
2119
2120   gtk_widget_size_allocate (priv->button, &allocation);
2121
2122   if (priv->window)
2123     {
2124       rtl = (gtk_widget_get_direction (priv->tree_view) == GTK_TEXT_DIR_RTL);
2125       gdk_window_move_resize (priv->window,
2126                               allocation.x + (rtl ? 0 : allocation.width) - TREE_VIEW_DRAG_WIDTH/2,
2127                               allocation.y,
2128                               TREE_VIEW_DRAG_WIDTH, allocation.height);
2129     }
2130
2131   g_object_notify (G_OBJECT (tree_column), "width");
2132 }
2133
2134 /**
2135  * gtk_tree_view_column_set_fixed_width:
2136  * @tree_column: A #GtkTreeViewColumn.
2137  * @fixed_width: The size to set @tree_column to. Must be greater than 0.
2138  * 
2139  * Sets the size of the column in pixels.  This is meaningful only if the sizing
2140  * type is #GTK_TREE_VIEW_COLUMN_FIXED.  The size of the column is clamped to
2141  * the min/max width for the column.  Please note that the min/max width of the
2142  * column doesn't actually affect the "fixed_width" property of the widget, just
2143  * the actual size when displayed.
2144  **/
2145 void
2146 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
2147                                       gint               fixed_width)
2148 {
2149   GtkTreeViewColumnPrivate *priv;
2150
2151   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2152   g_return_if_fail (fixed_width > 0);
2153
2154   priv = tree_column->priv;
2155
2156   priv->fixed_width = fixed_width;
2157   priv->use_resized_width = FALSE;
2158
2159   if (priv->tree_view &&
2160       gtk_widget_get_realized (priv->tree_view) &&
2161       priv->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
2162     {
2163       gtk_widget_queue_resize (priv->tree_view);
2164     }
2165
2166   g_object_notify (G_OBJECT (tree_column), "fixed-width");
2167 }
2168
2169 /**
2170  * gtk_tree_view_column_get_fixed_width:
2171  * @tree_column: a #GtkTreeViewColumn
2172  * 
2173  * Gets the fixed width of the column.  This value is only meaning may not be
2174  * the actual width of the column on the screen, just what is requested.
2175  * 
2176  * Return value: the fixed width of the column
2177  **/
2178 gint
2179 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
2180 {
2181   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2182
2183   return tree_column->priv->fixed_width;
2184 }
2185
2186 /**
2187  * gtk_tree_view_column_set_min_width:
2188  * @tree_column: A #GtkTreeViewColumn.
2189  * @min_width: The minimum width of the column in pixels, or -1.
2190  * 
2191  * Sets the minimum width of the @tree_column.  If @min_width is -1, then the
2192  * minimum width is unset.
2193  **/
2194 void
2195 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
2196                                     gint               min_width)
2197 {
2198   GtkTreeViewColumnPrivate *priv;
2199
2200   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2201   g_return_if_fail (min_width >= -1);
2202
2203   priv = tree_column->priv;
2204
2205   if (min_width == priv->min_width)
2206     return;
2207
2208   if (priv->visible &&
2209       priv->tree_view != NULL &&
2210       gtk_widget_get_realized (priv->tree_view))
2211     {
2212       if (min_width > priv->width)
2213         gtk_widget_queue_resize (priv->tree_view);
2214     }
2215
2216   priv->min_width = min_width;
2217   g_object_freeze_notify (G_OBJECT (tree_column));
2218   if (priv->max_width != -1 && priv->max_width < min_width)
2219     {
2220       priv->max_width = min_width;
2221       g_object_notify (G_OBJECT (tree_column), "max-width");
2222     }
2223   g_object_notify (G_OBJECT (tree_column), "min-width");
2224   g_object_thaw_notify (G_OBJECT (tree_column));
2225
2226   if (priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2227     _gtk_tree_view_column_autosize (GTK_TREE_VIEW (priv->tree_view),
2228                                     tree_column);
2229 }
2230
2231 /**
2232  * gtk_tree_view_column_get_min_width:
2233  * @tree_column: A #GtkTreeViewColumn.
2234  * 
2235  * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
2236  * width is set.
2237  * 
2238  * Return value: The minimum width of the @tree_column.
2239  **/
2240 gint
2241 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
2242 {
2243   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2244
2245   return tree_column->priv->min_width;
2246 }
2247
2248 /**
2249  * gtk_tree_view_column_set_max_width:
2250  * @tree_column: A #GtkTreeViewColumn.
2251  * @max_width: The maximum width of the column in pixels, or -1.
2252  * 
2253  * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
2254  * maximum width is unset.  Note, the column can actually be wider than max
2255  * width if it's the last column in a view.  In this case, the column expands to
2256  * fill any extra space.
2257  **/
2258 void
2259 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
2260                                     gint               max_width)
2261 {
2262   GtkTreeViewColumnPrivate *priv;
2263
2264   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2265   g_return_if_fail (max_width >= -1);
2266
2267   priv = tree_column->priv;
2268
2269   if (max_width == priv->max_width)
2270     return;
2271
2272   if (priv->visible &&
2273       priv->tree_view != NULL &&
2274       gtk_widget_get_realized (priv->tree_view))
2275     {
2276       if (max_width != -1 && max_width < priv->width)
2277         gtk_widget_queue_resize (priv->tree_view);
2278     }
2279
2280   priv->max_width = max_width;
2281   g_object_freeze_notify (G_OBJECT (tree_column));
2282   if (max_width != -1 && max_width < priv->min_width)
2283     {
2284       priv->min_width = max_width;
2285       g_object_notify (G_OBJECT (tree_column), "min-width");
2286     }
2287   g_object_notify (G_OBJECT (tree_column), "max-width");
2288   g_object_thaw_notify (G_OBJECT (tree_column));
2289
2290   if (priv->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2291     _gtk_tree_view_column_autosize (GTK_TREE_VIEW (priv->tree_view),
2292                                     tree_column);
2293 }
2294
2295 /**
2296  * gtk_tree_view_column_get_max_width:
2297  * @tree_column: A #GtkTreeViewColumn.
2298  * 
2299  * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
2300  * width is set.
2301  * 
2302  * Return value: The maximum width of the @tree_column.
2303  **/
2304 gint
2305 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
2306 {
2307   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2308
2309   return tree_column->priv->max_width;
2310 }
2311
2312 /**
2313  * gtk_tree_view_column_clicked:
2314  * @tree_column: a #GtkTreeViewColumn
2315  * 
2316  * Emits the "clicked" signal on the column.  This function will only work if
2317  * @tree_column is clickable.
2318  **/
2319 void
2320 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
2321 {
2322   GtkTreeViewColumnPrivate *priv;
2323
2324   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2325
2326   priv = tree_column->priv;
2327
2328   if (priv->visible &&
2329       priv->button &&
2330       priv->clickable)
2331     gtk_button_clicked (GTK_BUTTON (priv->button));
2332 }
2333
2334 /**
2335  * gtk_tree_view_column_set_title:
2336  * @tree_column: A #GtkTreeViewColumn.
2337  * @title: The title of the @tree_column.
2338  * 
2339  * Sets the title of the @tree_column.  If a custom widget has been set, then
2340  * this value is ignored.
2341  **/
2342 void
2343 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
2344                                 const gchar       *title)
2345 {
2346   GtkTreeViewColumnPrivate *priv;
2347   gchar                    *new_title;
2348
2349   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2350
2351   priv = tree_column->priv;
2352
2353   new_title = g_strdup (title);
2354   g_free (priv->title);
2355   priv->title = new_title;
2356
2357   gtk_tree_view_column_update_button (tree_column);
2358   g_object_notify (G_OBJECT (tree_column), "title");
2359 }
2360
2361 /**
2362  * gtk_tree_view_column_get_title:
2363  * @tree_column: A #GtkTreeViewColumn.
2364  * 
2365  * Returns the title of the widget.
2366  * 
2367  * Return value: the title of the column. This string should not be
2368  * modified or freed.
2369  **/
2370 G_CONST_RETURN gchar *
2371 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
2372 {
2373   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2374
2375   return tree_column->priv->title;
2376 }
2377
2378 /**
2379  * gtk_tree_view_column_set_expand:
2380  * @tree_column: A #GtkTreeViewColumn
2381  * @expand: %TRUE if the column should take available extra space, %FALSE if not
2382  * 
2383  * Sets the column to take available extra space.  This space is shared equally
2384  * amongst all columns that have the expand set to %TRUE.  If no column has this
2385  * option set, then the last column gets all extra space.  By default, every
2386  * column is created with this %FALSE.
2387  *
2388  * Since: 2.4
2389  **/
2390 void
2391 gtk_tree_view_column_set_expand (GtkTreeViewColumn *tree_column,
2392                                  gboolean           expand)
2393 {
2394   GtkTreeViewColumnPrivate *priv;
2395
2396   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2397
2398   priv = tree_column->priv;
2399
2400   expand = expand?TRUE:FALSE;
2401   if (priv->expand == expand)
2402     return;
2403   priv->expand = expand;
2404
2405   if (priv->visible &&
2406       priv->tree_view != NULL &&
2407       gtk_widget_get_realized (priv->tree_view))
2408     {
2409       /* We want to continue using the original width of the
2410        * column that includes additional space added by the user
2411        * resizing the columns and possibly extra (expanded) space, which
2412        * are not included in the resized width.
2413        */
2414       priv->use_resized_width = FALSE;
2415
2416       gtk_widget_queue_resize (priv->tree_view);
2417     }
2418
2419   g_object_notify (G_OBJECT (tree_column), "expand");
2420 }
2421
2422 /**
2423  * gtk_tree_view_column_get_expand:
2424  * @tree_column: a #GtkTreeViewColumn
2425  * 
2426  * Return %TRUE if the column expands to take any available space.
2427  * 
2428  * Return value: %TRUE, if the column expands
2429  *
2430  * Since: 2.4
2431  **/
2432 gboolean
2433 gtk_tree_view_column_get_expand (GtkTreeViewColumn *tree_column)
2434 {
2435   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2436
2437   return tree_column->priv->expand;
2438 }
2439
2440 /**
2441  * gtk_tree_view_column_set_clickable:
2442  * @tree_column: A #GtkTreeViewColumn.
2443  * @clickable: %TRUE if the header is active.
2444  * 
2445  * Sets the header to be active if @active is %TRUE.  When the header is active,
2446  * then it can take keyboard focus, and can be clicked.
2447  **/
2448 void
2449 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
2450                                     gboolean           clickable)
2451 {
2452   GtkTreeViewColumnPrivate *priv;
2453
2454   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2455
2456   priv = tree_column->priv;
2457
2458   clickable = !! clickable;
2459   if (priv->clickable == clickable)
2460     return;
2461
2462   priv->clickable = clickable;
2463   gtk_tree_view_column_update_button (tree_column);
2464   g_object_notify (G_OBJECT (tree_column), "clickable");
2465 }
2466
2467 /**
2468  * gtk_tree_view_column_get_clickable:
2469  * @tree_column: a #GtkTreeViewColumn
2470  * 
2471  * Returns %TRUE if the user can click on the header for the column.
2472  * 
2473  * Return value: %TRUE if user can click the column header.
2474  **/
2475 gboolean
2476 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
2477 {
2478   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2479
2480   return tree_column->priv->clickable;
2481 }
2482
2483 /**
2484  * gtk_tree_view_column_set_widget:
2485  * @tree_column: A #GtkTreeViewColumn.
2486  * @widget: (allow-none): A child #GtkWidget, or %NULL.
2487  *
2488  * Sets the widget in the header to be @widget.  If widget is %NULL, then the
2489  * header button is set with a #GtkLabel set to the title of @tree_column.
2490  **/
2491 void
2492 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
2493                                  GtkWidget         *widget)
2494 {
2495   GtkTreeViewColumnPrivate *priv;
2496
2497   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2498   g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
2499
2500   priv = tree_column->priv;
2501
2502   if (widget)
2503     g_object_ref_sink (widget);
2504
2505   if (priv->child)      
2506     g_object_unref (priv->child);
2507
2508   priv->child = widget;
2509   gtk_tree_view_column_update_button (tree_column);
2510   g_object_notify (G_OBJECT (tree_column), "widget");
2511 }
2512
2513 /**
2514  * gtk_tree_view_column_get_widget:
2515  * @tree_column: A #GtkTreeViewColumn.
2516  *
2517  * Returns the #GtkWidget in the button on the column header.
2518  * If a custom widget has not been set then %NULL is returned.
2519  *
2520  * Return value: (transfer none): The #GtkWidget in the column
2521  *     header, or %NULL
2522  **/
2523 GtkWidget *
2524 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
2525 {
2526   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2527
2528   return tree_column->priv->child;
2529 }
2530
2531 /**
2532  * gtk_tree_view_column_set_alignment:
2533  * @tree_column: A #GtkTreeViewColumn.
2534  * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
2535  * 
2536  * Sets the alignment of the title or custom widget inside the column header.
2537  * The alignment determines its location inside the button -- 0.0 for left, 0.5
2538  * for center, 1.0 for right.
2539  **/
2540 void
2541 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
2542                                     gfloat             xalign)
2543 {
2544   GtkTreeViewColumnPrivate *priv;
2545
2546   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2547
2548   priv = tree_column->priv;
2549
2550   xalign = CLAMP (xalign, 0.0, 1.0);
2551
2552   if (priv->xalign == xalign)
2553     return;
2554
2555   priv->xalign = xalign;
2556   gtk_tree_view_column_update_button (tree_column);
2557   g_object_notify (G_OBJECT (tree_column), "alignment");
2558 }
2559
2560 /**
2561  * gtk_tree_view_column_get_alignment:
2562  * @tree_column: A #GtkTreeViewColumn.
2563  * 
2564  * Returns the current x alignment of @tree_column.  This value can range
2565  * between 0.0 and 1.0.
2566  * 
2567  * Return value: The current alignent of @tree_column.
2568  **/
2569 gfloat
2570 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
2571 {
2572   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
2573
2574   return tree_column->priv->xalign;
2575 }
2576
2577 /**
2578  * gtk_tree_view_column_set_reorderable:
2579  * @tree_column: A #GtkTreeViewColumn
2580  * @reorderable: %TRUE, if the column can be reordered.
2581  * 
2582  * If @reorderable is %TRUE, then the column can be reordered by the end user
2583  * dragging the header.
2584  **/
2585 void
2586 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
2587                                       gboolean           reorderable)
2588 {
2589   GtkTreeViewColumnPrivate *priv;
2590
2591   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2592
2593   priv = tree_column->priv;
2594
2595   /*  if (reorderable)
2596       gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
2597
2598   if (priv->reorderable == (reorderable?TRUE:FALSE))
2599     return;
2600
2601   priv->reorderable = (reorderable?TRUE:FALSE);
2602   gtk_tree_view_column_update_button (tree_column);
2603   g_object_notify (G_OBJECT (tree_column), "reorderable");
2604 }
2605
2606 /**
2607  * gtk_tree_view_column_get_reorderable:
2608  * @tree_column: A #GtkTreeViewColumn
2609  * 
2610  * Returns %TRUE if the @tree_column can be reordered by the user.
2611  * 
2612  * Return value: %TRUE if the @tree_column can be reordered by the user.
2613  **/
2614 gboolean
2615 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
2616 {
2617   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2618
2619   return tree_column->priv->reorderable;
2620 }
2621
2622
2623 /**
2624  * gtk_tree_view_column_set_sort_column_id:
2625  * @tree_column: a #GtkTreeViewColumn
2626  * @sort_column_id: The @sort_column_id of the model to sort on.
2627  *
2628  * Sets the logical @sort_column_id that this column sorts on when this column 
2629  * is selected for sorting.  Doing so makes the column header clickable.
2630  **/
2631 void
2632 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
2633                                          gint               sort_column_id)
2634 {
2635   GtkTreeViewColumnPrivate *priv;
2636
2637   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2638   g_return_if_fail (sort_column_id >= -1);
2639
2640   priv = tree_column->priv;
2641
2642   if (priv->sort_column_id == sort_column_id)
2643     return;
2644
2645   priv->sort_column_id = sort_column_id;
2646
2647   /* Handle unsetting the id */
2648   if (sort_column_id == -1)
2649     {
2650       GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
2651
2652       if (priv->sort_clicked_signal)
2653         {
2654           g_signal_handler_disconnect (tree_column, priv->sort_clicked_signal);
2655           priv->sort_clicked_signal = 0;
2656         }
2657
2658       if (priv->sort_column_changed_signal)
2659         {
2660           g_signal_handler_disconnect (model, priv->sort_column_changed_signal);
2661           priv->sort_column_changed_signal = 0;
2662         }
2663
2664       gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2665       gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
2666       gtk_tree_view_column_set_clickable (tree_column, FALSE);
2667       g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2668       return;
2669     }
2670
2671   gtk_tree_view_column_set_clickable (tree_column, TRUE);
2672
2673   if (! priv->sort_clicked_signal)
2674     priv->sort_clicked_signal = g_signal_connect (tree_column,
2675                                                   "clicked",
2676                                                   G_CALLBACK (gtk_tree_view_column_sort),
2677                                                   NULL);
2678
2679   gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
2680   g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2681 }
2682
2683 /**
2684  * gtk_tree_view_column_get_sort_column_id:
2685  * @tree_column: a #GtkTreeViewColumn
2686  *
2687  * Gets the logical @sort_column_id that the model sorts on when this
2688  * column is selected for sorting.
2689  * See gtk_tree_view_column_set_sort_column_id().
2690  *
2691  * Return value: the current @sort_column_id for this column, or -1 if
2692  *               this column can't be used for sorting.
2693  **/
2694 gint
2695 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
2696 {
2697   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2698
2699   return tree_column->priv->sort_column_id;
2700 }
2701
2702 /**
2703  * gtk_tree_view_column_set_sort_indicator:
2704  * @tree_column: a #GtkTreeViewColumn
2705  * @setting: %TRUE to display an indicator that the column is sorted
2706  *
2707  * Call this function with a @setting of %TRUE to display an arrow in
2708  * the header button indicating the column is sorted. Call
2709  * gtk_tree_view_column_set_sort_order() to change the direction of
2710  * the arrow.
2711  * 
2712  **/
2713 void
2714 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn     *tree_column,
2715                                          gboolean               setting)
2716 {
2717   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2718
2719   setting = setting != FALSE;
2720
2721   if (setting == tree_column->priv->show_sort_indicator)
2722     return;
2723
2724   tree_column->priv->show_sort_indicator = setting;
2725   gtk_tree_view_column_update_button (tree_column);
2726   g_object_notify (G_OBJECT (tree_column), "sort-indicator");
2727 }
2728
2729 /**
2730  * gtk_tree_view_column_get_sort_indicator:
2731  * @tree_column: a #GtkTreeViewColumn
2732  * 
2733  * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2734  * 
2735  * Return value: whether the sort indicator arrow is displayed
2736  **/
2737 gboolean
2738 gtk_tree_view_column_get_sort_indicator  (GtkTreeViewColumn     *tree_column)
2739 {
2740   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2741
2742   return tree_column->priv->show_sort_indicator;
2743 }
2744
2745 /**
2746  * gtk_tree_view_column_set_sort_order:
2747  * @tree_column: a #GtkTreeViewColumn
2748  * @order: sort order that the sort indicator should indicate
2749  *
2750  * Changes the appearance of the sort indicator. 
2751  * 
2752  * This <emphasis>does not</emphasis> actually sort the model.  Use
2753  * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2754  * support.  This function is primarily for custom sorting behavior, and should
2755  * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2756  * that. For custom models, the mechanism will vary. 
2757  * 
2758  * The sort indicator changes direction to indicate normal sort or reverse sort.
2759  * Note that you must have the sort indicator enabled to see anything when 
2760  * calling this function; see gtk_tree_view_column_set_sort_indicator().
2761  **/
2762 void
2763 gtk_tree_view_column_set_sort_order      (GtkTreeViewColumn     *tree_column,
2764                                           GtkSortType            order)
2765 {
2766   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2767
2768   if (order == tree_column->priv->sort_order)
2769     return;
2770
2771   tree_column->priv->sort_order = order;
2772   gtk_tree_view_column_update_button (tree_column);
2773   g_object_notify (G_OBJECT (tree_column), "sort-order");
2774 }
2775
2776 /**
2777  * gtk_tree_view_column_get_sort_order:
2778  * @tree_column: a #GtkTreeViewColumn
2779  * 
2780  * Gets the value set by gtk_tree_view_column_set_sort_order().
2781  * 
2782  * Return value: the sort order the sort indicator is indicating
2783  **/
2784 GtkSortType
2785 gtk_tree_view_column_get_sort_order      (GtkTreeViewColumn     *tree_column)
2786 {
2787   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2788
2789   return tree_column->priv->sort_order;
2790 }
2791
2792 /**
2793  * gtk_tree_view_column_cell_set_cell_data:
2794  * @tree_column: A #GtkTreeViewColumn.
2795  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2796  * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2797  * @is_expander: %TRUE, if the row has children
2798  * @is_expanded: %TRUE, if the row has visible children
2799  * 
2800  * Sets the cell renderer based on the @tree_model and @iter.  That is, for
2801  * every attribute mapping in @tree_column, it will get a value from the set
2802  * column on the @iter, and use that value to set the attribute on the cell
2803  * renderer.  This is used primarily by the #GtkTreeView.
2804  **/
2805 void
2806 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2807                                          GtkTreeModel      *tree_model,
2808                                          GtkTreeIter       *iter,
2809                                          gboolean           is_expander,
2810                                          gboolean           is_expanded)
2811 {
2812   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2813
2814   if (tree_model == NULL)
2815     return;
2816
2817   gtk_cell_area_apply_attributes (tree_column->priv->cell_area, tree_model, iter,
2818                                   is_expander, is_expanded);
2819 }
2820
2821 /**
2822  * gtk_tree_view_column_cell_get_size:
2823  * @tree_column: A #GtkTreeViewColumn.
2824  * @cell_area: (allow-none): The area a cell in the column will be allocated, or %NULL
2825  * @x_offset: (out) (allow-none): location to return x offset of a cell relative to @cell_area, or %NULL
2826  * @y_offset: (out) (allow-none): location to return y offset of a cell relative to @cell_area, or %NULL
2827  * @width: (out) (allow-none): location to return width needed to render a cell, or %NULL
2828  * @height: (out) (allow-none): location to return height needed to render a cell, or %NULL
2829  * 
2830  * Obtains the width and height needed to render the column.  This is used
2831  * primarily by the #GtkTreeView.
2832  **/
2833 void
2834 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn  *tree_column,
2835                                     const GdkRectangle *cell_area,
2836                                     gint               *x_offset,
2837                                     gint               *y_offset,
2838                                     gint               *width,
2839                                     gint               *height)
2840 {
2841   GtkTreeViewColumnPrivate *priv;
2842   gint min_width = 0, min_height = 0;
2843
2844   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2845
2846   priv = tree_column->priv;
2847
2848   g_signal_handler_block (priv->cell_area_context, 
2849                           priv->context_changed_signal);
2850
2851   gtk_cell_area_get_preferred_width (priv->cell_area,
2852                                      priv->cell_area_context,
2853                                      priv->tree_view,
2854                                      NULL, NULL);
2855
2856   gtk_cell_area_context_get_preferred_width (priv->cell_area_context, &min_width, NULL);
2857
2858   gtk_cell_area_get_preferred_height_for_width (priv->cell_area,
2859                                                 priv->cell_area_context,
2860                                                 priv->tree_view,
2861                                                 min_width,
2862                                                 &min_height,
2863                                                 NULL);
2864
2865   g_signal_handler_unblock (priv->cell_area_context, 
2866                             priv->context_changed_signal);
2867
2868
2869   if (height)
2870     * height = min_height;
2871   if (width)
2872     * width = min_width;
2873
2874 }
2875
2876 /**
2877  * gtk_tree_view_column_cell_render:
2878  * @tree_column: A #GtkTreeViewColumn.
2879  * @cr: cairo context to draw to
2880  * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2881  * @cell_area: area normally rendered by a cell renderer
2882  * @flags: flags that affect rendering
2883  * 
2884  * Renders the cell contained by #tree_column. This is used primarily by the
2885  * #GtkTreeView.
2886  **/
2887 void
2888 _gtk_tree_view_column_cell_render (GtkTreeViewColumn  *tree_column,
2889                                    cairo_t            *cr,
2890                                    const GdkRectangle *background_area,
2891                                    const GdkRectangle *cell_area,
2892                                    guint               flags,
2893                                    gboolean            draw_focus)
2894 {
2895   GtkTreeViewColumnPrivate *priv;
2896
2897   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2898   g_return_if_fail (cr != NULL);
2899   g_return_if_fail (background_area != NULL);
2900   g_return_if_fail (cell_area != NULL);
2901
2902   priv = tree_column->priv;
2903
2904   cairo_save (cr);
2905
2906   gtk_cell_area_render (priv->cell_area, priv->cell_area_context,
2907                         priv->tree_view, cr,
2908                         background_area, cell_area, flags,
2909                         draw_focus);
2910
2911   cairo_restore (cr);
2912 }
2913
2914 gboolean
2915 _gtk_tree_view_column_cell_event (GtkTreeViewColumn  *tree_column,
2916                                   GdkEvent           *event,
2917                                   const GdkRectangle *cell_area,
2918                                   guint               flags)
2919 {
2920   GtkTreeViewColumnPrivate *priv;
2921
2922   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2923
2924   priv = tree_column->priv;
2925
2926   return gtk_cell_area_event (priv->cell_area,
2927                               priv->cell_area_context,
2928                               priv->tree_view,
2929                               event,
2930                               cell_area,
2931                               flags);
2932 }
2933
2934 /**
2935  * gtk_tree_view_column_cell_is_visible:
2936  * @tree_column: A #GtkTreeViewColumn
2937  * 
2938  * Returns %TRUE if any of the cells packed into the @tree_column are visible.
2939  * For this to be meaningful, you must first initialize the cells with
2940  * gtk_tree_view_column_cell_set_cell_data()
2941  * 
2942  * Return value: %TRUE, if any of the cells packed into the @tree_column are currently visible
2943  **/
2944 gboolean
2945 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2946 {
2947   GList *list;
2948   GList *cells;
2949   GtkTreeViewColumnPrivate *priv;
2950
2951   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2952
2953   priv = tree_column->priv;
2954
2955   cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->cell_area));
2956   for (list = cells; list; list = list->next)
2957     {
2958       if (gtk_cell_renderer_get_visible (list->data))
2959         {
2960           g_list_free (cells);
2961           return TRUE;
2962         }
2963     }
2964
2965   g_list_free (cells);
2966
2967   return FALSE;
2968 }
2969
2970 /**
2971  * gtk_tree_view_column_focus_cell:
2972  * @tree_column: A #GtkTreeViewColumn
2973  * @cell: A #GtkCellRenderer
2974  *
2975  * Sets the current keyboard focus to be at @cell, if the column contains
2976  * 2 or more editable and activatable cells.
2977  *
2978  * Since: 2.2
2979  **/
2980 void
2981 gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
2982                                  GtkCellRenderer   *cell)
2983 {
2984   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2985   g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
2986
2987   gtk_cell_area_set_focus_cell (tree_column->priv->cell_area, cell);
2988 }
2989
2990 void
2991 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
2992                                       gboolean           install_handler)
2993 {
2994   GtkTreeViewColumnPrivate *priv = tree_column->priv;
2995
2996   priv->dirty = TRUE;
2997   priv->padding = 0;
2998   priv->width = 0;
2999
3000   /* Issue a manual reset on the context to have all
3001    * sizes re-requested for the context.
3002    */
3003   g_signal_handler_block (priv->cell_area_context, 
3004                           priv->context_changed_signal);
3005   gtk_cell_area_context_reset (priv->cell_area_context);
3006   g_signal_handler_unblock (priv->cell_area_context, 
3007                             priv->context_changed_signal);
3008
3009   if (priv->tree_view &&
3010       gtk_widget_get_realized (priv->tree_view))
3011     {
3012       _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (priv->tree_view), install_handler);
3013       gtk_widget_queue_resize (priv->tree_view);
3014     }
3015 }
3016
3017 gboolean
3018 _gtk_tree_view_column_cell_get_dirty (GtkTreeViewColumn  *tree_column)
3019 {
3020   return tree_column->priv->dirty;
3021 }
3022
3023 /**
3024  * gtk_tree_view_column_cell_get_position:
3025  * @tree_column: a #GtkTreeViewColumn
3026  * @cell_renderer: a #GtkCellRenderer
3027  * @x_offset: (out) (allow-none): return location for the horizontal
3028  *            position of @cell within @tree_column, may be %NULL
3029  * @width: (out) (allow-none): return location for the width of @cell,
3030  *         may be %NULL
3031  *
3032  * Obtains the horizontal position and size of a cell in a column. If the
3033  * cell is not found in the column, @start_pos and @width are not changed and
3034  * %FALSE is returned.
3035  * 
3036  * Return value: %TRUE if @cell belongs to @tree_column.
3037  */
3038 gboolean
3039 gtk_tree_view_column_cell_get_position (GtkTreeViewColumn *tree_column,
3040                                         GtkCellRenderer   *cell_renderer,
3041                                         gint              *x_offset,
3042                                         gint              *width)
3043 {
3044   GtkTreeViewColumnPrivate *priv;
3045   GdkRectangle cell_area;
3046   GdkRectangle allocation;
3047
3048   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
3049   g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell_renderer), FALSE);
3050
3051   priv = tree_column->priv;
3052
3053   gtk_tree_view_get_background_area (GTK_TREE_VIEW (priv->tree_view),
3054                                      NULL, tree_column, &cell_area);
3055
3056   gtk_cell_area_get_cell_allocation (priv->cell_area,
3057                                      priv->cell_area_context,
3058                                      priv->tree_view,
3059                                      cell_renderer,
3060                                      &cell_area,
3061                                      &allocation);
3062
3063   if (x_offset)
3064     {
3065       GdkRectangle button_allocation;
3066
3067       /* Retrieve column offset */
3068       gtk_widget_get_allocation (priv->button, &button_allocation);
3069       *x_offset = allocation.x - button_allocation.x;
3070     }
3071   if (width)
3072     *width = allocation.width;
3073
3074   return TRUE;
3075 }
3076
3077 /**
3078  * gtk_tree_view_column_queue_resize:
3079  * @tree_column: A #GtkTreeViewColumn
3080  *
3081  * Flags the column, and the cell renderers added to this column, to have
3082  * their sizes renegotiated.
3083  *
3084  * Since: 2.8
3085  **/
3086 void
3087 gtk_tree_view_column_queue_resize (GtkTreeViewColumn *tree_column)
3088 {
3089   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3090
3091   if (tree_column->priv->tree_view)
3092     _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
3093 }
3094
3095 /**
3096  * gtk_tree_view_column_get_tree_view:
3097  * @tree_column: A #GtkTreeViewColumn
3098  *
3099  * Returns the #GtkTreeView wherein @tree_column has been inserted.
3100  * If @column is currently not inserted in any tree view, %NULL is
3101  * returned.
3102  *
3103  * Return value: (transfer none): The tree view wherein @column has
3104  *     been inserted if any, %NULL otherwise.
3105  *
3106  * Since: 2.12
3107  */
3108 GtkWidget *
3109 gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
3110 {
3111   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3112
3113   return tree_column->priv->tree_view;
3114 }
3115
3116 /**
3117  * gtk_tree_view_column_get_button:
3118  * @tree_column: A #GtkTreeViewColumn
3119  *
3120  * Returns the button used in the treeview column header
3121  *
3122  * Return value: (transfer none): The button for the column header.
3123  *
3124  * Since: 3.0
3125  */
3126 GtkWidget *
3127 gtk_tree_view_column_get_button (GtkTreeViewColumn *tree_column)
3128 {
3129   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3130
3131   return tree_column->priv->button;
3132 }
3133
3134 GdkWindow *
3135 _gtk_tree_view_column_get_window (GtkTreeViewColumn  *column)
3136 {
3137   return column->priv->window;
3138 }
3139
3140 void
3141 _gtk_tree_view_column_push_padding (GtkTreeViewColumn  *column,
3142                                     gint                padding)
3143 {
3144   column->priv->padding = MAX (column->priv->padding, padding);
3145 }
3146
3147 gint
3148 _gtk_tree_view_column_get_requested_width (GtkTreeViewColumn  *column)
3149 {
3150   gint requested_width;
3151
3152   gtk_cell_area_context_get_preferred_width (column->priv->cell_area_context, &requested_width, NULL);
3153
3154   return requested_width + column->priv->padding;
3155 }
3156
3157
3158 void
3159 _gtk_tree_view_column_set_resized_width (GtkTreeViewColumn  *column,
3160                                          gint                width)
3161 {
3162   column->priv->resized_width = width;
3163 }
3164
3165 gint
3166 _gtk_tree_view_column_get_resized_width (GtkTreeViewColumn  *column)
3167 {
3168   return column->priv->resized_width;
3169 }
3170
3171 void
3172 _gtk_tree_view_column_set_use_resized_width (GtkTreeViewColumn  *column,
3173                                              gboolean            use_resized_width)
3174 {
3175   column->priv->use_resized_width = use_resized_width;
3176 }
3177
3178 gboolean
3179 _gtk_tree_view_column_get_use_resized_width (GtkTreeViewColumn  *column)
3180 {
3181   return column->priv->use_resized_width;
3182 }
3183
3184 gint
3185 _gtk_tree_view_column_get_drag_x (GtkTreeViewColumn  *column)
3186 {
3187   return column->priv->drag_x;
3188 }
3189
3190 GtkCellAreaContext *
3191 _gtk_tree_view_column_get_context (GtkTreeViewColumn  *column)
3192 {
3193   return column->priv->cell_area_context;
3194 }