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