]> Pileus Git - ~andy/gtk/blob - gtk/gtktreeviewcolumn.c
don't draw if label->layout is NULL due to a pending resize
[~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 "gtktreeviewcolumn.h"
21 #include "gtktreeprivate.h"
22 #include "gtksignal.h"
23 #include "gtkbutton.h"
24 #include "gtkalignment.h"
25 #include "gtklabel.h"
26 #include "gtkintl.h"
27
28 enum
29 {
30   PROP_0,
31   
32   PROP_CELL_RENDERER,
33   PROP_VISIBLE,
34   PROP_SIZING,
35   PROP_WIDTH,
36   PROP_MIN_WIDTH,
37   PROP_MAX_WIDTH,
38   PROP_TITLE,
39   PROP_CLICKABLE,
40   PROP_WIDGET,
41   PROP_JUSTIFICATION
42 };
43
44 enum
45 {
46   CLICKED,
47   LAST_SIGNAL
48 };
49
50
51 static void gtk_tree_view_column_init            (GtkTreeViewColumn      *tree_column);
52 static void gtk_tree_view_column_class_init      (GtkTreeViewColumnClass *klass);
53 static void gtk_tree_view_column_set_attributesv (GtkTreeViewColumn      *tree_column,
54                                                   va_list                 args);
55 static void gtk_real_tree_column_clicked         (GtkTreeViewColumn      *tree_column);
56 static void gtk_tree_view_column_set_property    (GObject         *object,
57                                                   guint            prop_id,
58                                                   const GValue    *value,
59                                                   GParamSpec      *pspec,
60                                                   const gchar     *trailer);
61 static void gtk_tree_view_column_get_property    (GObject         *object,
62                                                   guint            prop_id,
63                                                   GValue          *value,
64                                                   GParamSpec      *pspec,
65                                                   const gchar     *trailer);
66
67
68
69 static GtkObjectClass *parent_class = NULL;
70 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
71
72
73 GtkType
74 gtk_tree_view_column_get_type (void)
75 {
76   static GtkType tree_column_type = 0;
77
78   if (!tree_column_type)
79     {
80       static const GTypeInfo tree_column_info =
81       {
82         sizeof (GtkTreeViewColumnClass),
83         NULL,           /* base_init */
84         NULL,           /* base_finalize */
85         (GClassInitFunc) gtk_tree_view_column_class_init,
86         NULL,           /* class_finalize */
87         NULL,           /* class_data */
88         sizeof (GtkTreeViewColumn),
89         0,
90         (GInstanceInitFunc) gtk_tree_view_column_init,
91       };
92
93       tree_column_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeViewColumn", &tree_column_info, 0);
94     }
95
96   return tree_column_type;
97 }
98
99 static void
100 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
101 {
102   GObjectClass *object_class;
103
104   object_class = (GObjectClass*) class;
105
106   parent_class = g_type_class_peek_parent (class);
107
108   class->clicked = gtk_real_tree_column_clicked;
109
110   object_class->set_property = gtk_tree_view_column_set_property;
111   object_class->get_property = gtk_tree_view_column_get_property;
112   
113   tree_column_signals[CLICKED] =
114     g_signal_newc ("clicked",
115                    GTK_CLASS_TYPE (object_class),
116                    G_SIGNAL_RUN_LAST,
117                    G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
118                    NULL,
119                    gtk_marshal_VOID__VOID,
120                    GTK_TYPE_NONE, 0);
121
122   g_object_class_install_property (object_class,
123                                    PROP_CELL_RENDERER,
124                                    g_param_spec_object ("cell_renderer",
125                                                         _("Cell renderer"),
126                                                         _("Cell renderer object to use for rendering the cell"),
127                                                         GTK_TYPE_CELL_RENDERER,
128                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
129   
130   g_object_class_install_property (object_class,
131                                    PROP_VISIBLE,
132                                    g_param_spec_boolean ("visible",
133                                                         _("Visible"),
134                                                         _("Whether to display the colomn"),
135                                                          TRUE,
136                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
137   
138   g_object_class_install_property (object_class,
139                                    PROP_SIZING,
140                                    g_param_spec_enum ("sizing",
141                                                       _("Sizing"),
142                                                       _("Resize mode of the column"),
143                                                       GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
144                                                       GTK_TREE_VIEW_COLUMN_AUTOSIZE,
145                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
146   
147   g_object_class_install_property (object_class,
148                                    PROP_WIDTH,
149                                    g_param_spec_int ("width",
150                                                      _("Width"),
151                                                      _("Current width of the column"),
152                                                      1,
153                                                      G_MAXINT,
154                                                      1, /* not useful */
155                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
156
157   g_object_class_install_property (object_class,
158                                    PROP_MIN_WIDTH,
159                                    g_param_spec_int ("min_width",
160                                                      _("Minimum Width"),
161                                                      _("Minimum allowed width of the column"),
162                                                      -1,
163                                                      G_MAXINT,
164                                                      1,
165                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
166
167   g_object_class_install_property (object_class,
168                                    PROP_MAX_WIDTH,
169                                    g_param_spec_int ("max_width",
170                                                      _("Maximum Width"),
171                                                      _("Maximum allowed width of the column"),
172                                                      -1,
173                                                      G_MAXINT,
174                                                      G_MAXINT,
175                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
176
177   g_object_class_install_property (object_class,
178                                    PROP_TITLE,
179                                    g_param_spec_string ("title",
180                                                         _("Title"),
181                                                         _("Title to appear in column header"),
182                                                         "",
183                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
184   
185   g_object_class_install_property (object_class,
186                                    PROP_CLICKABLE,
187                                    g_param_spec_boolean ("clickable",
188                                                         _("Clickable"),
189                                                         _("Whether the header can be clicked"),
190                                                          TRUE,
191                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
192   
193
194   g_object_class_install_property (object_class,
195                                    PROP_WIDGET,
196                                    g_param_spec_object ("widget",
197                                                         _("Widget"),
198                                                         _("Widget to put in column header button instead of column title"),
199                                                         GTK_TYPE_WIDGET,
200                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
201
202   g_object_class_install_property (object_class,
203                                    PROP_JUSTIFICATION,
204                                    g_param_spec_enum ("justification",
205                                                       _("Justification"),
206                                                       _("Justification of the column"),
207                                                       GTK_TYPE_JUSTIFICATION,
208                                                       GTK_JUSTIFY_LEFT,
209                                                       G_PARAM_READABLE | G_PARAM_WRITABLE));
210 }
211
212 static void
213 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
214 {
215   tree_column->button = NULL;
216   tree_column->justification = GTK_JUSTIFY_LEFT;
217   tree_column->width = 1;
218   tree_column->min_width = -1;
219   tree_column->max_width = -1;
220   tree_column->cell = NULL;
221   tree_column->attributes = NULL;
222   tree_column->column_type = GTK_TREE_VIEW_COLUMN_AUTOSIZE;
223   tree_column->visible = TRUE;
224   tree_column->button_active = FALSE;
225   tree_column->dirty = TRUE;
226 }
227
228 static void
229 gtk_tree_view_column_set_property (GObject         *object,
230                                    guint            prop_id,
231                                    const GValue    *value,
232                                    GParamSpec      *pspec,
233                                    const gchar     *trailer)
234 {
235   GtkTreeViewColumn *tree_column;
236
237   tree_column = GTK_TREE_VIEW_COLUMN (object);
238
239   switch (prop_id)
240     {
241     case PROP_CELL_RENDERER:
242       gtk_tree_view_column_set_cell_renderer (tree_column,
243                                               (GtkCellRenderer*)
244                                               g_value_get_object (value));
245       break;
246
247     case PROP_VISIBLE:
248       gtk_tree_view_column_set_visible (tree_column,
249                                         g_value_get_boolean (value));
250       break;
251
252     case PROP_SIZING:
253       gtk_tree_view_column_set_sizing (tree_column,
254                                        g_value_get_enum (value));
255       break;
256
257     case PROP_WIDTH:
258       gtk_tree_view_column_set_width (tree_column,
259                                       g_value_get_int (value));
260       break;
261
262     case PROP_MIN_WIDTH:
263       gtk_tree_view_column_set_min_width (tree_column,
264                                           g_value_get_int (value));
265       break;
266
267     case PROP_MAX_WIDTH:
268       gtk_tree_view_column_set_max_width (tree_column,
269                                           g_value_get_int (value));
270       break;
271
272     case PROP_TITLE:
273       gtk_tree_view_column_set_title (tree_column,
274                                       g_value_get_string (value));
275       break;
276
277     case PROP_CLICKABLE:
278       gtk_tree_view_column_set_clickable (tree_column,
279                                           g_value_get_boolean (value));
280       break;
281
282     case PROP_WIDGET:
283       gtk_tree_view_column_set_widget (tree_column,
284                                        (GtkWidget*) g_value_get_object (value));
285       break;
286
287     case PROP_JUSTIFICATION:
288       gtk_tree_view_column_set_justification (tree_column,
289                                               g_value_get_enum (value));
290       break;
291
292     default:
293       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
294       break;
295     }
296 }
297
298 static void
299 gtk_tree_view_column_get_property (GObject         *object,
300                                    guint            prop_id,
301                                    GValue          *value,
302                                    GParamSpec      *pspec,
303                                    const gchar     *trailer)
304 {
305   GtkTreeViewColumn *tree_column;
306
307   tree_column = GTK_TREE_VIEW_COLUMN (object);
308
309   switch (prop_id)
310     {
311     case PROP_CELL_RENDERER:
312       g_value_set_object (value, (GObject*) tree_column->cell);
313       break;
314
315     case PROP_VISIBLE:
316       g_value_set_boolean (value, tree_column->visible);
317       break;
318
319     case PROP_SIZING:
320       g_value_set_enum (value, tree_column->column_type);
321       break;
322
323     case PROP_WIDTH:
324       g_value_set_int (value, tree_column->width);
325       break;
326
327     case PROP_MIN_WIDTH:
328       g_value_set_int (value, tree_column->min_width);
329       break;
330
331     case PROP_MAX_WIDTH:
332       g_value_set_int (value, tree_column->max_width);
333       break;
334
335     case PROP_TITLE:
336       g_value_set_string (value, tree_column->title);
337       break;
338
339     case PROP_CLICKABLE:
340       g_value_set_boolean (value, tree_column->button_active);
341       break;
342
343     case PROP_WIDGET:
344       g_warning ("FIXME");
345       break;
346
347     case PROP_JUSTIFICATION:
348       g_value_set_enum (value, tree_column->justification);
349       break;
350
351     default:
352       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
353       break;
354     }
355
356 }
357
358 /* used to make the buttons 'unclickable' */
359
360 static gint
361 gtk_tree_view_passive_func (GtkWidget *widget,
362                             GdkEvent  *event,
363                             gpointer   data)
364 {
365   g_return_val_if_fail (event != NULL, FALSE);
366
367   switch (event->type)
368     {
369     case GDK_MOTION_NOTIFY:
370     case GDK_BUTTON_PRESS:
371     case GDK_2BUTTON_PRESS:
372     case GDK_3BUTTON_PRESS:
373     case GDK_BUTTON_RELEASE:
374     case GDK_ENTER_NOTIFY:
375     case GDK_LEAVE_NOTIFY:
376       return TRUE;
377     default:
378       break;
379     }
380   return FALSE;
381 }
382
383 static void
384 gtk_real_tree_column_clicked (GtkTreeViewColumn *tree_column)
385 {
386   g_return_if_fail (tree_column != NULL);
387   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
388
389 }
390
391 /**
392  * gtk_tree_view_column_new:
393  * 
394  * Creates a new #GtkTreeViewColumn.
395  * 
396  * Return value: A newly created #GtkTreeViewColumn.
397  **/
398 GtkTreeViewColumn *
399 gtk_tree_view_column_new (void)
400 {
401   GtkTreeViewColumn *retval;
402
403   retval = GTK_TREE_VIEW_COLUMN (gtk_type_new (GTK_TYPE_TREE_COLUMN));
404
405   return retval;
406 }
407
408 /**
409  * gtk_tree_view_column_new_with_attributes:
410  * @title: The title to set the header to.
411  * @cell: The #GtkCellRenderer.
412  * @Varargs: A NULL terminated list of attributes.
413  * 
414  * Creates a new #GtkTreeViewColumn with a number of default values.  This is
415  * equivalent to calling @gtk_tree_view_column_set_title,
416  * @gtk_tree_view_column_set_cell_renderer, and
417  * @gtk_tree_view_column_set_attributes on the newly created #GtkTreeViewColumn.
418  * 
419  * Return value: A newly created #GtkTreeViewColumn.
420  **/
421 GtkTreeViewColumn *
422 gtk_tree_view_column_new_with_attributes (gchar           *title,
423                                           GtkCellRenderer *cell,
424                                           ...)
425 {
426   GtkTreeViewColumn *retval;
427   va_list args;
428
429   retval = gtk_tree_view_column_new ();
430
431   gtk_tree_view_column_set_title (retval, title);
432   gtk_tree_view_column_set_cell_renderer (retval, cell);
433
434   va_start (args, cell);
435   gtk_tree_view_column_set_attributesv (retval, args);
436   va_end (args);
437
438   return retval;
439 }
440
441 /**
442  * gtk_tree_view_column_set_cell_renderer:
443  * @tree_column: A #GtkTreeViewColumn.
444  * @cell: The #GtkCellRenderer, or NULL.
445  * 
446  * Sets the cell renderer of the @tree_column.  If there is a cell
447  * renderer already set, then it is removed.  If @cell is NULL, then
448  * the cell renderer is unset.
449  **/
450 void
451 gtk_tree_view_column_set_cell_renderer (GtkTreeViewColumn *tree_column,
452                                         GtkCellRenderer   *cell)
453 {
454   g_return_if_fail (tree_column != NULL);
455   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
456   if (cell)
457     g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
458
459   if (cell)
460     g_object_ref (G_OBJECT (cell));
461
462   if (tree_column->cell)
463     g_object_unref (G_OBJECT (tree_column->cell));
464
465   tree_column->cell = cell;
466
467   g_object_notify (G_OBJECT (tree_column), "cell_renderer");
468 }
469
470 /**
471  * gtk_tree_view_column_add_attribute:
472  * @tree_column: A #GtkTreeViewColumn.
473  * @attribute: An attribute on the columns cell
474  * @column: The column position on the model to get the attribute from.
475  * 
476  * Adds an attribute mapping to the list in @tree_column.  The @column is the
477  * column position on the model to get a value from, and the @attribute is the
478  * parameter on the @tree_column's cell renderer to set that value to.
479  **/
480 void
481 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
482                                     gchar             *attribute,
483                                     gint               column)
484 {
485   g_return_if_fail (tree_column != NULL);
486   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
487
488   tree_column->attributes = g_slist_prepend (tree_column->attributes,
489                                              GINT_TO_POINTER (column));
490   tree_column->attributes = g_slist_prepend (tree_column->attributes,
491                                              g_strdup (attribute));
492 }
493
494 static void
495 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
496                                       va_list            args)
497 {
498   GSList *list;
499   gchar *attribute;
500   gint column;
501
502   g_return_if_fail (tree_column != NULL);
503   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
504
505   attribute = va_arg (args, gchar *);
506
507   list = tree_column->attributes;
508
509   while (list && list->next)
510     {
511       g_free (list->data);
512       list = list->next->next;
513     }
514   g_slist_free (tree_column->attributes);
515   tree_column->attributes = NULL;
516
517   while (attribute != NULL)
518     {
519       column = va_arg (args, gint);
520       gtk_tree_view_column_add_attribute (tree_column,
521                                           attribute,
522                                           column);
523       attribute = va_arg (args, gchar *);
524     }
525 }
526
527 /**
528  * gtk_tree_view_column_set_attributes:
529  * @tree_column: A #GtkTreeViewColumn.
530  * @Varargs: A NULL terminated listing of attributes.
531  * 
532  * Sets the attributes in the list as the attributes of @tree_column.
533  * The attributes should be in attribute/column order, as in
534  * @gtk_tree_view_column_add_attribute. All existing attributes
535  * are removed, and replaced with the new attributes.
536  **/
537 void
538 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
539                                      ...)
540 {
541   va_list args;
542
543   g_return_if_fail (tree_column != NULL);
544   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
545
546   va_start (args, tree_column);
547
548   gtk_tree_view_column_set_attributesv (tree_column, args);
549
550   va_end (args);
551 }
552
553 /**
554  * gtk_tree_view_column_set_cell_data:
555  * @tree_column: A #GtkTreeViewColumn.
556  * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
557  * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
558  * 
559  * Sets the cell renderer based on the @tree_model and @tree_node.  That is, for
560  * every attribute mapping in @tree_column, it will get a value from the set
561  * column on the @tree_node, and use that value to set the attribute on the cell
562  * renderer.
563  **/
564 void
565 gtk_tree_view_column_set_cell_data (GtkTreeViewColumn *tree_column,
566                                     GtkTreeModel      *tree_model,
567                                     GtkTreeIter       *iter)
568 {
569   GSList *list;
570   GValue value = { 0, };
571   GObject *cell;
572
573   g_return_if_fail (tree_column != NULL);
574   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
575   g_return_if_fail (tree_column->cell != NULL);
576
577   if (tree_model == NULL)
578     return;
579
580   if (tree_column->func && (* tree_column->func) (tree_column,
581                                                   tree_model,
582                                                   iter,
583                                                   tree_column->func_data))
584     return;
585
586   cell = (GObject *) tree_column->cell;
587   list = tree_column->attributes;
588
589   while (list && list->next)
590     {
591       gtk_tree_model_get_value (tree_model, iter,
592                                 GPOINTER_TO_INT (list->next->data),
593                                 &value);
594       g_object_set_property (cell, (gchar *) list->data, &value);
595       g_value_unset (&value);
596       list = list->next->next;
597     }
598 }
599
600 /* Options for manipulating the columns */
601
602 /**
603  * gtk_tree_view_column_set_visible:
604  * @tree_column: A #GtkTreeViewColumn.
605  * @visible: TRUE if the @tree_column is visible.
606  * 
607  * Sets the visibility of @tree_column.
608  **/
609 void
610 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
611                                   gboolean           visible)
612 {
613   g_return_if_fail (tree_column != NULL);
614   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
615
616   visible = !! visible;
617   
618   if (tree_column->visible == visible)
619     return;
620
621   tree_column->visible = visible;
622
623   if (visible)
624     {
625       gtk_widget_show (tree_column->button);
626       if (GTK_WIDGET_REALIZED (tree_column->tree_view))
627         gdk_window_show (tree_column->window);
628     }
629   else
630     {
631       gtk_widget_hide (tree_column->button);
632       if (GTK_WIDGET_REALIZED (tree_column->tree_view))
633         gdk_window_hide (tree_column->window);
634     }
635
636   if (GTK_WIDGET_REALIZED (tree_column->tree_view))
637     _gtk_tree_view_set_size (GTK_TREE_VIEW (tree_column->tree_view), -1, -1);
638
639   g_object_notify (G_OBJECT (tree_column), "visible");
640 }
641
642 /**
643  * gtk_tree_view_column_get_visible:
644  * @tree_column: A #GtkTreeViewColumn.
645  * 
646  * Returns TRUE if @tree_column is visible.
647  * 
648  * Return value: whether the column is visible or not.  If it is visible, then
649  * the tree will show the column.
650  **/
651 gboolean
652 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
653 {
654   g_return_val_if_fail (tree_column != NULL, FALSE);
655   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
656
657   return tree_column->visible;
658 }
659
660 /**
661  * gtk_tree_view_column_set_sizing:
662  * @tree_column: A #GtkTreeViewColumn.
663  * @type: The #GtkTreeViewColumnSizing.
664  * 
665  * Sets the growth behavior of @tree_column to @type.
666  **/
667 void
668 gtk_tree_view_column_set_sizing (GtkTreeViewColumn     *tree_column,
669                                  GtkTreeViewColumnSizing  type)
670 {
671   g_return_if_fail (tree_column != NULL);
672   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
673
674   if (type == tree_column->column_type)
675     return;
676
677   tree_column->column_type = type;
678   switch (type)
679     {
680     case GTK_TREE_VIEW_COLUMN_AUTOSIZE:
681       tree_column->dirty = TRUE;
682     case GTK_TREE_VIEW_COLUMN_FIXED:
683       if (GTK_WIDGET_REALIZED (tree_column->tree_view))
684         gdk_window_hide (tree_column->window);
685       break;
686     default:
687       if (GTK_WIDGET_REALIZED (tree_column->tree_view))
688         {
689           gdk_window_show (tree_column->window);
690           gdk_window_raise (tree_column->window);
691         }
692       break;
693     }
694
695   gtk_widget_queue_resize (tree_column->tree_view);
696
697   g_object_notify (G_OBJECT (tree_column), "sizing");
698 }
699
700 /**
701  * gtk_tree_view_column_get_sizing:
702  * @tree_column: A #GtkTreeViewColumn.
703  * 
704  * Returns the current type of @tree_column.
705  * 
706  * Return value: The type of @tree_column.
707  **/
708 gint
709 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
710 {
711   g_return_val_if_fail (tree_column != NULL, 0);
712   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
713
714   return tree_column->column_type;
715 }
716
717 /**
718  * gtk_tree_view_column_get_size:
719  * @tree_column: A #GtkTreeViewColumn.
720  * 
721  * Returns the current size of the @tree_column in pixels.
722  * 
723  * Return value: The current size of the @tree_column.
724  **/
725 gint
726 gtk_tree_view_column_get_size (GtkTreeViewColumn *tree_column)
727 {
728   g_return_val_if_fail (tree_column != NULL, 0);
729   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
730
731   return tree_column->width;
732 }
733
734 /**
735  * gtk_tree_view_column_set_width:
736  * @tree_column: A #GtkTreeViewColumn.
737  * @size: The size to set the @tree_column to.
738  * 
739  * Sets the size of the column in pixels, unless the the column type is
740  * #GTK_TREE_VIEW_COLUMN_AUTOSIZE.  In this case, the value is discarded as the
741  * size of the column is based on the calculated width of the column. The
742  * width is clamped to the min/max width for the column.
743  **/
744 void
745 gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
746                                 gint               size)
747 {
748   g_return_if_fail (tree_column != NULL);
749   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
750   g_return_if_fail (size > 0);
751   
752   if (tree_column->min_width != -1 &&
753       size < tree_column->min_width)
754     size = tree_column->min_width;
755   else if (tree_column->max_width != -1 &&
756            size > tree_column->max_width)
757     size = tree_column->max_width;
758   
759   if (tree_column->width == size)
760     return;
761   
762   tree_column->width = size;
763   
764   if (GTK_WIDGET_REALIZED (tree_column->tree_view))
765     gtk_widget_queue_resize (tree_column->tree_view);
766   
767   g_object_notify (G_OBJECT (tree_column), "width");
768 }
769
770 /**
771  * gtk_tree_view_column_set_min_width:
772  * @tree_column: A #GtkTreeViewColumn.
773  * @min_width: The minimum width of the column in pixels, or -1.
774  * 
775  * Sets the minimum width of the @tree_column.  If @min_width is -1, then the
776  * minimum width is unset.
777  **/
778 void
779 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
780                                     gint               min_width)
781 {
782   gint real_min_width;
783
784   g_return_if_fail (tree_column != NULL);
785   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
786   g_return_if_fail (min_width >= -1);
787
788   if (min_width == tree_column->min_width)
789     return;
790
791   real_min_width = (tree_column->min_width == -1) ?
792     tree_column->button->requisition.width : tree_column->min_width;
793
794   /* We want to queue a resize if the either the old min_size or the
795    * new min_size determined the size of the column */
796   if (GTK_WIDGET_REALIZED (tree_column->tree_view) &&
797       ((tree_column->min_width > tree_column->width) ||
798        (tree_column->min_width == -1 &&
799         tree_column->button->requisition.width > tree_column->width) ||
800        (min_width > tree_column->width) ||
801        (min_width == -1 &&
802         tree_column->button->requisition.width > tree_column->width)))
803     gtk_widget_queue_resize (tree_column->tree_view);
804
805   if (tree_column->max_width != -1 &&
806       tree_column->max_width < real_min_width)
807     tree_column->max_width = real_min_width;
808
809   tree_column->min_width = min_width;
810
811   g_object_notify (G_OBJECT (tree_column), "min_width");
812 }
813
814 /**
815  * gtk_tree_view_column_get_min_width:
816  * @tree_column: A #GtkTreeViewColumn.
817  * 
818  * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
819  * width is set.
820  * 
821  * Return value: The minimum width of the @tree_column.
822  **/
823 gint
824 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
825 {
826   g_return_val_if_fail (tree_column != NULL, -1);
827   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
828
829   return tree_column->min_width;
830 }
831
832 /**
833  * gtk_tree_view_column_set_max_width:
834  * @tree_column: A #GtkTreeViewColumn.
835  * @max_width: The maximum width of the column in pixels, or -1.
836  * 
837  * Sets the maximum width of the @tree_column.  If @max_width is -1, then the
838  * maximum width is unset.
839  **/
840 void
841 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
842                                     gint               max_width)
843 {
844   gint real_min_width;
845
846   g_return_if_fail (tree_column != NULL);
847   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
848   g_return_if_fail (max_width >= -1);
849
850   if (max_width == tree_column->max_width)
851     return;
852
853   real_min_width = tree_column->min_width == -1 ?
854     tree_column->button->requisition.width : tree_column->min_width;
855
856   if (GTK_WIDGET_REALIZED (tree_column->tree_view) &&
857       ((tree_column->max_width < tree_column->width) ||
858        (max_width != -1 && max_width < tree_column->width)))
859     gtk_widget_queue_resize (tree_column->tree_view);
860
861   tree_column->max_width = max_width;
862
863   if (real_min_width > max_width)
864     tree_column->min_width = max_width;
865
866   g_object_notify (G_OBJECT (tree_column), "max_width");
867 }
868
869 /**
870  * gtk_tree_view_column_get_max_width:
871  * @tree_column: A #GtkTreeViewColumn.
872  * 
873  * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
874  * width is set.
875  * 
876  * Return value: The maximum width of the @tree_column.
877  **/
878 gint
879 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
880 {
881   g_return_val_if_fail (tree_column != NULL, -1);
882   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
883
884   return tree_column->max_width;
885 }
886
887 /**
888  * gtk_tree_view_column_clicked:
889  * @tree_column: a #GtkTreeViewColumn
890  * 
891  * Emits the "clicked" signal on the column.
892  **/
893 void
894 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
895 {
896   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
897
898   gtk_signal_emit (GTK_OBJECT (tree_column), tree_column_signals[CLICKED]);
899 }
900
901 /**
902  * gtk_tree_view_column_set_title:
903  * @tree_column: A #GtkTreeViewColumn.
904  * @title: The title of the @tree_column.
905  * 
906  * Sets the title of the @tree_column.  If a custom widget has been set, then
907  * this value is ignored.
908  **/
909 void
910 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
911                                 gchar         *title)
912 {
913   g_return_if_fail (tree_column != NULL);
914   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
915
916   g_free (tree_column->title);
917   if (title)
918     tree_column->title = g_strdup (title);
919   else
920     tree_column->title = NULL;
921
922   /* Hmmm.  This is a little ugly... */
923   if (tree_column->button)
924     {
925       if (GTK_BIN (tree_column->button)->child &&
926           GTK_IS_ALIGNMENT (GTK_BIN (tree_column->button)->child))
927         {
928           if (GTK_BIN (GTK_BIN (tree_column->button)->child)->child &&
929               GTK_IS_LABEL (GTK_BIN (GTK_BIN (tree_column->button)->child)->child))
930             {
931               gtk_label_set_text (GTK_LABEL (GTK_BIN (GTK_BIN (tree_column->button)->child)->child),
932                                   tree_column->title);
933             }
934         }
935     }
936
937   g_object_notify (G_OBJECT (tree_column), "title");
938 }
939
940 /**
941  * gtk_tree_view_column_get_title:
942  * @tree_column: A #GtkTreeViewColumn.
943  * 
944  * Returns the title of the widget.  This value should not be modified.
945  * 
946  * Return value: the title of the column.
947  **/
948 gchar *
949 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
950 {
951   g_return_val_if_fail (tree_column != NULL, NULL);
952   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
953
954   return tree_column->title;
955 }
956
957 /**
958  * gtk_tree_view_column_set_clickable:
959  * @tree_column: A #GtkTreeViewColumn.
960  * @active: TRUE if the header is active.
961  * 
962  * Sets the header to be active if @active is TRUE.  When the header is active,
963  * then it can take keyboard focus, and can be clicked.
964  **/
965 void
966 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
967                                     gboolean           active)
968 {
969   g_return_if_fail (tree_column != NULL);
970   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
971
972   if (!tree_column->button)
973     return;
974
975   if (tree_column->button_active == active)
976     return;
977
978   tree_column->button_active = active;
979   if (active)
980     {
981       gtk_signal_disconnect_by_func (GTK_OBJECT (tree_column->button),
982                                      (GtkSignalFunc) gtk_tree_view_passive_func,
983                                      NULL);
984
985       GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
986
987       if (GTK_WIDGET_VISIBLE (tree_column->tree_view))
988         gtk_widget_queue_draw (tree_column->button);
989     }
990   else
991     {
992       gtk_signal_connect (GTK_OBJECT (tree_column->button),
993                           "event",
994                           (GtkSignalFunc) gtk_tree_view_passive_func,
995                           NULL);
996
997       GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
998
999       if (GTK_WIDGET_VISIBLE (tree_column->tree_view))
1000         gtk_widget_queue_draw (tree_column->button);
1001     }
1002
1003   g_object_notify (G_OBJECT (tree_column), "clickable");
1004 }
1005
1006 /**
1007  * gtk_tree_view_column_get_clickable:
1008  * @tree_column: a #GtkTreeViewColumn
1009  * 
1010  * Returns %TRUE if the user can click on the header for the column.
1011  * 
1012  * Return value: whether the user can click the column header
1013  **/
1014 gboolean
1015 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1016 {
1017   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1018
1019   return tree_column->button_active;
1020 }
1021
1022 /**
1023  * gtk_tree_view_column_set_widget:
1024  * @tree_column: A #GtkTreeViewColumn.
1025  * @widget: A child #GtkWidget, or NULL.
1026  * 
1027  * Sets the widget in the header to be @widget.  If widget is NULL, then the
1028  * header button is set with a #GtkLabel set to the title of @tree_column.
1029  **/
1030 void
1031 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1032                                  GtkWidget         *widget)
1033 {
1034   /* FIXME: Implement this function. */
1035 #if 0
1036   gint new_button = 0;
1037   GtkWidget *old_widget;
1038
1039   g_return_if_fail (tree_view != NULL);
1040   g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
1041
1042   if (column < 0 || column >= tree_view->priv->columns)
1043     return;
1044
1045   /* if the column button doesn't currently exist,
1046    * it has to be created first */
1047   if (!column->button)
1048     {
1049       column_button_create (tree_view, column);
1050       new_button = 1;
1051     }
1052
1053   column_title_new (clist, column, NULL);
1054
1055   /* remove and destroy the old widget */
1056   old_widget = GTK_BIN (clist->column[column].button)->child;
1057   if (old_widget)
1058     gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
1059                           old_widget);
1060
1061   /* add and show the widget */
1062   if (widget)
1063     {
1064       gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
1065       gtk_widget_show (widget);
1066     }
1067
1068   /* if this button didn't previously exist, then the
1069    * column button positions have to be re-computed */
1070   if (GTK_WIDGET_VISIBLE (clist) && new_button)
1071     size_allocate_title_buttons (clist);
1072 #endif
1073
1074   g_object_notify (G_OBJECT (tree_column), "widget");
1075 }
1076
1077 /**
1078  * gtk_tree_view_column_get_widget:
1079  * @tree_column: A #GtkTreeViewColumn.
1080  * 
1081  * Returns the #GtkWidget in the button in the column header.  If a custom
1082  * widget has not been set, then this will be a #GtkAlignment with a #GtkLabel
1083  * in it.
1084  * 
1085  * Return value: The #GtkWidget in the column header.
1086  **/
1087 GtkWidget *
1088 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1089 {
1090   g_return_val_if_fail (tree_column != NULL, NULL);
1091   g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1092
1093   if (tree_column->button)
1094     return GTK_BUTTON (tree_column->button)->child;
1095
1096   return NULL;
1097 }
1098
1099 /**
1100  * gtk_tree_view_column_set_justification:
1101  * @tree_column: A #GtkTreeViewColumn.
1102  * @justification: The justification of the title.
1103  * 
1104  * Sets the justification of the title inside the column header.  If a custom
1105  * widget has been set, then this value is discarded.
1106  **/
1107 void
1108 gtk_tree_view_column_set_justification (GtkTreeViewColumn *tree_column,
1109                                         GtkJustification   justification)
1110 {
1111   GtkWidget *alignment;
1112
1113   g_return_if_fail (tree_column != NULL);
1114   g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1115
1116   if (tree_column->justification == justification)
1117     return;
1118
1119   tree_column->justification = justification;
1120
1121   /* change the alignment of the button title if it's not a
1122    * custom widget */
1123   alignment = GTK_BIN (tree_column->button)->child;
1124
1125   if (GTK_IS_ALIGNMENT (alignment))
1126     {
1127       switch (tree_column->justification)
1128         {
1129         case GTK_JUSTIFY_LEFT:
1130           gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
1131           break;
1132
1133         case GTK_JUSTIFY_RIGHT:
1134           gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
1135           break;
1136
1137         case GTK_JUSTIFY_CENTER:
1138           gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1139           break;
1140
1141         case GTK_JUSTIFY_FILL:
1142           gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
1143           break;
1144
1145         default:
1146           break;
1147         }
1148     }
1149
1150   g_object_notify (G_OBJECT (tree_column), "justification");
1151 }