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->resized_width = 0;
306 tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
307 tree_column->visible = TRUE;
308 tree_column->resizable = FALSE;
309 tree_column->clickable = FALSE;
310 tree_column->dirty = TRUE;
311 tree_column->sort_order = GTK_SORT_ASCENDING;
312 tree_column->show_sort_indicator = FALSE;
313 tree_column->property_changed_signal = 0;
314 tree_column->sort_clicked_signal = 0;
315 tree_column->sort_column_changed_signal = 0;
316 tree_column->sort_column_id = -1;
317 tree_column->reorderable = FALSE;
318 tree_column->maybe_reordered = FALSE;
319 tree_column->use_resized_width = FALSE;
323 gtk_tree_view_column_finalize (GObject *object)
325 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
328 for (list = tree_column->cell_list; list; list = list->next)
330 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
331 if (info->func_data && info->destroy)
332 (info->destroy) (info->func_data);
333 gtk_tree_view_column_clear_attributes (tree_column, info->cell);
334 g_object_unref (G_OBJECT (info->cell));
338 g_free (tree_column->title);
340 G_OBJECT_CLASS (parent_class)->finalize (object);
344 gtk_tree_view_column_set_property (GObject *object,
349 GtkTreeViewColumn *tree_column;
351 tree_column = GTK_TREE_VIEW_COLUMN (object);
356 gtk_tree_view_column_set_visible (tree_column,
357 g_value_get_boolean (value));
361 gtk_tree_view_column_set_resizable (tree_column,
362 g_value_get_boolean (value));
366 gtk_tree_view_column_set_sizing (tree_column,
367 g_value_get_enum (value));
370 case PROP_FIXED_WIDTH:
371 gtk_tree_view_column_set_fixed_width (tree_column,
372 g_value_get_int (value));
376 gtk_tree_view_column_set_min_width (tree_column,
377 g_value_get_int (value));
381 gtk_tree_view_column_set_max_width (tree_column,
382 g_value_get_int (value));
386 gtk_tree_view_column_set_title (tree_column,
387 g_value_get_string (value));
391 gtk_tree_view_column_set_clickable (tree_column,
392 g_value_get_boolean (value));
396 gtk_tree_view_column_set_widget (tree_column,
397 (GtkWidget*) g_value_get_object (value));
401 gtk_tree_view_column_set_alignment (tree_column,
402 g_value_get_float (value));
405 case PROP_REORDERABLE:
406 gtk_tree_view_column_set_reorderable (tree_column,
407 g_value_get_boolean (value));
410 case PROP_SORT_INDICATOR:
411 gtk_tree_view_column_set_sort_indicator (tree_column,
412 g_value_get_boolean (value));
415 case PROP_SORT_ORDER:
416 gtk_tree_view_column_set_sort_order (tree_column,
417 g_value_get_enum (value));
421 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
427 gtk_tree_view_column_get_property (GObject *object,
432 GtkTreeViewColumn *tree_column;
434 tree_column = GTK_TREE_VIEW_COLUMN (object);
439 g_value_set_boolean (value,
440 gtk_tree_view_column_get_visible (tree_column));
444 g_value_set_boolean (value,
445 gtk_tree_view_column_get_resizable (tree_column));
449 g_value_set_int (value,
450 gtk_tree_view_column_get_width (tree_column));
454 g_value_set_enum (value,
455 gtk_tree_view_column_get_sizing (tree_column));
458 case PROP_FIXED_WIDTH:
459 g_value_set_int (value,
460 gtk_tree_view_column_get_fixed_width (tree_column));
464 g_value_set_int (value,
465 gtk_tree_view_column_get_min_width (tree_column));
469 g_value_set_int (value,
470 gtk_tree_view_column_get_max_width (tree_column));
474 g_value_set_string (value,
475 gtk_tree_view_column_get_title (tree_column));
479 g_value_set_boolean (value,
480 gtk_tree_view_column_get_clickable (tree_column));
484 g_value_set_object (value,
485 (GObject*) gtk_tree_view_column_get_widget (tree_column));
489 g_value_set_float (value,
490 gtk_tree_view_column_get_alignment (tree_column));
493 case PROP_REORDERABLE:
494 g_value_set_boolean (value,
495 gtk_tree_view_column_get_reorderable (tree_column));
498 case PROP_SORT_INDICATOR:
499 g_value_set_boolean (value,
500 gtk_tree_view_column_get_sort_indicator (tree_column));
503 case PROP_SORT_ORDER:
504 g_value_set_enum (value,
505 gtk_tree_view_column_get_sort_order (tree_column));
509 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517 /* Button handling code
520 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
522 GtkTreeView *tree_view;
526 tree_view = (GtkTreeView *) tree_column->tree_view;
528 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
529 g_return_if_fail (tree_column->button == NULL);
531 gtk_widget_push_composite_child ();
532 tree_column->button = gtk_button_new ();
533 gtk_widget_pop_composite_child ();
535 /* make sure we own a reference to it as well. */
536 if (tree_view->priv->header_window)
537 gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
538 gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
540 gtk_signal_connect (GTK_OBJECT (tree_column->button), "realize",
541 (GtkSignalFunc) gtk_tree_view_column_button_realize,
544 gtk_signal_connect (GTK_OBJECT (tree_column->button), "event",
545 (GtkSignalFunc) gtk_tree_view_column_button_event,
546 (gpointer) tree_column);
548 gtk_signal_connect (GTK_OBJECT (tree_column->button), "clicked",
549 (GtkSignalFunc) gtk_tree_view_column_button_clicked,
550 (gpointer) tree_column);
552 tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
554 hbox = gtk_hbox_new (FALSE, 2);
555 tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
557 if (tree_column->child)
558 child = tree_column->child;
561 child = gtk_label_new (tree_column->title);
562 gtk_widget_show (child);
565 if (tree_column->xalign <= 0.5)
566 gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
568 gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
570 gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
572 gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
573 gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
575 gtk_widget_show (hbox);
576 gtk_widget_show (tree_column->alignment);
577 gtk_tree_view_column_update_button (tree_column);
581 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
584 GtkWidget *alignment;
586 GtkWidget *current_child;
588 /* Create a button if necessary */
589 if (tree_column->visible &&
590 tree_column->button == NULL &&
591 tree_column->tree_view &&
592 GTK_WIDGET_REALIZED (tree_column->tree_view))
593 gtk_tree_view_column_create_button (tree_column);
595 if (! tree_column->button)
598 hbox = GTK_BIN (tree_column->button)->child;
599 alignment = tree_column->alignment;
600 arrow = tree_column->arrow;
601 current_child = GTK_BIN (alignment)->child;
603 /* Set up the actual button */
604 gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
607 if (tree_column->child)
609 if (current_child != tree_column->child)
611 gtk_container_remove (GTK_CONTAINER (alignment),
613 gtk_container_add (GTK_CONTAINER (alignment),
619 if (current_child == NULL)
621 current_child = gtk_label_new (NULL);
622 gtk_widget_show (current_child);
623 gtk_container_add (GTK_CONTAINER (alignment),
627 g_return_if_fail (GTK_IS_LABEL (current_child));
629 if (tree_column->title)
630 gtk_label_set_text (GTK_LABEL (current_child),
633 gtk_label_set_text (GTK_LABEL (current_child),
637 switch (tree_column->sort_order)
639 case GTK_SORT_ASCENDING:
640 gtk_arrow_set (GTK_ARROW (arrow),
645 case GTK_SORT_DESCENDING:
646 gtk_arrow_set (GTK_ARROW (arrow),
652 g_warning (G_STRLOC": bad sort order");
656 /* Put arrow on the right if the text is left-or-center justified,
657 * and on the left otherwise; do this by packing boxes, so flipping
658 * text direction will reverse things
660 gtk_widget_ref (arrow);
661 gtk_container_remove (GTK_CONTAINER (hbox), arrow);
663 if (tree_column->xalign <= 0.5)
665 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
669 gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
670 /* move it to the front */
671 gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
673 gtk_widget_unref (arrow);
675 if (tree_column->show_sort_indicator)
676 gtk_widget_show (arrow);
678 gtk_widget_hide (arrow);
680 /* It's always safe to hide the button. It isn't always safe to show it, as if you show it
681 * before it's realized, it'll get the wrong window. */
682 if (tree_column->button &&
683 tree_column->tree_view != NULL &&
684 GTK_WIDGET_REALIZED (tree_column->tree_view))
686 if (tree_column->visible)
688 gtk_widget_show_now (tree_column->button);
689 if (tree_column->window)
691 if (tree_column->resizable)
693 gdk_window_show (tree_column->window);
694 gdk_window_raise (tree_column->window);
698 gdk_window_hide (tree_column->window);
704 gtk_widget_hide (tree_column->button);
705 if (tree_column->window)
706 gdk_window_hide (tree_column->window);
710 if (tree_column->reorderable || tree_column->clickable)
712 GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
716 GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
717 if (GTK_WIDGET_HAS_FOCUS (tree_column->button))
719 GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
720 if (GTK_WIDGET_TOPLEVEL (toplevel))
722 gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
726 /* Queue a resize on the assumption that we always want to catch all changes
727 * and columns don't change all that often.
729 if (GTK_WIDGET_REALIZED (tree_column->tree_view))
730 gtk_widget_queue_resize (tree_column->tree_view);
734 /* Button signal handlers
738 gtk_tree_view_column_button_event (GtkWidget *widget,
742 GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
744 g_return_val_if_fail (event != NULL, FALSE);
746 if (event->type == GDK_BUTTON_PRESS &&
749 column->maybe_reordered = TRUE;
750 gdk_window_get_pointer (widget->window,
754 gtk_widget_grab_focus (widget);
757 if (event->type == GDK_BUTTON_RELEASE &&
758 column->maybe_reordered)
759 column->maybe_reordered = FALSE;
761 if (event->type == GDK_MOTION_NOTIFY &&
762 (column->maybe_reordered) &&
763 (gtk_drag_check_threshold (widget,
766 (gint) ((GdkEventMotion *)event)->x,
767 (gint) ((GdkEventMotion *)event)->y)))
769 column->maybe_reordered = FALSE;
770 _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
773 if (column->clickable == FALSE)
777 case GDK_BUTTON_PRESS:
778 case GDK_2BUTTON_PRESS:
779 case GDK_3BUTTON_PRESS:
780 case GDK_MOTION_NOTIFY:
781 case GDK_BUTTON_RELEASE:
782 case GDK_ENTER_NOTIFY:
783 case GDK_LEAVE_NOTIFY:
793 gtk_tree_view_column_button_realize (GtkWidget *widget, gpointer data)
795 gdk_window_set_events (widget->window, gdk_window_get_events (widget->window) | GDK_POINTER_MOTION_MASK);
799 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
801 g_signal_emit_by_name (G_OBJECT (data), "clicked");
805 gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
806 GtkTreeViewColumn *column)
811 if (gtk_tree_sortable_get_sort_column_id (sortable,
815 if (sort_column_id == column->sort_column_id)
817 gtk_tree_view_column_set_sort_indicator (column, TRUE);
818 gtk_tree_view_column_set_sort_order (column, order);
822 gtk_tree_view_column_set_sort_indicator (column, FALSE);
827 gtk_tree_view_column_set_sort_indicator (column, FALSE);
832 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
837 gboolean has_sort_column;
838 gboolean has_default_sort_func;
840 g_return_if_fail (tree_column->tree_view != NULL);
843 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
846 has_default_sort_func =
847 gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model));
849 if (has_sort_column &&
850 sort_column_id == tree_column->sort_column_id)
852 if (order == GTK_SORT_ASCENDING)
853 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
854 tree_column->sort_column_id,
855 GTK_SORT_DESCENDING);
856 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
857 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
858 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
861 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
862 tree_column->sort_column_id,
867 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
868 tree_column->sort_column_id,
875 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
879 if (tree_column->tree_view == NULL)
882 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
887 if (GTK_IS_TREE_SORTABLE (model) &&
888 tree_column->sort_column_id != -1)
890 gint real_sort_column_id;
891 GtkSortType real_order;
893 if (tree_column->sort_column_changed_signal == 0)
894 tree_column->sort_column_changed_signal =
895 g_signal_connect (G_OBJECT (model), "sort_column_changed",
896 GTK_SIGNAL_FUNC (gtk_tree_view_model_sort_column_changed),
899 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
900 &real_sort_column_id,
902 (real_sort_column_id == tree_column->sort_column_id))
904 gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
905 gtk_tree_view_column_set_sort_order (tree_column, real_order);
913 /* Exported Private Functions.
914 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
918 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
920 GtkTreeView *tree_view;
922 guint attributes_mask;
924 tree_view = (GtkTreeView *)column->tree_view;
926 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
927 g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
928 g_return_if_fail (tree_view->priv->header_window != NULL);
929 g_return_if_fail (column->button != NULL);
931 gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
934 gtk_widget_show (column->button);
936 attr.window_type = GDK_WINDOW_CHILD;
937 attr.wclass = GDK_INPUT_ONLY;
938 attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
939 attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
940 attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view));
941 attr.event_mask = (GDK_BUTTON_PRESS_MASK |
942 GDK_BUTTON_RELEASE_MASK |
943 GDK_POINTER_MOTION_MASK |
944 GDK_POINTER_MOTION_HINT_MASK |
946 attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
947 attr.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
950 attr.width = TREE_VIEW_DRAG_WIDTH;
951 attr.height = tree_view->priv->header_height;
953 attr.x = (column->button->allocation.x + column->button->allocation.width) - 3;
955 column->window = gdk_window_new (tree_view->priv->header_window,
956 &attr, attributes_mask);
957 gdk_window_set_user_data (column->window, tree_view);
959 gtk_tree_view_column_update_button (column);
961 gdk_cursor_unref (attr.cursor);
965 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
967 g_return_if_fail (column != NULL);
968 g_return_if_fail (column->window != NULL);
970 gdk_window_set_user_data (column->window, NULL);
971 gdk_window_destroy (column->window);
972 column->window = NULL;
976 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
977 GtkTreeView *tree_view)
979 g_assert (column->tree_view == NULL);
981 column->tree_view = GTK_WIDGET (tree_view);
982 gtk_tree_view_column_create_button (column);
984 column->property_changed_signal =
985 g_signal_connect_swapped (GTK_OBJECT (tree_view),
987 GTK_SIGNAL_FUNC (gtk_tree_view_column_setup_sort_column_id_callback),
990 gtk_tree_view_column_setup_sort_column_id_callback (column);
994 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
996 if (column->tree_view && column->button)
998 gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
1000 if (column->property_changed_signal)
1002 g_signal_handler_disconnect (G_OBJECT (column->tree_view), column->property_changed_signal);
1003 column->property_changed_signal = 0;
1006 if (column->sort_column_changed_signal)
1008 g_signal_handler_disconnect (G_OBJECT (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view))),
1009 column->sort_column_changed_signal);
1010 column->sort_column_changed_signal = 0;
1013 column->tree_view = NULL;
1014 column->button = NULL;
1017 /* Public Functions */
1021 * gtk_tree_view_column_new:
1023 * Creates a new #GtkTreeViewColumn.
1025 * Return value: A newly created #GtkTreeViewColumn.
1028 gtk_tree_view_column_new (void)
1030 GtkTreeViewColumn *tree_column;
1032 tree_column = GTK_TREE_VIEW_COLUMN (gtk_type_new (GTK_TYPE_TREE_VIEW_COLUMN));
1038 * gtk_tree_view_column_new_with_attributes:
1039 * @title: The title to set the header to.
1040 * @cell: The #GtkCellRenderer.
1041 * @Varargs: A %NULL-terminated list of attributes.
1043 * Creates a new #GtkTreeViewColumn with a number of default values. This is
1044 * equivalent to calling gtk_tree_view_column_set_title(),
1045 * gtk_tree_view_column_pack_start(), and
1046 * gtk_tree_view_column_set_attributes() on the newly created #GtkTreeViewColumn.
1048 * Return value: A newly created #GtkTreeViewColumn.
1051 gtk_tree_view_column_new_with_attributes (const gchar *title,
1052 GtkCellRenderer *cell,
1055 GtkTreeViewColumn *retval;
1058 retval = gtk_tree_view_column_new ();
1060 gtk_tree_view_column_set_title (retval, title);
1061 gtk_tree_view_column_pack_start (retval, cell, TRUE);
1063 va_start (args, cell);
1064 gtk_tree_view_column_set_attributesv (retval, cell, args);
1070 static GtkTreeViewColumnCellInfo *
1071 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1072 GtkCellRenderer *cell_renderer)
1075 for (list = tree_column->cell_list; list; list = list->next)
1076 if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1077 return (GtkTreeViewColumnCellInfo *) list->data;
1083 * gtk_tree_view_column_pack_start:
1084 * @tree_column: A #GtkTreeViewColumn.
1085 * @cell: The #GtkCellRenderer.
1086 * @expand: %TRUE if @cell is to be given extra space allocated to box.
1090 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1091 GtkCellRenderer *cell,
1094 GtkTreeViewColumnCellInfo *cell_info;
1096 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1097 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1098 g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1100 g_object_ref (G_OBJECT (cell));
1101 gtk_object_sink (GTK_OBJECT (cell));
1103 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
1104 cell_info->cell = cell;
1105 cell_info->expand = expand ? TRUE : FALSE;
1106 cell_info->pack = GTK_PACK_START;
1107 cell_info->has_focus = 0;
1108 cell_info->attributes = NULL;
1110 tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1114 gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
1115 GtkCellRenderer *cell,
1118 GtkTreeViewColumnCellInfo *cell_info;
1120 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1121 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
1122 g_return_if_fail (! gtk_tree_view_column_get_cell_info (tree_column, cell));
1124 g_object_ref (G_OBJECT (cell));
1125 gtk_object_sink (GTK_OBJECT (cell));
1127 cell_info = g_new (GtkTreeViewColumnCellInfo, 1);
1128 cell_info->cell = cell;
1129 cell_info->expand = expand ? TRUE : FALSE;
1130 cell_info->pack = GTK_PACK_END;
1131 cell_info->has_focus = 0;
1132 cell_info->attributes = NULL;
1134 tree_column->cell_list = g_list_append (tree_column->cell_list, cell_info);
1139 * gtk_tree_view_column_clear:
1140 * @tree_column: A #GtkTreeViewColumn
1142 * Unsets all the mappings on all renderers on the @tree_column.
1145 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1148 g_return_if_fail (tree_column != NULL);
1150 for (list = tree_column->cell_list; list; list = list->next)
1152 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1154 g_object_unref (G_OBJECT (info->cell));
1155 gtk_tree_view_column_clear_attributes (tree_column, info->cell);
1159 g_list_free (tree_column->cell_list);
1160 tree_column->cell_list = NULL;
1164 * gtk_tree_view_column_get_cell_renderers:
1165 * @tree_column: A #GtkTreeViewColumn
1167 * Returns a newly-allocated #GList of all the cell renderers in the column,
1168 * in no particular order. The list must be freed with g_list_free().
1170 * Return value: A list of #GtkCellRenderers
1173 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1175 GList *retval = NULL, *list;
1177 g_return_val_if_fail (tree_column != NULL, NULL);
1179 for (list = tree_column->cell_list; list; list = list->next)
1181 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1183 retval = g_list_append (retval, info->cell);
1190 * gtk_tree_view_column_add_attribute:
1191 * @tree_column: A #GtkTreeViewColumn.
1192 * @cell_renderer: the #GtkCellRenderer to set attributes on
1193 * @attribute: An attribute on the renderer
1194 * @column: The column position on the model to get the attribute from.
1196 * Adds an attribute mapping to the list in @tree_column. The @column is the
1197 * column of the model to get a value from, and the @attribute is the
1198 * parameter on @cell_renderer to be set from the value. So for example
1199 * if column 2 of the model contains strings, you could have the
1200 * "text" attribute of a #GtkCellRendererText get its values from
1204 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1205 GtkCellRenderer *cell_renderer,
1206 const gchar *attribute,
1209 GtkTreeViewColumnCellInfo *info;
1211 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1212 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1213 g_return_if_fail (info != NULL);
1215 info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
1216 info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
1218 if (tree_column->tree_view)
1219 gtk_tree_view_column_cell_set_dirty (tree_column);
1224 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1225 GtkCellRenderer *cell_renderer,
1231 attribute = va_arg (args, gchar *);
1233 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1235 while (attribute != NULL)
1237 column = va_arg (args, gint);
1238 gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1239 attribute = va_arg (args, gchar *);
1244 * gtk_tree_view_column_set_attributes:
1245 * @tree_column: A #GtkTreeViewColumn.
1246 * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1247 * @Varargs: A %NULL-terminated list of attributes.
1249 * Sets the attributes in the list as the attributes of @tree_column.
1250 * The attributes should be in attribute/column order, as in
1251 * gtk_tree_view_column_add_attribute(). All existing attributes
1252 * are removed, and replaced with the new attributes.
1255 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1256 GtkCellRenderer *cell_renderer,
1261 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1262 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1263 g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1265 va_start (args, cell_renderer);
1266 gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1272 * gtk_tree_view_column_set_cell_data_func:
1273 * @tree_column: A #GtkTreeViewColumn
1274 * @cell_renderer: A #GtkCellRenderer
1275 * @func: The #GtkTreeViewColumnFunc to use.
1276 * @func_data: The user data for @func.
1277 * @destroy: The destroy notification for @func_data
1279 * Sets the #GtkTreeViewColumnFunc to use for the column. This
1280 * function is used instead of the standard attributes mapping for
1281 * setting the column value, and should set the value of @tree_column's
1282 * cell renderer as appropriate. @func may be %NULL to remove an
1286 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
1287 GtkCellRenderer *cell_renderer,
1288 GtkTreeCellDataFunc func,
1290 GtkDestroyNotify destroy)
1292 GtkTreeViewColumnCellInfo *info;
1294 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1295 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1296 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1298 g_return_if_fail (info != NULL);
1300 if (func == info->func &&
1301 func_data == info->func_data &&
1302 destroy == info->destroy)
1305 if (info->func_data && info->destroy)
1306 (info->destroy) (info->func_data);
1309 info->func_data = func_data;
1310 info->destroy = destroy;
1312 if (tree_column->tree_view)
1313 gtk_tree_view_column_cell_set_dirty (tree_column);
1318 * gtk_tree_view_column_clear_attributes:
1319 * @tree_column: a #GtkTreeViewColumn
1320 * @cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1322 * Clears all existing attributes previously set with
1323 * gtk_tree_view_column_set_attributes().
1326 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1327 GtkCellRenderer *cell_renderer)
1329 GtkTreeViewColumnCellInfo *info;
1332 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1333 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1334 info = gtk_tree_view_column_get_cell_info (tree_column, cell_renderer);
1336 list = info->attributes;
1338 while (list && list->next)
1340 g_free (list->data);
1341 list = list->next->next;
1343 g_slist_free (info->attributes);
1344 info->attributes = NULL;
1346 if (tree_column->tree_view)
1347 gtk_tree_view_column_cell_set_dirty (tree_column);
1352 * gtk_tree_view_column_set_spacing:
1353 * @tree_column: A #GtkTreeViewColumn.
1354 * @spacing: distance between cell renderers in pixels.
1356 * Sets the spacing field of @tree_column, which is the number of pixels to
1357 * place between cell renderers packed into it.
1360 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1363 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1364 g_return_if_fail (spacing >= 0);
1366 if (tree_column->spacing == spacing)
1369 tree_column->spacing = spacing;
1370 if (tree_column->tree_view)
1371 gtk_tree_view_column_cell_set_dirty (tree_column);
1375 * gtk_tree_view_column_get_spacing:
1376 * @tree_column: A #GtkTreeViewColumn.
1378 * Returns the spacing of @tree_column.
1380 * Return value: the spacing of @tree_column.
1383 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1385 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1387 return tree_column->spacing;
1390 /* Options for manipulating the columns */
1393 * gtk_tree_view_column_set_visible:
1394 * @tree_column: A #GtkTreeViewColumn.
1395 * @visible: %TRUE if the @tree_column is visible.
1397 * Sets the visibility of @tree_column.
1400 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1403 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1405 visible = !! visible;
1407 if (tree_column->visible == visible)
1410 tree_column->visible = visible;
1412 gtk_tree_view_column_update_button (tree_column);
1413 g_object_notify (G_OBJECT (tree_column), "visible");
1417 * gtk_tree_view_column_get_visible:
1418 * @tree_column: A #GtkTreeViewColumn.
1420 * Returns %TRUE if @tree_column is visible.
1422 * Return value: whether the column is visible or not. If it is visible, then
1423 * the tree will show the column.
1426 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1428 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1430 return tree_column->visible;
1434 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1437 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1439 resizable = !! resizable;
1441 if (tree_column->resizable == resizable)
1444 tree_column->resizable = resizable;
1446 if (resizable && tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1447 gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1449 gtk_tree_view_column_update_button (tree_column);
1451 g_object_notify (G_OBJECT (tree_column), "resizable");
1455 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1457 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1459 return tree_column->resizable;
1464 * gtk_tree_view_column_set_sizing:
1465 * @tree_column: A #GtkTreeViewColumn.
1466 * @type: The #GtkTreeViewColumnSizing.
1468 * Sets the growth behavior of @tree_column to @type.
1471 gtk_tree_view_column_set_sizing (GtkTreeViewColumn *tree_column,
1472 GtkTreeViewColumnSizing type)
1474 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1476 if (type == tree_column->column_type)
1479 if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1480 gtk_tree_view_column_set_resizable (tree_column, FALSE);
1483 /* I was clearly on crack when I wrote this. I'm not sure what's supposed to
1484 * be below so I'll leave it until I figure it out.
1486 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1487 tree_column->requested_width != -1)
1489 gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1492 tree_column->column_type = type;
1494 gtk_tree_view_column_update_button (tree_column);
1496 g_object_notify (G_OBJECT (tree_column), "sizing");
1500 * gtk_tree_view_column_get_sizing:
1501 * @tree_column: A #GtkTreeViewColumn.
1503 * Returns the current type of @tree_column.
1505 * Return value: The type of @tree_column.
1507 GtkTreeViewColumnSizing
1508 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1510 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1512 return tree_column->column_type;
1516 * gtk_tree_view_column_get_width:
1517 * @tree_column: A #GtkTreeViewColumn.
1519 * Returns the current size of @tree_column in pixels.
1521 * Return value: The current width of @tree_column.
1524 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1526 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1528 return tree_column->width;
1532 * gtk_tree_view_column_set_fixed_width:
1533 * @tree_column: A #GtkTreeViewColumn.
1534 * @fixed_width: The size to set @tree_column to. Must be greater than 0.
1536 * Sets the size of the column in pixels. This is meaningful only if the sizing
1537 * type is #GTK_TREE_VIEW_COLUMN_FIXED. In this case, the value is discarded
1538 * as the size of the column is based on the calculated width of the column. The
1539 * width is clamped to the min/max width for the column.
1542 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1545 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1546 g_return_if_fail (fixed_width > 0);
1548 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1551 tree_column->fixed_width = fixed_width;
1553 if (tree_column->tree_view &&
1554 GTK_WIDGET_REALIZED (tree_column->tree_view) &&
1555 tree_column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
1557 gtk_widget_queue_resize (tree_column->tree_view);
1562 * gtk_tree_view_column_get_fixed_width:
1563 * @tree_column: a #GtkTreeViewColumn
1565 * Gets the fixed width of the column. This value is only meaning may not be
1566 * the actual width of the column on the screen, just what is requested.
1568 * Return value: the fixed width of the column
1571 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1573 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1575 return tree_column->fixed_width;
1579 * gtk_tree_view_column_set_min_width:
1580 * @tree_column: A #GtkTreeViewColumn.
1581 * @min_width: The minimum width of the column in pixels, or -1.
1583 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
1584 * minimum width is unset.
1587 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1590 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1591 g_return_if_fail (min_width >= -1);
1593 if (min_width == tree_column->min_width)
1596 if (tree_column->visible &&
1597 tree_column->tree_view != NULL &&
1598 GTK_WIDGET_REALIZED (tree_column->tree_view))
1600 if (min_width > tree_column->width)
1601 gtk_widget_queue_resize (tree_column->tree_view);
1604 tree_column->min_width = min_width;
1605 if (tree_column->max_width != -1 && tree_column->max_width < min_width)
1607 tree_column->max_width = min_width;
1608 g_object_notify (G_OBJECT (tree_column), "max_width");
1610 g_object_notify (G_OBJECT (tree_column), "min_width");
1614 * gtk_tree_view_column_get_min_width:
1615 * @tree_column: A #GtkTreeViewColumn.
1617 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
1620 * Return value: The minimum width of the @tree_column.
1623 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
1625 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1627 return tree_column->min_width;
1631 * gtk_tree_view_column_set_max_width:
1632 * @tree_column: A #GtkTreeViewColumn.
1633 * @max_width: The maximum width of the column in pixels, or -1.
1635 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
1636 * maximum width is unset. Note, the column can actually be wider than max
1637 * width if it's the last column in a view. In this case, the column expands to
1638 * fill any extra space.
1641 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
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->visible &&
1651 tree_column->tree_view != NULL &&
1652 GTK_WIDGET_REALIZED (tree_column->tree_view))
1654 if (max_width != -1 && max_width < tree_column->width)
1655 gtk_widget_queue_resize (tree_column->tree_view);
1658 tree_column->max_width = max_width;
1659 if (max_width != -1 && max_width < tree_column->min_width)
1661 tree_column->min_width = max_width;
1662 g_object_notify (G_OBJECT (tree_column), "min_width");
1664 g_object_notify (G_OBJECT (tree_column), "max_width");
1668 * gtk_tree_view_column_get_max_width:
1669 * @tree_column: A #GtkTreeViewColumn.
1671 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
1674 * Return value: The maximum width of the @tree_column.
1677 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
1679 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
1681 return tree_column->max_width;
1685 * gtk_tree_view_column_clicked:
1686 * @tree_column: a #GtkTreeViewColumn
1688 * Emits the "clicked" signal on the column. This function will only work if
1689 * @tree_column is clickable.
1692 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
1694 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1696 if (tree_column->visible &&
1697 tree_column->button &&
1698 tree_column->clickable)
1699 gtk_button_clicked (GTK_BUTTON (tree_column->button));
1703 * gtk_tree_view_column_set_title:
1704 * @tree_column: A #GtkTreeViewColumn.
1705 * @title: The title of the @tree_column.
1707 * Sets the title of the @tree_column. If a custom widget has been set, then
1708 * this value is ignored.
1711 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
1714 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1716 g_free (tree_column->title);
1718 tree_column->title = g_strdup (title);
1720 tree_column->title = NULL;
1722 gtk_tree_view_column_update_button (tree_column);
1723 g_object_notify (G_OBJECT (tree_column), "title");
1727 * gtk_tree_view_column_get_title:
1728 * @tree_column: A #GtkTreeViewColumn.
1730 * Returns the title of the widget. This value should not be modified.
1732 * Return value: the title of the column.
1734 G_CONST_RETURN gchar *
1735 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
1737 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1739 return tree_column->title;
1743 * gtk_tree_view_column_set_clickable:
1744 * @tree_column: A #GtkTreeViewColumn.
1745 * @clickable: %TRUE if the header is active.
1747 * Sets the header to be active if @active is %TRUE. When the header is active,
1748 * then it can take keyboard focus, and can be clicked.
1751 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
1754 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1756 clickable = !! clickable;
1757 if (tree_column->clickable == clickable)
1760 tree_column->clickable = clickable;
1761 gtk_tree_view_column_update_button (tree_column);
1762 g_object_notify (G_OBJECT (tree_column), "clickable");
1766 * gtk_tree_view_column_get_clickable:
1767 * @tree_column: a #GtkTreeViewColumn
1769 * Returns %TRUE if the user can click on the header for the column.
1771 * Return value: %TRUE if user can click the column header.
1774 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
1776 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1778 return tree_column->clickable;
1782 * gtk_tree_view_column_set_widget:
1783 * @tree_column: A #GtkTreeViewColumn.
1784 * @widget: A child #GtkWidget, or %NULL.
1786 * Sets the widget in the header to be @widget. If widget is %NULL, then the
1787 * header button is set with a #GtkLabel set to the title of @tree_column.
1790 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
1793 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1794 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1798 gtk_object_ref (GTK_OBJECT (widget));
1799 gtk_object_sink (GTK_OBJECT (widget));
1802 if (tree_column->child)
1803 gtk_object_unref (GTK_OBJECT (tree_column->child));
1805 tree_column->child = widget;
1806 gtk_tree_view_column_update_button (tree_column);
1807 g_object_notify (G_OBJECT (tree_column), "widget");
1811 * gtk_tree_view_column_get_widget:
1812 * @tree_column: A #GtkTreeViewColumn.
1814 * Returns the #GtkWidget in the button in the column header. If a custom
1815 * widget has not been set, then this will be a #GtkAlignment with a #GtkLabel
1818 * Return value: The #GtkWidget in the column header.
1821 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
1823 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
1825 return tree_column->child;
1829 * gtk_tree_view_column_set_alignment:
1830 * @tree_column: A #GtkTreeViewColumn.
1831 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
1833 * Sets the alignment of the title or custom widget inside the column header.
1834 * The alignment determines its location inside the button -- 0.0 for left, 0.5
1835 * for center, 1.0 for right.
1838 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
1841 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1843 xalign = CLAMP (xalign, 0.0, 1.0);
1845 if (tree_column->xalign == xalign)
1848 tree_column->xalign = xalign;
1849 gtk_tree_view_column_update_button (tree_column);
1850 g_object_notify (G_OBJECT (tree_column), "alignment");
1854 * gtk_tree_view_column_get_alignment:
1855 * @tree_column: A #GtkTreeViewColumn.
1857 * Returns the current x alignment of @tree_column. This value can range
1858 * between 0.0 and 1.0.
1860 * Return value: The current alignent of @tree_column.
1863 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
1865 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
1867 return tree_column->xalign;
1871 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
1872 gboolean reorderable)
1874 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1877 gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
1879 if (tree_column->reorderable == (reorderable?TRUE:FALSE))
1882 tree_column->reorderable = (reorderable?TRUE:FALSE);
1883 gtk_tree_view_column_update_button (tree_column);
1884 g_object_notify (G_OBJECT (tree_column), "reorderable");
1888 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
1890 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1892 return tree_column->reorderable;
1897 * gtk_tree_view_column_set_sort_column_id:
1898 * @tree_column: a #GtkTreeViewColumn
1899 * @sort_column_id: The @sort_column_id of the model to sort on.
1901 * Sets the logical @sort_column_id that this column sorts on when this column
1902 * is selected for sorting. Doing so makes the column header clickable.
1905 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
1906 gint sort_column_id)
1908 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1909 g_return_if_fail (sort_column_id >= 0);
1911 if (tree_column->sort_column_id == sort_column_id)
1914 tree_column->sort_column_id = sort_column_id;
1916 /* Handle unsetting the id */
1917 if (sort_column_id == -1)
1919 if (tree_column->sort_clicked_signal)
1921 g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_clicked_signal);
1922 tree_column->sort_clicked_signal = 0;
1925 if (tree_column->sort_column_changed_signal)
1927 g_signal_handler_disconnect (G_OBJECT (tree_column), tree_column->sort_column_changed_signal);
1928 tree_column->sort_column_changed_signal = 0;
1931 gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
1932 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1936 gtk_tree_view_column_set_clickable (tree_column, TRUE);
1938 if (! tree_column->sort_clicked_signal)
1939 tree_column->sort_clicked_signal = g_signal_connect (G_OBJECT (tree_column),
1941 G_CALLBACK (gtk_tree_view_column_sort),
1944 gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
1948 * gtk_tree_view_column_get_sort_column_id:
1949 * @tree_column: a #GtkTreeViewColumn
1951 * Gets the logical @sort_column_id that the model sorts on when this
1952 * column is selected for sorting. See gtk_tree_view_column_set_sort_column_id().
1954 * Return value: the current @sort_column_id for this column, or -1 if
1955 * this column can't be used for sorting.
1958 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
1960 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1962 return tree_column->sort_column_id;
1966 * gtk_tree_view_column_set_sort_indicator:
1967 * @tree_column: a #GtkTreeViewColumn
1968 * @setting: %TRUE to display an indicator that the column is sorted
1970 * Call this function with a @setting of %TRUE to display an arrow in
1971 * the header button indicating the column is sorted. Call
1972 * gtk_tree_view_column_set_sort_order() to change the direction of
1977 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
1980 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1982 setting = setting != FALSE;
1984 if (setting == tree_column->show_sort_indicator)
1987 tree_column->show_sort_indicator = setting;
1988 gtk_tree_view_column_update_button (tree_column);
1989 g_object_notify (G_OBJECT (tree_column), "sort_indicator");
1993 * gtk_tree_view_column_get_sort_indicator:
1994 * @tree_column: a #GtkTreeViewColumn
1996 * Gets the value set by gtk_tree_view_column_set_sort_indicator().
1998 * Return value: whether the sort indicator arrow is displayed
2001 gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
2003 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2005 return tree_column->show_sort_indicator;
2009 * gtk_tree_view_column_set_sort_order:
2010 * @tree_column: a #GtkTreeViewColumn
2011 * @order: sort order that the sort indicator should indicate
2013 * Changes the appearance of the sort indicator.
2015 * This <emphasis>does not</emphasis> actually sort the model. Use
2016 * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2017 * support. This function is primarily for custom sorting behavior, and should
2018 * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2019 * that. For custom models, the mechanism will vary.
2021 * The sort indicator changes direction to indicate normal sort or reverse sort.
2022 * Note that you must have the sort indicator enabled to see anything when
2023 * calling this function; see gtk_tree_view_column_set_sort_indicator().
2026 gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
2029 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2031 if (order == tree_column->sort_order)
2034 tree_column->sort_order = order;
2035 gtk_tree_view_column_update_button (tree_column);
2036 g_object_notify (G_OBJECT (tree_column), "sort_order");
2040 * gtk_tree_view_column_get_sort_order:
2041 * @tree_column: a #GtkTreeViewColumn
2043 * Gets the value set by gtk_tree_view_column_set_sort_order().
2045 * Return value: the sort order the sort indicator is indicating
2048 gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
2050 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2052 return tree_column->sort_order;
2056 * gtk_tree_view_column_cell_set_cell_data:
2057 * @tree_column: A #GtkTreeViewColumn.
2058 * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2059 * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2060 * @is_expander: %TRUE, if the row has children
2061 * @is_expanded: %TRUE, if the row has visible children
2063 * Sets the cell renderer based on the @tree_model and @tree_node. That is, for
2064 * every attribute mapping in @tree_column, it will get a value from the set
2065 * column on the @tree_node, and use that value to set the attribute on the cell
2066 * renderer. This is used primarily by the #GtkTreeView.
2069 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2070 GtkTreeModel *tree_model,
2072 gboolean is_expander,
2073 gboolean is_expanded)
2076 GValue value = { 0, };
2079 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2080 g_return_if_fail (tree_column->cell_list != NULL);
2082 if (tree_model == NULL)
2085 for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2087 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2088 GObject *cell = (GObject *) info->cell;
2090 list = info->attributes;
2092 g_object_freeze_notify (cell);
2093 g_object_set (cell, "is_expander", is_expander, "is_expanded", is_expanded, NULL);
2095 while (list && list->next)
2097 gtk_tree_model_get_value (tree_model, iter,
2098 GPOINTER_TO_INT (list->next->data),
2100 g_object_set_property (cell, (gchar *) list->data, &value);
2101 g_value_unset (&value);
2102 list = list->next->next;
2106 (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2107 g_object_thaw_notify (G_OBJECT (info->cell));
2113 * gtk_tree_view_column_cell_get_size:
2114 * @tree_column: A #GtkTreeViewColumn.
2115 * @cell_area: The area a the column will be allocated, or %NULL
2116 * @x_offset: location to return x offset of cell relative to @cell_area, or %NULL
2117 * @y_offset: location to return y offset of cell relative to @cell_area, or %NULL
2118 * @width: location to return width needed to render a cell, or %NULL
2119 * @height: location to return height needed to render a cell, or %NULL
2121 * Obtains the width and height needed to render the column. This is used
2122 * primarily by the #GtkTreeView.
2125 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2126 GdkRectangle *cell_area,
2133 gboolean first_cell = TRUE;
2135 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2142 for (list = tree_column->cell_list; list; list = list->next)
2144 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2146 gint new_height = 0;
2148 g_object_get (info->cell, "visible", &visible, NULL);
2150 if (visible == FALSE)
2153 if (first_cell == FALSE && *width)
2154 *width += tree_column->spacing;
2156 gtk_cell_renderer_get_size (info->cell,
2157 tree_column->tree_view,
2165 * height = MAX (*height, new_height);
2166 info->requested_width = MAX (info->requested_width, new_width);
2168 * width += info->requested_width;
2173 /* both rendering and rendering focus are somewhat complicated, and a bit of
2174 * code. Rather than duplicate them, we put them together to keep the code in
2178 gtk_tree_view_column_cell_render_or_focus (GtkTreeViewColumn *tree_column,
2180 GdkRectangle *background_area,
2181 GdkRectangle *cell_area,
2182 GdkRectangle *expose_area,
2185 GdkRectangle *focus_rectangle)
2188 GdkRectangle real_cell_area;
2189 gint expand_cell_count = 0;
2190 gint full_requested_width = 0;
2192 gint min_x, min_y, max_x, max_y;
2199 real_cell_area = *cell_area;
2201 /* Find out how my extra space we have to allocate */
2202 for (list = tree_column->cell_list; list; list = list->next)
2204 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2206 if (! info->cell->visible)
2209 if (info->expand == TRUE)
2210 expand_cell_count ++;
2211 full_requested_width += info->requested_width;
2214 extra_space = cell_area->width - full_requested_width;
2215 if (extra_space < 0)
2218 for (list = tree_column->cell_list; list; list = list->next)
2220 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2222 if (info->pack == GTK_PACK_END)
2225 if (! info->cell->visible)
2228 real_cell_area.width = info->requested_width +
2229 (info->expand?extra_space:0);
2232 gtk_cell_renderer_render (info->cell,
2234 tree_column->tree_view,
2242 gint x_offset, y_offset, width, height;
2244 gtk_cell_renderer_get_size (info->cell,
2245 tree_column->tree_view,
2247 &x_offset, &y_offset,
2250 if (min_x > (real_cell_area.x + x_offset))
2251 min_x = real_cell_area.x + x_offset;
2252 if (max_x < real_cell_area.x + x_offset + width)
2253 max_x = real_cell_area.x + x_offset + width;
2254 if (min_y > (real_cell_area.y + y_offset))
2255 min_y = real_cell_area.y + y_offset;
2256 if (max_y < real_cell_area.y + y_offset + height)
2257 max_y = real_cell_area.y + y_offset + height;
2259 real_cell_area.x += (info->requested_width + tree_column->spacing);
2261 for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2263 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2265 if (info->pack == GTK_PACK_START)
2268 if (! info->cell->visible)
2271 real_cell_area.width = info->requested_width +
2272 (info->expand?extra_space:0);
2273 gtk_cell_renderer_render (info->cell,
2275 tree_column->tree_view,
2280 real_cell_area.x += (info->requested_width + tree_column->spacing);
2284 if (min_x >= max_x || min_y >= max_y)
2286 *focus_rectangle = *cell_area;
2287 focus_rectangle->x -= 1;
2288 focus_rectangle->y -= 1;
2289 focus_rectangle->width += 2;
2290 focus_rectangle->height += 2;
2294 focus_rectangle->x = min_x - 1;
2295 focus_rectangle->y = min_y - 1;
2296 focus_rectangle->width = (max_x - min_x) + 2;
2297 focus_rectangle->height = (max_y - min_y) + 2;
2303 * gtk_tree_view_column_cell_render:
2304 * @tree_column: A #GtkTreeViewColumn.
2305 * @window: a #GdkDrawable to draw to
2306 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
2307 * @cell_area: area normally rendered by a cell renderer
2308 * @expose_area: area that actually needs updating
2309 * @flags: flags that affect rendering
2311 * Renders the cell contained by #tree_column. This is used primarily by the
2315 gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
2317 GdkRectangle *background_area,
2318 GdkRectangle *cell_area,
2319 GdkRectangle *expose_area,
2322 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2323 g_return_if_fail (background_area != NULL);
2324 g_return_if_fail (cell_area != NULL);
2325 g_return_if_fail (expose_area != NULL);
2327 gtk_tree_view_column_cell_render_or_focus (tree_column,
2338 _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
2339 GtkCellEditable **editable_widget,
2342 GdkRectangle *background_area,
2343 GdkRectangle *cell_area,
2346 gboolean visible, mode;
2348 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2350 g_object_get (G_OBJECT (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell),
2351 "visible", &visible,
2354 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2356 if (gtk_cell_renderer_activate (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2358 tree_column->tree_view,
2365 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2367 *editable_widget = gtk_cell_renderer_start_editing (((GtkTreeViewColumnCellInfo *) tree_column->cell_list->data)->cell,
2369 tree_column->tree_view,
2375 if (*editable_widget != NULL)
2377 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2387 gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
2390 if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
2396 gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column,
2398 GdkRectangle *background_area,
2399 GdkRectangle *cell_area,
2400 GdkRectangle *expose_area,
2403 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2404 if (tree_column->editable_widget)
2406 /* This function is only called on the editable row when editing.
2409 gtk_paint_focus (tree_column->tree_view->style,
2411 GTK_WIDGET_STATE (tree_column->tree_view),
2413 tree_column->tree_view,
2417 cell_area->width + 2,
2418 cell_area->height + 2);
2423 GdkRectangle focus_rectangle;
2424 gtk_tree_view_column_cell_render_or_focus (tree_column,
2433 gtk_paint_focus (tree_column->tree_view->style,
2435 GTK_WIDGET_STATE (tree_column->tree_view),
2437 tree_column->tree_view,
2441 focus_rectangle.width,
2442 focus_rectangle.height);
2447 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
2451 for (list = tree_column->cell_list; list; list = list->next)
2453 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2455 if (info->cell->visible)
2463 gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column)
2467 for (list = tree_column->cell_list; list; list = list->next)
2469 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2471 info->requested_width = 0;
2473 tree_column->dirty = TRUE;
2474 tree_column->requested_width = 0;
2476 if (tree_column->tree_view &&
2477 GTK_WIDGET_REALIZED (tree_column->tree_view))
2479 _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (tree_column->tree_view));
2480 gtk_widget_queue_resize (tree_column->tree_view);
2485 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
2486 GtkCellEditable *cell_editable)
2488 g_return_if_fail (tree_column->editable_widget == NULL);
2490 tree_column->editable_widget = cell_editable;
2494 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
2496 g_return_if_fail (tree_column->editable_widget != NULL);
2498 tree_column->editable_widget = NULL;