2 * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
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.
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.
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.
20 #include "gtktreeviewcolumn.h"
21 #include "gtktreeview.h"
22 #include "gtktreeprivate.h"
23 #include "gtksignal.h"
24 #include "gtkbutton.h"
25 #include "gtkalignment.h"
28 #include "gtkmarshalers.h"
58 typedef struct _GtkTreeViewColumnCellInfo GtkTreeViewColumnCellInfo;
59 struct _GtkTreeViewColumnCellInfo
61 GtkCellRenderer *cell;
63 GtkTreeCellDataFunc func;
65 GtkDestroyNotify destroy;
73 static void gtk_tree_view_column_init (GtkTreeViewColumn *tree_column);
74 static void gtk_tree_view_column_class_init (GtkTreeViewColumnClass *klass);
77 static void gtk_tree_view_column_set_property (GObject *object,
81 static void gtk_tree_view_column_get_property (GObject *object,
85 static void gtk_tree_view_column_finalize (GObject *object);
87 /* Button handling code */
88 static void gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column);
89 static void gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column);
91 /* Button signal handlers */
92 static gint gtk_tree_view_column_button_event (GtkWidget *widget,
95 static void gtk_tree_view_column_button_realize (GtkWidget *widget,
97 static void gtk_tree_view_column_button_clicked (GtkWidget *widget,
100 /* Property handlers */
101 static void gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
102 GtkTreeViewColumn *tree_column);
104 /* Internal functions */
105 static void gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
107 static void gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column);
108 static void gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
109 GtkCellRenderer *cell_renderer,
111 static GtkTreeViewColumnCellInfo *gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
112 GtkCellRenderer *cell_renderer);
116 static GtkObjectClass *parent_class = NULL;
117 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
121 gtk_tree_view_column_get_type (void)
123 static GtkType tree_column_type = 0;
125 if (!tree_column_type)
127 static const GTypeInfo tree_column_info =
129 sizeof (GtkTreeViewColumnClass),
130 NULL, /* base_init */
131 NULL, /* base_finalize */
132 (GClassInitFunc) gtk_tree_view_column_class_init,
133 NULL, /* class_finalize */
134 NULL, /* class_data */
135 sizeof (GtkTreeViewColumn),
137 (GInstanceInitFunc) gtk_tree_view_column_init,
140 tree_column_type = g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeViewColumn", &tree_column_info, 0);
143 return tree_column_type;
147 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
149 GObjectClass *object_class;
151 object_class = (GObjectClass*) class;
153 parent_class = g_type_class_peek_parent (class);
155 class->clicked = NULL;
157 object_class->finalize = gtk_tree_view_column_finalize;
158 object_class->set_property = gtk_tree_view_column_set_property;
159 object_class->get_property = gtk_tree_view_column_get_property;
161 tree_column_signals[CLICKED] =
162 g_signal_new ("clicked",
163 GTK_CLASS_TYPE (object_class),
165 G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
167 _gtk_marshal_VOID__VOID,
170 g_object_class_install_property (object_class,
172 g_param_spec_boolean ("visible",
174 _("Whether to display the column"),
176 G_PARAM_READABLE | G_PARAM_WRITABLE));
178 g_object_class_install_property (object_class,
180 g_param_spec_boolean ("resizable",
182 _("Column is user-resizable"),
184 G_PARAM_READABLE | G_PARAM_WRITABLE));
186 g_object_class_install_property (object_class,
188 g_param_spec_int ("width",
190 _("Current width of the column"),
195 g_object_class_install_property (object_class,
197 g_param_spec_enum ("sizing",
199 _("Resize mode of the column"),
200 GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
201 GTK_TREE_VIEW_COLUMN_AUTOSIZE,
202 G_PARAM_READABLE | G_PARAM_WRITABLE));
204 g_object_class_install_property (object_class,
206 g_param_spec_int ("fixed_width",
208 _("Current fixed width of the column"),
212 G_PARAM_READABLE | G_PARAM_WRITABLE));
214 g_object_class_install_property (object_class,
216 g_param_spec_int ("min_width",
218 _("Minimum allowed width of the column"),
222 G_PARAM_READABLE | G_PARAM_WRITABLE));
224 g_object_class_install_property (object_class,
226 g_param_spec_int ("max_width",
228 _("Maximum allowed width of the column"),
232 G_PARAM_READABLE | G_PARAM_WRITABLE));
234 g_object_class_install_property (object_class,
236 g_param_spec_string ("title",
238 _("Title to appear in column header"),
240 G_PARAM_READABLE | G_PARAM_WRITABLE));
242 g_object_class_install_property (object_class,
244 g_param_spec_boolean ("clickable",
246 _("Whether the header can be clicked"),
248 G_PARAM_READABLE | G_PARAM_WRITABLE));
251 g_object_class_install_property (object_class,
253 g_param_spec_object ("widget",
255 _("Widget to put in column header button instead of column title"),
257 G_PARAM_READABLE | G_PARAM_WRITABLE));
259 g_object_class_install_property (object_class,
261 g_param_spec_float ("alignment",
263 _("X Alignment of the column header text or widget"),
267 G_PARAM_READABLE | G_PARAM_WRITABLE));
269 g_object_class_install_property (object_class,
271 g_param_spec_boolean ("reorderable",
273 _("Whether the column can be reordered around the headers"),
275 G_PARAM_READABLE | G_PARAM_WRITABLE));
277 g_object_class_install_property (object_class,
279 g_param_spec_boolean ("sort_indicator",
281 _("Whether to show a sort indicator"),
283 G_PARAM_READABLE | G_PARAM_WRITABLE));
285 g_object_class_install_property (object_class,
287 g_param_spec_enum ("sort_order",
289 _("Sort direction the sort indicator should indicate"),
292 G_PARAM_READABLE | G_PARAM_WRITABLE));
297 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
299 tree_column->button = NULL;
300 tree_column->xalign = 0.0;
301 tree_column->width = 0;
302 tree_column->requested_width = -1;
303 tree_column->min_width = -1;
304 tree_column->max_width = -1;
305 tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
306 tree_column->visible = TRUE;
307 tree_column->resizable = FALSE;
308 tree_column->clickable = FALSE;
309 tree_column->dirty = TRUE;
310 tree_column->sort_order = GTK_SORT_ASCENDING;
311 tree_column->show_sort_indicator = FALSE;
312 tree_column->property_changed_signal = 0;
313 tree_column->sort_clicked_signal = 0;
314 tree_column->sort_column_changed_signal = 0;
315 tree_column->sort_column_id = -1;
316 tree_column->reorderable = FALSE;
317 tree_column->maybe_reordered = FALSE;
321 gtk_tree_view_column_finalize (GObject *object)
323 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
326 for (list = tree_column->cell_list; list; list = list->next)
328 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
329 if (info->func_data && info->destroy)
330 (info->destroy) (info->func_data);
331 gtk_tree_view_column_clear_attributes (tree_column, info->cell);
332 g_object_unref (G_OBJECT (info->cell));
336 g_free (tree_column->title);
338 G_OBJECT_CLASS (parent_class)->finalize (object);
342 gtk_tree_view_column_set_property (GObject *object,
347 GtkTreeViewColumn *tree_column;
349 tree_column = GTK_TREE_VIEW_COLUMN (object);
354 gtk_tree_view_column_set_visible (tree_column,
355 g_value_get_boolean (value));
359 gtk_tree_view_column_set_sizing (tree_column,
360 g_value_get_enum (value));
363 case PROP_FIXED_WIDTH:
364 gtk_tree_view_column_set_fixed_width (tree_column,
365 g_value_get_int (value));
369 gtk_tree_view_column_set_min_width (tree_column,
370 g_value_get_int (value));
374 gtk_tree_view_column_set_max_width (tree_column,
375 g_value_get_int (value));
379 gtk_tree_view_column_set_title (tree_column,
380 g_value_get_string (value));
384 gtk_tree_view_column_set_clickable (tree_column,
385 g_value_get_boolean (value));
389 gtk_tree_view_column_set_widget (tree_column,
390 (GtkWidget*) g_value_get_object (value));
394 gtk_tree_view_column_set_alignment (tree_column,
395 g_value_get_float (value));
398 case PROP_REORDERABLE:
399 gtk_tree_view_column_set_reorderable (tree_column,
400 g_value_get_boolean (value));
403 case PROP_SORT_INDICATOR:
404 gtk_tree_view_column_set_sort_indicator (tree_column,
405 g_value_get_boolean (value));
408 case PROP_SORT_ORDER:
409 gtk_tree_view_column_set_sort_order (tree_column,
410 g_value_get_enum (value));
414 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
420 gtk_tree_view_column_get_property (GObject *object,
425 GtkTreeViewColumn *tree_column;
427 tree_column = GTK_TREE_VIEW_COLUMN (object);
432 g_value_set_boolean (value,
433 gtk_tree_view_column_get_visible (tree_column));
437 g_value_set_int (value,
438 gtk_tree_view_column_get_width (tree_column));
442 g_value_set_enum (value,
443 gtk_tree_view_column_get_sizing (tree_column));
446 case PROP_FIXED_WIDTH:
447 g_value_set_int (value,
448 gtk_tree_view_column_get_fixed_width (tree_column));
452 g_value_set_int (value,
453 gtk_tree_view_column_get_min_width (tree_column));
457 g_value_set_int (value,
458 gtk_tree_view_column_get_max_width (tree_column));
462 g_value_set_string (value,
463 gtk_tree_view_column_get_title (tree_column));
467 g_value_set_boolean (value,
468 gtk_tree_view_column_get_clickable (tree_column));
472 g_value_set_object (value,
473 (GObject*) gtk_tree_view_column_get_widget (tree_column));
477 g_value_set_float (value,
478 gtk_tree_view_column_get_alignment (tree_column));
481 case PROP_REORDERABLE:
482 g_value_set_boolean (value,
483 gtk_tree_view_column_get_reorderable (tree_column));
486 case PROP_SORT_INDICATOR:
487 g_value_set_boolean (value,
488 gtk_tree_view_column_get_sort_indicator (tree_column));
491 case PROP_SORT_ORDER:
492 g_value_set_enum (value,
493 gtk_tree_view_column_get_sort_order (tree_column));
497 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
505 /* Button handling code
508 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
510 GtkTreeView *tree_view;
514 tree_view = (GtkTreeView *) tree_column->tree_view;
516 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
517 g_return_if_fail (tree_column->button == NULL);
519 gtk_widget_push_composite_child ();
520 tree_column->button = gtk_button_new ();
521 gtk_widget_pop_composite_child ();
523 /* make sure we own a reference to it as well. */
524 if (tree_view->priv->header_window)
525 gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
526 gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
528 gtk_signal_connect (GTK_OBJECT (tree_column->button), "realize",
529 (GtkSignalFunc) gtk_tree_view_column_button_realize,
532 gtk_signal_connect (GTK_OBJECT (tree_column->button), "event",
533 (GtkSignalFunc) gtk_tree_view_column_button_event,
534 (gpointer) tree_column);
536 gtk_signal_connect (GTK_OBJECT (tree_column->button), "clicked",
537 (GtkSignalFunc) gtk_tree_view_column_button_clicked,
538 (gpointer) tree_column);
540 tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
542 hbox = gtk_hbox_new (FALSE, 2);
543 tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
545 if (tree_column->child)
546 child = tree_column->child;
549 child = gtk_label_new (tree_column->title);
550 gtk_widget_show (child);
553 if (tree_column->xalign <= 0.5)
554 gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
556 gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
558 gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
560 gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
561 gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
563 gtk_widget_show (hbox);
564 gtk_widget_show (tree_column->alignment);
565 gtk_tree_view_column_update_button (tree_column);
569 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
572 GtkWidget *alignment;
574 GtkWidget *current_child;
576 /* Create a button if necessary */
577 if (tree_column->visible &&
578 tree_column->button == NULL &&
579 tree_column->tree_view &&
580 GTK_WIDGET_REALIZED (tree_column->tree_view))
581 gtk_tree_view_column_create_button (tree_column);
583 if (! tree_column->button)
586 hbox = GTK_BIN (tree_column->button)->child;
587 alignment = tree_column->alignment;
588 arrow = tree_column->arrow;
589 current_child = GTK_BIN (alignment)->child;
591 /* Set up the actual button */
592 gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
595 if (tree_column->child)
597 if (current_child != tree_column->child)
599 gtk_container_remove (GTK_CONTAINER (alignment),
601 gtk_container_add (GTK_CONTAINER (alignment),
607 if (current_child == NULL)
609 current_child = gtk_label_new (NULL);
610 gtk_widget_show (current_child);
611 gtk_container_add (GTK_CONTAINER (alignment),
615 g_return_if_fail (GTK_IS_LABEL (current_child));
617 if (tree_column->title)
618 gtk_label_set_text (GTK_LABEL (current_child),
621 gtk_label_set_text (GTK_LABEL (current_child),
625 switch (tree_column->sort_order)
627 case GTK_SORT_ASCENDING:
628 gtk_arrow_set (GTK_ARROW (arrow),
633 case GTK_SORT_DESCENDING:
634 gtk_arrow_set (GTK_ARROW (arrow),
640 g_warning (G_STRLOC": bad sort order");
644 /* Put arrow on the right if the text is left-or-center justified,
645 * and on the left otherwise; do this by packing boxes, so flipping
646 * text direction will reverse things
648 gtk_widget_ref (arrow);
649 gtk_container_remove (GTK_CONTAINER (hbox), arrow);
651 if (tree_column->xalign <= 0.5)
653 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
657 gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
658 /* move it to the front */
659 gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
661 gtk_widget_unref (arrow);
663 if (tree_column->show_sort_indicator)
664 gtk_widget_show (arrow);
666 gtk_widget_hide (arrow);
668 /* It's always safe to hide the button. It isn't always safe to show it, as if you show it
669 * before it's realized, it'll get the wrong window. */
670 if (tree_column->button &&
671 tree_column->tree_view != NULL &&
672 GTK_WIDGET_REALIZED (tree_column->tree_view))
674 if (tree_column->visible)
676 gtk_widget_show_now (tree_column->button);
677 if (tree_column->window)
679 if (tree_column->resizable)
681 gdk_window_show (tree_column->window);
682 gdk_window_raise (tree_column->window);
686 gdk_window_hide (tree_column->window);
692 gtk_widget_hide (tree_column->button);
693 if (tree_column->window)
694 gdk_window_hide (tree_column->window);
698 if (tree_column->reorderable || tree_column->clickable)
700 GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
704 GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
705 if (GTK_WIDGET_HAS_FOCUS (tree_column->button))
707 GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
708 if (GTK_WIDGET_TOPLEVEL (toplevel))
710 gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
715 gtk_tree_view_column_cell_set_dirty (tree_column);
718 /* Button signal handlers
722 gtk_tree_view_column_button_event (GtkWidget *widget,
726 GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
728 g_return_val_if_fail (event != NULL, FALSE);
730 if (event->type == GDK_BUTTON_PRESS &&
733 column->maybe_reordered = TRUE;
734 gdk_window_get_pointer (widget->window,
738 gtk_widget_grab_focus (widget);
741 if (event->type == GDK_BUTTON_RELEASE &&
742 column->maybe_reordered)
743 column->maybe_reordered = FALSE;
745 if (event->type == GDK_MOTION_NOTIFY &&
746 (column->maybe_reordered) &&
747 (gtk_drag_check_threshold (widget,
750 (gint) ((GdkEventMotion *)event)->x,
751 (gint) ((GdkEventMotion *)event)->y)))
753 column->maybe_reordered = FALSE;
754 _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
757 if (column->clickable == FALSE)
761 case GDK_BUTTON_PRESS:
762 case GDK_2BUTTON_PRESS:
763 case GDK_3BUTTON_PRESS:
764 case GDK_MOTION_NOTIFY:
765 case GDK_BUTTON_RELEASE:
766 case GDK_ENTER_NOTIFY:
767 case GDK_LEAVE_NOTIFY:
777 gtk_tree_view_column_button_realize (GtkWidget *widget, gpointer data)
779 gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | GDK_POINTER_MOTION_MASK);
783 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
785 g_signal_emit_by_name (G_OBJECT (data), "clicked");
789 gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
790 GtkTreeViewColumn *column)
795 if (gtk_tree_sortable_get_sort_column_id (sortable,
799 if (sort_column_id == column->sort_column_id)
801 gtk_tree_view_column_set_sort_indicator (column, TRUE);
802 gtk_tree_view_column_set_sort_order (column, order);
806 gtk_tree_view_column_set_sort_indicator (column, FALSE);
811 gtk_tree_view_column_set_sort_indicator (column, FALSE);
816 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
821 gboolean has_sort_column;
822 gboolean has_default_sort_func;
824 g_return_if_fail (tree_column->tree_view != NULL);
827 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
830 has_default_sort_func =
831 gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model));
833 if (has_sort_column &&
834 sort_column_id == tree_column->sort_column_id)
836 if (order == GTK_SORT_ASCENDING)
837 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
838 tree_column->sort_column_id,
839 GTK_SORT_DESCENDING);
840 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
841 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
842 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
845 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
846 tree_column->sort_column_id,
851 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
852 tree_column->sort_column_id,
859 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
863 if (tree_column->tree_view == NULL)
866 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
871 if (GTK_IS_TREE_SORTABLE (model) &&
872 tree_column->sort_column_id != -1)
874 gint real_sort_column_id;
875 GtkSortType real_order;
877 if (tree_column->sort_column_changed_signal == 0)
878 tree_column->sort_column_changed_signal =
879 g_signal_connect (G_OBJECT (model), "sort_column_changed",
880 GTK_SIGNAL_FUNC (gtk_tree_view_model_sort_column_changed),
883 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
884 &real_sort_column_id,
886 (real_sort_column_id == tree_column->sort_column_id))
888 gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
889 gtk_tree_view_column_set_sort_order (tree_column, real_order);
897 /* Exported Private Functions.
898 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
902 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
904 GtkTreeView *tree_view;
906 guint attributes_mask;
908 tree_view = (GtkTreeView *)column->tree_view;
910 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
911 g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
912 g_return_if_fail (tree_view->priv->header_window != NULL);
913 g_return_if_fail (column->button != NULL);
915 gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
918 gtk_widget_show (column->button);
920 attr.window_type = GDK_WINDOW_CHILD;
921 attr.wclass = GDK_INPUT_ONLY;
922 attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
923 attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
924 attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view));
925 attr.event_mask = (GDK_BUTTON_PRESS_MASK |
926 GDK_BUTTON_RELEASE_MASK |
927 GDK_POINTER_MOTION_MASK |
928 GDK_POINTER_MOTION_HINT_MASK |
930 attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
931 attr.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
934 attr.width = TREE_VIEW_DRAG_WIDTH;
935 attr.height = tree_view->priv->header_height;
937 attr.x = (column->button->allocation.x + column->button->allocation.width) - 3;
939 column->window = gdk_window_new (tree_view->priv->header_window,
940 &attr, attributes_mask);
941 gdk_window_set_user_data (column->window, tree_view);
943 gtk_tree_view_column_update_button (column);
945 gdk_cursor_unref (attr.cursor);
949 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
951 g_return_if_fail (column != NULL);
952 g_return_if_fail (column->window != NULL);
954 gdk_window_set_user_data (column->window, NULL);
955 gdk_window_destroy (column->window);
956 column->window = NULL;
960 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
961 GtkTreeView *tree_view)
963 g_assert (column->tree_view == NULL);
965 column->tree_view = GTK_WIDGET (tree_view);
966 gtk_tree_view_column_create_button (column);
968 column->property_changed_signal =
969 g_signal_connect_swapped (GTK_OBJECT (tree_view),
971 GTK_SIGNAL_FUNC (gtk_tree_view_column_setup_sort_column_id_callback),
974 gtk_tree_view_column_setup_sort_column_id_callback (column);
978 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
980 if (column->tree_view && column->button)
982 gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
984 if (column->property_changed_signal)
986 g_signal_handler_disconnect (G_OBJECT (column->tree_view), column->property_changed_signal);
987 column->property_changed_signal = 0;
990 if (column->sort_column_changed_signal)
992 g_signal_handler_disconnect (G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view))),
993 column->sort_column_changed_signal);
994 column->sort_column_changed_signal = 0;
997 column->tree_view = NULL;
998 column->button = NULL;
1002 _gtk_tree_view_column_set_width (GtkTreeViewColumn *tree_column,
1005 if (tree_column->min_width != -1 &&
1006 width <= tree_column->min_width)
1007 width = tree_column->min_width;
1008 else if (tree_column->max_width != -1 &&
1009 width > tree_column->max_width)
1010 width = tree_column->max_width;
1012 if (tree_column->width == width)
1015 tree_column->width = width;
1017 g_object_notify (G_OBJECT (tree_column), "width");
1019 if (tree_column->tree_view != NULL)
1020 gtk_widget_queue_resize (tree_column->tree_view);
1024 /* Public Functions */
1028 * gtk_tree_view_column_new:
1030 * Creates a new #GtkTreeViewColumn.
1032 * Return value: A newly created #GtkTreeViewColumn.
1035 gtk_tree_view_column_new (void)
1037 GtkTreeViewColumn *tree_column;
1039 tree_column = GTK_TREE_VIEW_COLUMN (gtk_type_new (GTK_TYPE_TREE_VIEW_COLUMN));
1045 * gtk_tree_view_column_new_with_attributes:
1046 * @title: The title to set the header to.
1047 * @cell: The #GtkCellRenderer.
1048 * @Varargs: A NULL terminated list of attributes.
1050 * Creates a new #GtkTreeViewColumn with a number of default values. This is
1051 * equivalent to calling @gtk_tree_view_column_set_title,
1052 * @gtk_tree_view_column_pack_start, and
1053 * @gtk_tree_view_column_set_attributes on the newly created #GtkTreeViewColumn.
1055 * Return value: A newly created #GtkTreeViewColumn.
1058 gtk_tree_view_column_new_with_attributes (const gchar *title,
1059 GtkCellRenderer *cell,
1062 GtkTreeViewColumn *retval;
1065 retval = gtk_tree_view_column_new ();
1067 gtk_tree_view_column_set_title (retval, title);
1068 gtk_tree_view_column_pack_start (retval, cell, TRUE);
1070 va_start (args, cell);
1071 gtk_tree_view_column_set_attributesv (retval, cell, args);
1077 static GtkTreeViewColumnCellInfo *
1078 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1079 GtkCellRenderer *cell_renderer)
1082 for (list = tree_column->cell_list; list; list = list->next)
1083 if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1084 return (GtkTreeViewColumnCellInfo *) list->data;
1090 * gtk_tree_view_column_pack_start:
1091 * @tree_column: A #GtkTreeViewColumn.
1092 * @cell: The #GtkCellRenderer,
1093 * @expand: TRUE if @cell is to be given extra space allocated to box.
1097 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1098 GtkCellRenderer *cell,
1101 GtkTreeViewColumnCellInfo *cell_info;
1103 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1104 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1105 g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1107 g_object_ref (G_OBJECT (cell));
1108 gtk_object_sink (GTK_OBJECT (cell));
1110 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
1111 cell_info->cell = cell;
1112 cell_info->expand = expand ? TRUE : FALSE;
1113 cell_info->pack = GTK_PACK_START;
1114 cell_info->has_focus = 0;
1115 cell_info->attributes = NULL;
1117 tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1121 gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
1122 GtkCellRenderer *cell,
1125 GtkTreeViewColumnCellInfo *cell_info;
1127 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1128 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1129 g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1131 g_object_ref (G_OBJECT (cell));
1132 gtk_object_sink (GTK_OBJECT (cell));
1134 cell_info = g_new (GtkTreeViewColumnCellInfo, 1);
1135 cell_info->cell = cell;
1136 cell_info->expand = expand ? TRUE : FALSE;
1137 cell_info->pack = GTK_PACK_END;
1138 cell_info->has_focus = 0;
1139 cell_info->attributes = NULL;
1141 tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1146 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1149 g_return_if_fail (tree_column != NULL);
1151 for (list = tree_column->cell_list; list; list = list->next)
1153 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1155 g_object_unref (G_OBJECT (info->cell));
1156 gtk_tree_view_column_clear_attributes (tree_column, info->cell);
1160 g_list_free (tree_column->cell_list);
1161 tree_column->cell_list = NULL;
1165 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1167 GList *retval = NULL, *list;
1169 g_return_val_if_fail (tree_column != NULL, NULL);
1171 for (list = tree_column->cell_list; list; list = list->next)
1173 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1175 retval = g_list_append (retval, info->cell);
1182 * gtk_tree_view_column_add_attribute:
1183 * @tree_column: A #GtkTreeViewColumn.
1184 * @cell_renderer: the #GtkCellRenderer to set attributes on
1185 * @attribute: An attribute on the renderer
1186 * @column: The column position on the model to get the attribute from.
1188 * Adds an attribute mapping to the list in @tree_column. The @column is the
1189 * column of the model to get a value from, and the @attribute is the
1190 * parameter on @cell_renderer to be set from the value. So for example
1191 * if column 2 of the model contains strings, you could have the
1192 * "text" attribute of a #GtkCellRendererText get its values from
1196 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1197 GtkCellRenderer *cell_renderer,
1198 const gchar *attribute,
1201 GtkTreeViewColumnCellInfo *info;
1203 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1204 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1205 g_return_if_fail (info != NULL);
1207 info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
1208 info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
1210 if (tree_column->tree_view)
1211 gtk_tree_view_column_cell_set_dirty (tree_column);
1216 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1217 GtkCellRenderer *cell_renderer,
1223 attribute = va_arg (args, gchar *);
1225 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1227 while (attribute != NULL)
1229 column = va_arg (args, gint);
1230 gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1231 attribute = va_arg (args, gchar *);
1236 * gtk_tree_view_column_set_attributes:
1237 * @tree_column: A #GtkTreeViewColumn.
1238 * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1239 * @Varargs: A NULL terminated listing of attributes.
1241 * Sets the attributes in the list as the attributes of @tree_column.
1242 * The attributes should be in attribute/column order, as in
1243 * @gtk_tree_view_column_add_attribute. All existing attributes
1244 * are removed, and replaced with the new attributes.
1247 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1248 GtkCellRenderer *cell_renderer,
1253 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1254 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1255 g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1257 va_start (args, cell_renderer);
1258 gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1264 * gtk_tree_view_column_set_cell_data_func:
1265 * @tree_column: A #GtkTreeViewColumn
1266 * @cell_renderer: A #GtkCellRenderer
1267 * @func: The #GtkTreeViewColumnFunc to use.
1268 * @func_data: The user data for @func.
1269 * @destroy: The destroy notification for @func_data
1271 * Sets the #GtkTreeViewColumnFunc to use for the column. This
1272 * function is used instead of the standard attributes mapping for
1273 * setting the column value, and should set the value of @tree_column's
1274 * cell renderer as appropriate. @func may be NULL to remove an
1278 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
1279 GtkCellRenderer *cell_renderer,
1280 GtkTreeCellDataFunc func,
1282 GtkDestroyNotify destroy)
1284 GtkTreeViewColumnCellInfo *info;
1286 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1287 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1288 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1290 g_return_if_fail (info != NULL);
1292 if (func == info->func &&
1293 func_data == info->func_data &&
1294 destroy == info->destroy)
1297 if (info->func_data && info->destroy)
1298 (info->destroy) (info->func_data);
1301 info->func_data = func_data;
1302 info->destroy = destroy;
1304 if (tree_column->tree_view)
1305 gtk_tree_view_column_cell_set_dirty (tree_column);
1310 * gtk_tree_view_column_clear_attributes:
1311 * @tree_column: a #GtkTreeViewColumn
1312 *@cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1314 * Clears all existing attributes previously set with
1315 * gtk_tree_view_column_set_attributes().
1318 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1319 GtkCellRenderer *cell_renderer)
1321 GtkTreeViewColumnCellInfo *info;
1324 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1325 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1326 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1328 list = info->attributes;
1330 while (list && list->next)
1332 g_free (list->data);
1333 list = list->next->next;
1335 g_slist_free (info->attributes);
1336 info->attributes = NULL;
1338 if (tree_column->tree_view)
1339 gtk_tree_view_column_cell_set_dirty (tree_column);
1344 * gtk_tree_view_column_set_spacing:
1345 * @tree_column: A #GtkTreeViewColumn.
1346 * @spacing: distance between cell renderers in pixels.
1348 * Sets the spacing field of @tree_column, which is the number of pixels to
1349 * place between cell renderers packed into it.
1352 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1355 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1356 g_return_if_fail (spacing >= 0);
1358 if (tree_column->spacing == spacing)
1361 tree_column->spacing = spacing;
1362 if (tree_column->tree_view)
1363 gtk_tree_view_column_cell_set_dirty (tree_column);
1367 * gtk_tree_view_column_get_spacing:
1368 * @tree_column: A #GtkTreeViewColumn.
1370 * Returns the spacing of @tree_column.
1373 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1375 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1377 return tree_column->spacing;
1380 /* Options for manipulating the columns */
1383 * gtk_tree_view_column_set_visible:
1384 * @tree_column: A #GtkTreeViewColumn.
1385 * @visible: TRUE if the @tree_column is visible.
1387 * Sets the visibility of @tree_column.
1390 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1393 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1395 visible = !! visible;
1397 if (tree_column->visible == visible)
1400 tree_column->visible = visible;
1402 gtk_tree_view_column_update_button (tree_column);
1403 g_object_notify (G_OBJECT (tree_column), "visible");
1407 * gtk_tree_view_column_get_visible:
1408 * @tree_column: A #GtkTreeViewColumn.
1410 * Returns TRUE if @tree_column is visible.
1412 * Return value: whether the column is visible or not. If it is visible, then
1413 * the tree will show the column.
1416 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1418 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1420 return tree_column->visible;
1424 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1427 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1429 resizable = !! resizable;
1431 if (tree_column->resizable == resizable)
1434 if (resizable && tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1435 gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1437 gtk_tree_view_column_update_button (tree_column);
1439 g_object_notify (G_OBJECT (tree_column), "resizable");
1443 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1445 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1447 return tree_column->resizable;
1452 * gtk_tree_view_column_set_sizing:
1453 * @tree_column: A #GtkTreeViewColumn.
1454 * @type: The #GtkTreeViewColumnSizing.
1456 * Sets the growth behavior of @tree_column to @type.
1459 gtk_tree_view_column_set_sizing (GtkTreeViewColumn *tree_column,
1460 GtkTreeViewColumnSizing type)
1462 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1464 if (type == tree_column->column_type)
1467 if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1468 gtk_tree_view_column_set_resizable (tree_column, FALSE);
1471 /* I was clearly on crack when I wrote this. I'm not sure what's supposed to
1472 * be below so I'll leave it until I figure it out.
1474 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1475 tree_column->requested_width != -1)
1477 gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1480 tree_column->column_type = type;
1482 gtk_tree_view_column_update_button (tree_column);
1484 g_object_notify (G_OBJECT (tree_column), "sizing");
1488 * gtk_tree_view_column_get_sizing:
1489 * @tree_column: A #GtkTreeViewColumn.
1491 * Returns the current type of @tree_column.
1493 * Return value: The type of @tree_column.
1495 GtkTreeViewColumnSizing
1496 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1498 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1500 return tree_column->column_type;
1504 * gtk_tree_view_column_get_width:
1505 * @tree_column: A #GtkTreeViewColumn.
1507 * Returns the current size of the @tree_column in pixels.
1509 * Return value: The current width of the @tree_column.
1512 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1514 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1516 return tree_column->width;
1520 * gtk_tree_view_column_set_fixed_width:
1521 * @tree_column: A #GtkTreeViewColumn.
1522 * @fixed_width: The size to set the @tree_column to. Must be greater than 0.
1524 * Sets the size of the column in pixels. This is meaningful only if the sizing
1525 * type is #GTK_TREE_VIEW_COLUMN_FIXED. In this case, the value is discarded
1526 * as the size of the column is based on the calculated width of the column. The
1527 * width is clamped to the min/max width for the column.
1530 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1533 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1534 g_return_if_fail (fixed_width > 0);
1536 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1539 tree_column->fixed_width = fixed_width;
1540 tree_column->requested_width = fixed_width;
1541 _gtk_tree_view_column_set_width (tree_column, fixed_width);
1545 * gtk_tree_view_column_get_fixed_width:
1546 * @tree_column: a #GtkTreeViewColumn
1548 * Gets the fixed width of the column. This value is only meaning may not be the
1549 * actual width of the column on the screen, just what is requested.
1551 * Return value: the fixed width of the column
1554 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1556 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1558 return tree_column->fixed_width;
1562 * gtk_tree_view_column_set_min_width:
1563 * @tree_column: A #GtkTreeViewColumn.
1564 * @min_width: The minimum width of the column in pixels, or -1.
1566 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
1567 * minimum width is unset.
1570 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1573 gint real_min_width;
1575 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1576 g_return_if_fail (min_width >= -1);
1578 if (min_width == tree_column->min_width)
1581 if (tree_column->tree_view == NULL)
1583 tree_column->min_width = min_width;
1587 real_min_width = (tree_column->min_width == -1) ?
1588 tree_column->button->requisition.width : tree_column->min_width;
1590 /* We want to queue a resize if the either the old min_size or the
1591 * new min_size determined the size of the column */
1592 if (GTK_WIDGET_REALIZED (tree_column->tree_view))
1594 if ((tree_column->min_width > tree_column->width) ||
1595 (tree_column->min_width == -1 &&
1596 tree_column->button->requisition.width > tree_column->width) ||
1597 (min_width > tree_column->width) ||
1599 tree_column->button->requisition.width > tree_column->width))
1600 gtk_widget_queue_resize (tree_column->tree_view);
1603 if (tree_column->max_width != -1 && tree_column->max_width < real_min_width)
1604 tree_column->max_width = real_min_width;
1606 tree_column->min_width = min_width;
1608 g_object_notify (G_OBJECT (tree_column), "min_width");
1612 * gtk_tree_view_column_get_min_width:
1613 * @tree_column: A #GtkTreeViewColumn.
1615 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
1618 * Return value: The minimum width of the @tree_column.
1621 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
1623 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1625 return tree_column->min_width;
1629 * gtk_tree_view_column_set_max_width:
1630 * @tree_column: A #GtkTreeViewColumn.
1631 * @max_width: The maximum width of the column in pixels, or -1.
1633 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
1634 * maximum width is unset. Note, the column can actually be wider than max
1635 * width if it's the last column in a view. In this case, the column expands to
1639 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
1642 gint real_max_width;
1644 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1645 g_return_if_fail (max_width >= -1);
1647 if (max_width == tree_column->max_width)
1650 if (tree_column->tree_view == NULL)
1652 tree_column->max_width = max_width;
1656 real_max_width = tree_column->max_width == -1 ?
1657 tree_column->button->requisition.width : tree_column->max_width;
1659 if (tree_column->tree_view &&
1660 GTK_WIDGET_REALIZED (tree_column->tree_view) &&
1661 ((tree_column->max_width < tree_column->width) ||
1662 (max_width != -1 && max_width < tree_column->width)))
1663 gtk_widget_queue_resize (tree_column->tree_view);
1665 tree_column->max_width = max_width;
1667 if (real_max_width > max_width)
1668 tree_column->max_width = max_width;
1670 g_object_notify (G_OBJECT (tree_column), "max_width");
1674 * gtk_tree_view_column_get_max_width:
1675 * @tree_column: A #GtkTreeViewColumn.
1677 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
1680 * Return value: The maximum width of the @tree_column.
1683 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
1685 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1687 return tree_column->max_width;
1691 * gtk_tree_view_column_clicked:
1692 * @tree_column: a #GtkTreeViewColumn
1694 * Emits the "clicked" signal on the column. This function will only work if
1695 * the user could have conceivably clicked on the button.
1698 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
1700 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1702 if (tree_column->visible &&
1703 tree_column->button &&
1704 tree_column->clickable)
1705 gtk_button_clicked (GTK_BUTTON (tree_column->button));
1709 * gtk_tree_view_column_set_title:
1710 * @tree_column: A #GtkTreeViewColumn.
1711 * @title: The title of the @tree_column.
1713 * Sets the title of the @tree_column. If a custom widget has been set, then
1714 * this value is ignored.
1717 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
1720 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1722 g_free (tree_column->title);
1724 tree_column->title = g_strdup (title);
1726 tree_column->title = NULL;
1728 gtk_tree_view_column_update_button (tree_column);
1729 g_object_notify (G_OBJECT (tree_column), "title");
1733 * gtk_tree_view_column_get_title:
1734 * @tree_column: A #GtkTreeViewColumn.
1736 * Returns the title of the widget. This value should not be modified.
1738 * Return value: the title of the column.
1740 G_CONST_RETURN gchar *
1741 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
1743 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1745 return tree_column->title;
1749 * gtk_tree_view_column_set_clickable:
1750 * @tree_column: A #GtkTreeViewColumn.
1751 * @clickable: TRUE if the header is active.
1753 * Sets the header to be active if @active is TRUE. When the header is active,
1754 * then it can take keyboard focus, and can be clicked.
1757 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
1760 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1762 if (tree_column->clickable == (clickable?TRUE:FALSE))
1765 tree_column->clickable = (clickable?TRUE:FALSE);
1766 gtk_tree_view_column_update_button (tree_column);
1767 g_object_notify (G_OBJECT (tree_column), "clickable");
1771 * gtk_tree_view_column_get_clickable:
1772 * @tree_column: a #GtkTreeViewColumn
1774 * Returns %TRUE if the user can click on the header for the column.
1776 * Return value: whether the user can click the column header
1779 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1781 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1783 return tree_column->clickable;
1787 * gtk_tree_view_column_set_widget:
1788 * @tree_column: A #GtkTreeViewColumn.
1789 * @widget: A child #GtkWidget, or NULL.
1791 * Sets the widget in the header to be @widget. If widget is NULL, then the
1792 * header button is set with a #GtkLabel set to the title of @tree_column.
1795 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1798 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1799 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1803 gtk_object_ref (GTK_OBJECT (widget));
1804 gtk_object_sink (GTK_OBJECT (widget));
1807 if (tree_column->child)
1808 gtk_object_unref (GTK_OBJECT (tree_column->child));
1810 tree_column->child = widget;
1811 gtk_tree_view_column_update_button (tree_column);
1812 g_object_notify (G_OBJECT (tree_column), "widget");
1816 * gtk_tree_view_column_get_widget:
1817 * @tree_column: A #GtkTreeViewColumn.
1819 * Returns the #GtkWidget in the button in the column header. If a custom
1820 * widget has not been set, then this will be a #GtkAlignment with a #GtkLabel
1823 * Return value: The #GtkWidget in the column header.
1826 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1828 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1830 return tree_column->child;
1834 * gtk_tree_view_column_set_alignment:
1835 * @tree_column: A #GtkTreeViewColumn.
1836 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
1838 * Sets the alignment of the title or custom widget inside the column header.
1839 * The alignment determines its location inside the button -- 0.0 for left, 0.5
1840 * for center, 1.0 for right.
1843 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
1846 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1848 xalign = CLAMP (xalign, 0.0, 1.0);
1850 if (tree_column->xalign == xalign)
1853 tree_column->xalign = xalign;
1854 gtk_tree_view_column_update_button (tree_column);
1855 g_object_notify (G_OBJECT (tree_column), "alignment");
1859 * gtk_tree_view_column_get_alignment:
1860 * @tree_column: A #GtkTreeViewColumn.
1862 * Returns the current x alignment of @tree_column. This value can range
1863 * between 0.0 and 1.0.
1865 * Return value: The current alignent of @tree_column.
1868 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
1870 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
1872 return tree_column->xalign;
1876 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
1877 gboolean reorderable)
1879 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1882 gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
1884 if (tree_column->reorderable == (reorderable?TRUE:FALSE))
1887 tree_column->reorderable = (reorderable?TRUE:FALSE);
1888 gtk_tree_view_column_update_button (tree_column);
1889 g_object_notify (G_OBJECT (tree_column), "reorderable");
1893 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
1895 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1897 return tree_column->reorderable;
1902 * gtk_tree_view_column_set_sort_column_id:
1903 * @tree_column: a #GtkTreeViewColumn
1904 * @sort_column_id: The sort_column_id of the model to sort on.
1906 * Sets the logical sort_column_id that this column sorts on when this column is
1907 * selected for sorting. Doing so makes the column header clickable.
1910 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
1911 gint sort_column_id)
1913 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1914 g_return_if_fail (sort_column_id >= 0);
1916 if (tree_column->sort_column_id == sort_column_id)
1919 tree_column->sort_column_id = sort_column_id;
1921 /* Handle unsetting the id */
1922 if (sort_column_id == -1)
1924 if (tree_column->sort_clicked_signal)
1926 g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal);
1927 tree_column->sort_clicked_signal = 0;
1930 if (tree_column->sort_column_changed_signal)
1932 g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_column_changed_signal);
1933 tree_column->sort_column_changed_signal = 0;
1936 gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
1937 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1941 gtk_tree_view_column_set_clickable (tree_column, TRUE);
1943 if (! tree_column->sort_clicked_signal)
1944 tree_column->sort_clicked_signal = g_signal_connect (G_OBJECT (tree_column),
1946 G_CALLBACK (gtk_tree_view_column_sort),
1949 gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
1953 * gtk_tree_view_column_get_sort_column_id:
1954 * @tree_column: a #GtkTreeViewColumn
1956 * Gets the logical sort_column_id that the model sorts on when this
1957 * coumn is selected for sorting. See gtk_tree_view_column_set_sort_column_id().
1959 * Return value: the current sort_column_id for this column, or -1 if
1960 * this column can't be used for sorting.
1963 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
1965 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1967 return tree_column->sort_column_id;
1971 * gtk_tree_view_column_set_sort_indicator:
1972 * @tree_column: a #GtkTreeViewColumn
1973 * @setting: %TRUE to display an indicator that the column is sorted
1975 * Call this function with a @setting of %TRUE to display an arrow in
1976 * the header button indicating the column is sorted. Call
1977 * gtk_tree_view_column_set_sort_order() to change the direction of
1982 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
1985 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1987 setting = setting != FALSE;
1989 if (setting == tree_column->show_sort_indicator)
1992 tree_column->show_sort_indicator = setting;
1993 gtk_tree_view_column_update_button (tree_column);
1994 g_object_notify (G_OBJECT (tree_column), "sort_indicator");
1998 * gtk_tree_view_column_get_sort_indicator:
1999 * @tree_column: a #GtkTreeViewColumn
2001 * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2003 * Return value: whether the sort indicator arrow is displayed
2006 gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
2008 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2010 return tree_column->show_sort_indicator;
2014 * gtk_tree_view_column_set_sort_order:
2015 * @tree_column: a #GtkTreeViewColumn
2016 * @order: sort order that the sort indicator should indicate
2018 * Changes the appearance of the sort indicator.
2020 * This <emphasis>does not</emphasis> actually sort the model. Use
2021 * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2022 * support. This function is primarily for custom sorting behavior, and should
2023 * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2024 * that. For custom models, the mechanism will vary.
2026 * The sort indicator changes direction to indicate normal sort or reverse sort.
2027 * Note that you must have the sort indicator enabled to see anything when
2028 * calling this function; see gtk_tree_view_column_set_sort_indicator().
2031 gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
2034 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2036 if (order == tree_column->sort_order)
2039 tree_column->sort_order = order;
2040 gtk_tree_view_column_update_button (tree_column);
2041 g_object_notify (G_OBJECT (tree_column), "sort_order");
2045 * gtk_tree_view_column_get_sort_order:
2046 * @tree_column: a #GtkTreeViewColumn
2048 * Gets the value set by gtk_tree_view_column_set_sort_order().
2050 * Return value: the sort order the sort indicator is indicating
2053 gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
2055 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2057 return tree_column->sort_order;
2061 * gtk_tree_view_column_cell_set_cell_data:
2062 * @tree_column: A #GtkTreeViewColumn.
2063 * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2064 * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2065 * @is_expander: TRUE, if the row has children
2066 * @is_expanded: TRUE, if the row has visible children
2068 * Sets the cell renderer based on the @tree_model and @tree_node. That is, for
2069 * every attribute mapping in @tree_column, it will get a value from the set
2070 * column on the @tree_node, and use that value to set the attribute on the cell
2071 * renderer. This is used primarily by the GtkTreeView.
2074 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2075 GtkTreeModel *tree_model,
2077 gboolean is_expander,
2078 gboolean is_expanded)
2081 GValue value = { 0, };
2084 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2085 g_return_if_fail (tree_column->cell_list != NULL);
2087 if (tree_model == NULL)
2090 for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2092 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2093 GObject *cell = (GObject *) info->cell;
2095 list = info->attributes;
2097 g_object_freeze_notify (cell);
2098 g_object_set (cell, "is_expander", is_expander, "is_expanded", is_expanded, NULL);
2100 while (list && list->next)
2102 gtk_tree_model_get_value (tree_model, iter,
2103 GPOINTER_TO_INT (list->next->data),
2105 g_object_set_property (cell, (gchar *) list->data, &value);
2106 g_value_unset (&value);
2107 list = list->next->next;
2111 (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2112 g_object_thaw_notify (G_OBJECT (info->cell));
2118 * gtk_tree_view_column_cell_get_size:
2119 * @tree_column: A #GtkTreeViewColumn.
2120 * @cell_area: The area a the column will be allocated, or %NULL
2121 * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
2122 * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
2123 * @width: location to return width needed to render a cell, or %NULL
2124 * @height: location to return height needed to render a cell, or %NULL
2126 * Obtains the width and height needed to render the column. This is used
2127 * primarily by the GtkTreeView.
2130 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2131 GdkRectangle *cell_area,
2138 gboolean first_cell = TRUE;
2140 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2147 for (list = tree_column->cell_list; list; list = list->next)
2149 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2151 gint new_height = 0;
2153 g_object_get (info->cell, "visible", &visible, NULL);
2155 if (visible == FALSE)
2158 if (first_cell == FALSE && *width)
2159 *width += tree_column->spacing;
2161 gtk_cell_renderer_get_size (info->cell,
2162 tree_column->tree_view,
2170 * height = MAX (*height, new_height);
2171 info->requested_width = MAX (info->requested_width, new_width);
2173 * width += info->requested_width;
2178 /* both rendering and rendering focus are somewhat complicated, and a bit of
2179 * code. Rather than duplicate them, we put them together to keep the code in
2183 gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
2185 GdkRectangle *background_area,
2186 GdkRectangle *cell_area,
2187 GdkRectangle *expose_area,
2190 GdkRectangle *focus_rectangle)
2193 GdkRectangle real_cell_area;
2194 gint expand_cell_count = 0;
2195 gint full_requested_width = 0;
2197 gint min_x, min_y, max_x, max_y;
2204 real_cell_area = *cell_area;
2206 /* Find out how my extra space we have to allocate */
2207 for (list = tree_column->cell_list; list; list = list->next)
2209 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2212 g_object_get (info->cell, "visible", &visible, NULL);
2213 if (visible == FALSE)
2216 if (info->expand == TRUE)
2217 expand_cell_count ++;
2218 full_requested_width += info->requested_width;
2221 extra_space = cell_area->width - full_requested_width;
2222 if (extra_space < 0)
2225 for (list = tree_column->cell_list; list; list = list->next)
2227 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2230 if (info->pack == GTK_PACK_END)
2233 g_object_get (info->cell, "visible", &visible, NULL);
2234 if (visible == FALSE)
2237 real_cell_area.width = info->requested_width +
2238 (info->expand?extra_space:0);
2241 gtk_cell_renderer_render (info->cell,
2243 tree_column->tree_view,
2251 gint x_offset, y_offset, width, height;
2253 gtk_cell_renderer_get_size (info->cell,
2254 tree_column->tree_view,
2256 &x_offset, &y_offset,
2259 if (min_x > (real_cell_area.x + x_offset))
2260 min_x = real_cell_area.x + x_offset;
2261 if (max_x < real_cell_area.x + x_offset + width)
2262 max_x = real_cell_area.x + x_offset + width;
2263 if (min_y > (real_cell_area.y + y_offset))
2264 min_y = real_cell_area.y + y_offset;
2265 if (max_y < real_cell_area.y + y_offset + height)
2266 max_y = real_cell_area.y + y_offset + height;
2268 real_cell_area.x += (info->requested_width + tree_column->spacing);
2270 for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2272 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2275 if (info->pack == GTK_PACK_START)
2278 g_object_get (info->cell, "visible", &visible, NULL);
2279 if (visible == FALSE)
2282 real_cell_area.width = info->requested_width +
2283 (info->expand?extra_space:0);
2284 gtk_cell_renderer_render (info->cell,
2286 tree_column->tree_view,
2291 real_cell_area.x += (info->requested_width + tree_column->spacing);
2295 if (min_x >= max_x || min_y >= max_y)
2297 *focus_rectangle = *cell_area;
2298 focus_rectangle->x -= 1;
2299 focus_rectangle->y -= 1;
2300 focus_rectangle->width += 2;
2301 focus_rectangle->height += 2;
2305 focus_rectangle->x = min_x - 1;
2306 focus_rectangle->y = min_y - 1;
2307 focus_rectangle->width = (max_x - min_x) + 2;
2308 focus_rectangle->height = (max_y - min_y) + 2;
2314 * gtk_tree_view_column_cell_render:
2315 * @tree_column: A #GtkTreeViewColumn.
2316 * @window: a #GdkDrawable to draw to
2317 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2318 * @cell_area: area normally rendered by a cell renderer
2319 * @expose_area: area that actually needs updating
2320 * @flags: flags that affect rendering
2322 * Renders the cell contained by #tree_column. This is used primarily by the
2326 gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
2328 GdkRectangle *background_area,
2329 GdkRectangle *cell_area,
2330 GdkRectangle *expose_area,
2333 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2334 g_return_if_fail (background_area != NULL);
2335 g_return_if_fail (cell_area != NULL);
2336 g_return_if_fail (expose_area != NULL);
2338 gtk_tree_view_column_cell_render_or_focus (tree_column,
2349 _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
2350 GtkCellEditable **editable_widget,
2353 GdkRectangle *background_area,
2354 GdkRectangle *cell_area,
2357 gboolean visible, mode;
2359 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2361 g_object_get (G_OBJECT (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell),
2362 "visible", &visible,
2365 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2367 if (gtk_cell_renderer_activate (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2369 tree_column->tree_view,
2376 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2378 *editable_widget = gtk_cell_renderer_start_editing (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2380 tree_column->tree_view,
2386 if (*editable_widget != NULL)
2388 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2398 gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
2401 if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
2407 gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column,
2409 GdkRectangle *background_area,
2410 GdkRectangle *cell_area,
2411 GdkRectangle *expose_area,
2414 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2415 if (tree_column->editable_widget)
2417 /* This function is only called on the editable row when editing.
2420 gtk_paint_focus (tree_column->tree_view->style,
2422 GTK_WIDGET_STATE (tree_column->tree_view),
2424 tree_column->tree_view,
2428 cell_area->width + 2,
2429 cell_area->height + 2);
2434 GdkRectangle focus_rectangle;
2435 gtk_tree_view_column_cell_render_or_focus (tree_column,
2444 gtk_paint_focus (tree_column->tree_view->style,
2446 GTK_WIDGET_STATE (tree_column->tree_view),
2448 tree_column->tree_view,
2452 focus_rectangle.width,
2453 focus_rectangle.height);
2458 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2462 for (list = tree_column->cell_list; list; list = list->next)
2464 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2467 g_object_get (G_OBJECT (info->cell), "visible", &visible, NULL);
2477 gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column)
2481 for (list = tree_column->cell_list; list; list = list->next)
2483 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2485 info->requested_width = 0;
2487 tree_column->dirty = TRUE;
2489 if (tree_column->tree_view)
2490 gtk_widget_queue_resize (tree_column->tree_view);
2494 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
2495 GtkCellEditable *cell_editable)
2497 g_return_if_fail (tree_column->editable_widget == NULL);
2499 tree_column->editable_widget = cell_editable;
2503 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
2505 g_return_if_fail (tree_column->editable_widget != NULL);
2507 tree_column->editable_widget = NULL;