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.
22 #include "gtktreeviewcolumn.h"
23 #include "gtktreeview.h"
24 #include "gtktreeprivate.h"
25 #include "gtkcelllayout.h"
26 #include "gtkbutton.h"
27 #include "gtkalignment.h"
29 #include "gtkextendedcell.h"
31 #include "gtkmarshalers.h"
33 #include "gtkprivate.h"
65 typedef struct _GtkTreeViewColumnCellInfo GtkTreeViewColumnCellInfo;
66 struct _GtkTreeViewColumnCellInfo
68 GtkCellRenderer *cell;
70 GtkTreeCellDataFunc func;
72 GDestroyNotify destroy;
78 guint in_editing_mode : 1;
82 static void gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface);
85 static void gtk_tree_view_column_set_property (GObject *object,
89 static void gtk_tree_view_column_get_property (GObject *object,
93 static void gtk_tree_view_column_finalize (GObject *object);
95 /* GtkCellLayout implementation */
96 static void gtk_tree_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
97 GtkCellRenderer *cell,
99 static void gtk_tree_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
100 GtkCellRenderer *cell,
102 static void gtk_tree_view_column_cell_layout_clear (GtkCellLayout *cell_layout);
103 static void gtk_tree_view_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
104 GtkCellRenderer *cell,
105 const gchar *attribute,
107 static void gtk_tree_view_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
108 GtkCellRenderer *cell,
109 GtkCellLayoutDataFunc func,
111 GDestroyNotify destroy);
112 static void gtk_tree_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
113 GtkCellRenderer *cell);
114 static void gtk_tree_view_column_cell_layout_reorder (GtkCellLayout *cell_layout,
115 GtkCellRenderer *cell,
117 static GList *gtk_tree_view_column_cell_layout_get_cells (GtkCellLayout *cell_layout);
119 /* Button handling code */
120 static void gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column);
121 static void gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column);
123 /* Button signal handlers */
124 static gint gtk_tree_view_column_button_event (GtkWidget *widget,
127 static void gtk_tree_view_column_button_clicked (GtkWidget *widget,
129 static gboolean gtk_tree_view_column_mnemonic_activate (GtkWidget *widget,
130 gboolean group_cycling,
133 /* Property handlers */
134 static void gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
135 GtkTreeViewColumn *tree_column);
137 /* Internal functions */
138 static void gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
140 static void gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column);
141 static void gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
142 GtkCellRenderer *cell_renderer,
144 static GtkTreeViewColumnCellInfo *gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
145 GtkCellRenderer *cell_renderer);
147 /* cell list manipulation */
148 static GList *gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column);
149 static GList *gtk_tree_view_column_cell_last (GtkTreeViewColumn *tree_column);
150 static GList *gtk_tree_view_column_cell_next (GtkTreeViewColumn *tree_column,
152 static GList *gtk_tree_view_column_cell_prev (GtkTreeViewColumn *tree_column,
154 static void gtk_tree_view_column_clear_attributes_by_info (GtkTreeViewColumn *tree_column,
155 GtkTreeViewColumnCellInfo *info);
156 /* GtkBuildable implementation */
157 static void gtk_tree_view_column_buildable_init (GtkBuildableIface *iface);
159 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
161 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT,
162 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
163 gtk_tree_view_column_cell_layout_init)
164 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
165 gtk_tree_view_column_buildable_init))
170 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
172 GObjectClass *object_class;
174 object_class = (GObjectClass*) class;
176 class->clicked = NULL;
178 object_class->finalize = gtk_tree_view_column_finalize;
179 object_class->set_property = gtk_tree_view_column_set_property;
180 object_class->get_property = gtk_tree_view_column_get_property;
182 tree_column_signals[CLICKED] =
183 g_signal_new (I_("clicked"),
184 G_OBJECT_CLASS_TYPE (object_class),
186 G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
188 _gtk_marshal_VOID__VOID,
191 g_object_class_install_property (object_class,
193 g_param_spec_boolean ("visible",
195 P_("Whether to display the column"),
197 GTK_PARAM_READWRITE));
199 g_object_class_install_property (object_class,
201 g_param_spec_boolean ("resizable",
203 P_("Column is user-resizable"),
205 GTK_PARAM_READWRITE));
207 g_object_class_install_property (object_class,
209 g_param_spec_int ("width",
211 P_("Current width of the column"),
215 GTK_PARAM_READABLE));
216 g_object_class_install_property (object_class,
218 g_param_spec_int ("spacing",
220 P_("Space which is inserted between cells"),
224 GTK_PARAM_READWRITE));
225 g_object_class_install_property (object_class,
227 g_param_spec_enum ("sizing",
229 P_("Resize mode of the column"),
230 GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
231 GTK_TREE_VIEW_COLUMN_GROW_ONLY,
232 GTK_PARAM_READWRITE));
234 g_object_class_install_property (object_class,
236 g_param_spec_int ("fixed-width",
238 P_("Current fixed width of the column"),
242 GTK_PARAM_READWRITE));
244 g_object_class_install_property (object_class,
246 g_param_spec_int ("min-width",
248 P_("Minimum allowed width of the column"),
252 GTK_PARAM_READWRITE));
254 g_object_class_install_property (object_class,
256 g_param_spec_int ("max-width",
258 P_("Maximum allowed width of the column"),
262 GTK_PARAM_READWRITE));
264 g_object_class_install_property (object_class,
266 g_param_spec_string ("title",
268 P_("Title to appear in column header"),
270 GTK_PARAM_READWRITE));
272 g_object_class_install_property (object_class,
274 g_param_spec_boolean ("expand",
276 P_("Column gets share of extra width allocated to the widget"),
278 GTK_PARAM_READWRITE));
280 g_object_class_install_property (object_class,
282 g_param_spec_boolean ("clickable",
284 P_("Whether the header can be clicked"),
286 GTK_PARAM_READWRITE));
289 g_object_class_install_property (object_class,
291 g_param_spec_object ("widget",
293 P_("Widget to put in column header button instead of column title"),
295 GTK_PARAM_READWRITE));
297 g_object_class_install_property (object_class,
299 g_param_spec_float ("alignment",
301 P_("X Alignment of the column header text or widget"),
305 GTK_PARAM_READWRITE));
307 g_object_class_install_property (object_class,
309 g_param_spec_boolean ("reorderable",
311 P_("Whether the column can be reordered around the headers"),
313 GTK_PARAM_READWRITE));
315 g_object_class_install_property (object_class,
317 g_param_spec_boolean ("sort-indicator",
318 P_("Sort indicator"),
319 P_("Whether to show a sort indicator"),
321 GTK_PARAM_READWRITE));
323 g_object_class_install_property (object_class,
325 g_param_spec_enum ("sort-order",
327 P_("Sort direction the sort indicator should indicate"),
330 GTK_PARAM_READWRITE));
333 * GtkTreeViewColumn:sort-column-id:
335 * Logical sort column ID this column sorts on when selected for sorting. Setting the sort column ID makes the column header
336 * clickable. Set to %-1 to make the column unsortable.
340 g_object_class_install_property (object_class,
342 g_param_spec_int ("sort-column-id",
343 P_("Sort column ID"),
344 P_("Logical sort column ID this column sorts on when selected for sorting"),
348 GTK_PARAM_READWRITE));
350 g_type_class_add_private (class, sizeof (GtkTreeViewColumnPrivate));
354 gtk_tree_view_column_buildable_init (GtkBuildableIface *iface)
356 iface->add_child = _gtk_cell_layout_buildable_add_child;
357 iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
358 iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
362 gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
364 iface->pack_start = gtk_tree_view_column_cell_layout_pack_start;
365 iface->pack_end = gtk_tree_view_column_cell_layout_pack_end;
366 iface->clear = gtk_tree_view_column_cell_layout_clear;
367 iface->add_attribute = gtk_tree_view_column_cell_layout_add_attribute;
368 iface->set_cell_data_func = gtk_tree_view_column_cell_layout_set_cell_data_func;
369 iface->clear_attributes = gtk_tree_view_column_cell_layout_clear_attributes;
370 iface->reorder = gtk_tree_view_column_cell_layout_reorder;
371 iface->get_cells = gtk_tree_view_column_cell_layout_get_cells;
375 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
377 tree_column->button = NULL;
378 tree_column->xalign = 0.0;
379 tree_column->width = 0;
380 tree_column->spacing = 0;
381 tree_column->requested_width = -1;
382 tree_column->min_width = -1;
383 tree_column->max_width = -1;
384 tree_column->resized_width = 0;
385 tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
386 tree_column->visible = TRUE;
387 tree_column->resizable = FALSE;
388 tree_column->expand = FALSE;
389 tree_column->clickable = FALSE;
390 tree_column->dirty = TRUE;
391 tree_column->sort_order = GTK_SORT_ASCENDING;
392 tree_column->show_sort_indicator = FALSE;
393 tree_column->property_changed_signal = 0;
394 tree_column->sort_clicked_signal = 0;
395 tree_column->sort_column_changed_signal = 0;
396 tree_column->sort_column_id = -1;
397 tree_column->reorderable = FALSE;
398 tree_column->maybe_reordered = FALSE;
399 tree_column->fixed_width = 1;
400 tree_column->use_resized_width = FALSE;
401 tree_column->title = g_strdup ("");
405 gtk_tree_view_column_finalize (GObject *object)
407 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
410 for (list = tree_column->cell_list; list; list = list->next)
412 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
416 GDestroyNotify d = info->destroy;
418 info->destroy = NULL;
421 gtk_tree_view_column_clear_attributes_by_info (tree_column, info);
422 g_object_unref (info->cell);
426 g_free (tree_column->title);
427 g_list_free (tree_column->cell_list);
429 if (tree_column->child)
430 g_object_unref (tree_column->child);
432 G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->finalize (object);
436 gtk_tree_view_column_set_property (GObject *object,
441 GtkTreeViewColumn *tree_column;
443 tree_column = GTK_TREE_VIEW_COLUMN (object);
448 gtk_tree_view_column_set_visible (tree_column,
449 g_value_get_boolean (value));
453 gtk_tree_view_column_set_resizable (tree_column,
454 g_value_get_boolean (value));
458 gtk_tree_view_column_set_sizing (tree_column,
459 g_value_get_enum (value));
462 case PROP_FIXED_WIDTH:
463 gtk_tree_view_column_set_fixed_width (tree_column,
464 g_value_get_int (value));
468 gtk_tree_view_column_set_min_width (tree_column,
469 g_value_get_int (value));
473 gtk_tree_view_column_set_max_width (tree_column,
474 g_value_get_int (value));
478 gtk_tree_view_column_set_spacing (tree_column,
479 g_value_get_int (value));
483 gtk_tree_view_column_set_title (tree_column,
484 g_value_get_string (value));
488 gtk_tree_view_column_set_expand (tree_column,
489 g_value_get_boolean (value));
493 gtk_tree_view_column_set_clickable (tree_column,
494 g_value_get_boolean (value));
498 gtk_tree_view_column_set_widget (tree_column,
499 (GtkWidget*) g_value_get_object (value));
503 gtk_tree_view_column_set_alignment (tree_column,
504 g_value_get_float (value));
507 case PROP_REORDERABLE:
508 gtk_tree_view_column_set_reorderable (tree_column,
509 g_value_get_boolean (value));
512 case PROP_SORT_INDICATOR:
513 gtk_tree_view_column_set_sort_indicator (tree_column,
514 g_value_get_boolean (value));
517 case PROP_SORT_ORDER:
518 gtk_tree_view_column_set_sort_order (tree_column,
519 g_value_get_enum (value));
522 case PROP_SORT_COLUMN_ID:
523 gtk_tree_view_column_set_sort_column_id (tree_column,
524 g_value_get_int (value));
528 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
534 gtk_tree_view_column_get_property (GObject *object,
539 GtkTreeViewColumn *tree_column;
541 tree_column = GTK_TREE_VIEW_COLUMN (object);
546 g_value_set_boolean (value,
547 gtk_tree_view_column_get_visible (tree_column));
551 g_value_set_boolean (value,
552 gtk_tree_view_column_get_resizable (tree_column));
556 g_value_set_int (value,
557 gtk_tree_view_column_get_width (tree_column));
561 g_value_set_int (value,
562 gtk_tree_view_column_get_spacing (tree_column));
566 g_value_set_enum (value,
567 gtk_tree_view_column_get_sizing (tree_column));
570 case PROP_FIXED_WIDTH:
571 g_value_set_int (value,
572 gtk_tree_view_column_get_fixed_width (tree_column));
576 g_value_set_int (value,
577 gtk_tree_view_column_get_min_width (tree_column));
581 g_value_set_int (value,
582 gtk_tree_view_column_get_max_width (tree_column));
586 g_value_set_string (value,
587 gtk_tree_view_column_get_title (tree_column));
591 g_value_set_boolean (value,
592 gtk_tree_view_column_get_expand (tree_column));
596 g_value_set_boolean (value,
597 gtk_tree_view_column_get_clickable (tree_column));
601 g_value_set_object (value,
602 (GObject*) gtk_tree_view_column_get_widget (tree_column));
606 g_value_set_float (value,
607 gtk_tree_view_column_get_alignment (tree_column));
610 case PROP_REORDERABLE:
611 g_value_set_boolean (value,
612 gtk_tree_view_column_get_reorderable (tree_column));
615 case PROP_SORT_INDICATOR:
616 g_value_set_boolean (value,
617 gtk_tree_view_column_get_sort_indicator (tree_column));
620 case PROP_SORT_ORDER:
621 g_value_set_enum (value,
622 gtk_tree_view_column_get_sort_order (tree_column));
625 case PROP_SORT_COLUMN_ID:
626 g_value_set_int (value,
627 gtk_tree_view_column_get_sort_column_id (tree_column));
631 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
636 /* Implementation of GtkCellLayout interface
640 gtk_tree_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
641 GtkCellRenderer *cell,
644 GtkTreeViewColumn *column;
645 GtkTreeViewColumnCellInfo *cell_info;
647 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
648 column = GTK_TREE_VIEW_COLUMN (cell_layout);
649 g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell));
651 g_object_ref_sink (cell);
653 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
654 cell_info->cell = cell;
655 cell_info->expand = expand ? TRUE : FALSE;
656 cell_info->pack = GTK_PACK_START;
657 cell_info->has_focus = 0;
658 cell_info->attributes = NULL;
660 column->cell_list = g_list_append (column->cell_list, cell_info);
664 gtk_tree_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
665 GtkCellRenderer *cell,
668 GtkTreeViewColumn *column;
669 GtkTreeViewColumnCellInfo *cell_info;
671 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
672 column = GTK_TREE_VIEW_COLUMN (cell_layout);
673 g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell));
675 g_object_ref_sink (cell);
677 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
678 cell_info->cell = cell;
679 cell_info->expand = expand ? TRUE : FALSE;
680 cell_info->pack = GTK_PACK_END;
681 cell_info->has_focus = 0;
682 cell_info->attributes = NULL;
684 column->cell_list = g_list_append (column->cell_list, cell_info);
688 gtk_tree_view_column_cell_layout_clear (GtkCellLayout *cell_layout)
690 GtkTreeViewColumn *column;
692 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
693 column = GTK_TREE_VIEW_COLUMN (cell_layout);
695 while (column->cell_list)
697 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)column->cell_list->data;
699 gtk_tree_view_column_cell_layout_clear_attributes (cell_layout, info->cell);
700 g_object_unref (info->cell);
702 column->cell_list = g_list_delete_link (column->cell_list,
708 gtk_tree_view_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
709 GtkCellRenderer *cell,
710 const gchar *attribute,
713 GtkTreeViewColumn *tree_column;
714 GtkTreeViewColumnCellInfo *info;
716 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
717 tree_column = GTK_TREE_VIEW_COLUMN (cell_layout);
719 info = gtk_tree_view_column_get_cell_info (tree_column, cell);
720 g_return_if_fail (info != NULL);
722 info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
723 info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
725 if (tree_column->tree_view)
726 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
730 gtk_tree_view_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
731 GtkCellRenderer *cell,
732 GtkCellLayoutDataFunc func,
734 GDestroyNotify destroy)
736 GtkTreeViewColumn *column;
737 GtkTreeViewColumnCellInfo *info;
739 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
740 column = GTK_TREE_VIEW_COLUMN (cell_layout);
742 info = gtk_tree_view_column_get_cell_info (column, cell);
743 g_return_if_fail (info != NULL);
747 GDestroyNotify d = info->destroy;
749 info->destroy = NULL;
753 info->func = (GtkTreeCellDataFunc)func;
754 info->func_data = func_data;
755 info->destroy = destroy;
757 if (column->tree_view)
758 _gtk_tree_view_column_cell_set_dirty (column, TRUE);
762 gtk_tree_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
763 GtkCellRenderer *cell_renderer)
765 GtkTreeViewColumn *column;
766 GtkTreeViewColumnCellInfo *info;
768 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
769 column = GTK_TREE_VIEW_COLUMN (cell_layout);
771 info = gtk_tree_view_column_get_cell_info (column, cell_renderer);
773 gtk_tree_view_column_clear_attributes_by_info (column, info);
777 gtk_tree_view_column_cell_layout_reorder (GtkCellLayout *cell_layout,
778 GtkCellRenderer *cell,
782 GtkTreeViewColumn *column;
783 GtkTreeViewColumnCellInfo *info;
785 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
786 column = GTK_TREE_VIEW_COLUMN (cell_layout);
788 info = gtk_tree_view_column_get_cell_info (column, cell);
790 g_return_if_fail (info != NULL);
791 g_return_if_fail (position >= 0);
793 link = g_list_find (column->cell_list, info);
795 g_return_if_fail (link != NULL);
797 column->cell_list = g_list_delete_link (column->cell_list, link);
798 column->cell_list = g_list_insert (column->cell_list, info, position);
800 if (column->tree_view)
801 gtk_widget_queue_draw (column->tree_view);
805 gtk_tree_view_column_clear_attributes_by_info (GtkTreeViewColumn *tree_column,
806 GtkTreeViewColumnCellInfo *info)
810 list = info->attributes;
812 while (list && list->next)
815 list = list->next->next;
817 g_slist_free (info->attributes);
818 info->attributes = NULL;
820 if (tree_column->tree_view)
821 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
827 /* Button handling code
830 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
832 GtkTreeView *tree_view;
836 tree_view = (GtkTreeView *) tree_column->tree_view;
838 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
839 g_return_if_fail (tree_column->button == NULL);
841 gtk_widget_push_composite_child ();
842 tree_column->button = gtk_button_new ();
843 gtk_widget_add_events (tree_column->button, GDK_POINTER_MOTION_MASK);
844 gtk_widget_pop_composite_child ();
846 /* make sure we own a reference to it as well. */
847 if (tree_view->priv->header_window)
848 gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
849 gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
851 g_signal_connect (tree_column->button, "event",
852 G_CALLBACK (gtk_tree_view_column_button_event),
854 g_signal_connect (tree_column->button, "clicked",
855 G_CALLBACK (gtk_tree_view_column_button_clicked),
858 tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
860 hbox = gtk_hbox_new (FALSE, 2);
861 tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
863 if (tree_column->child)
864 child = tree_column->child;
867 child = gtk_label_new (tree_column->title);
868 gtk_widget_show (child);
871 g_signal_connect (child, "mnemonic-activate",
872 G_CALLBACK (gtk_tree_view_column_mnemonic_activate),
875 if (tree_column->xalign <= 0.5)
876 gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
878 gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
880 gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
882 gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
883 gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
885 gtk_widget_show (hbox);
886 gtk_widget_show (tree_column->alignment);
887 gtk_tree_view_column_update_button (tree_column);
891 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
893 gint sort_column_id = -1;
895 GtkWidget *alignment;
897 GtkWidget *current_child;
898 GtkArrowType arrow_type = GTK_ARROW_NONE;
901 if (tree_column->tree_view)
902 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
906 /* Create a button if necessary */
907 if (tree_column->visible &&
908 tree_column->button == NULL &&
909 tree_column->tree_view &&
910 gtk_widget_get_realized (tree_column->tree_view))
911 gtk_tree_view_column_create_button (tree_column);
913 if (! tree_column->button)
916 hbox = GTK_BIN (tree_column->button)->child;
917 alignment = tree_column->alignment;
918 arrow = tree_column->arrow;
919 current_child = GTK_BIN (alignment)->child;
921 /* Set up the actual button */
922 gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
925 if (tree_column->child)
927 if (current_child != tree_column->child)
929 gtk_container_remove (GTK_CONTAINER (alignment),
931 gtk_container_add (GTK_CONTAINER (alignment),
937 if (current_child == NULL)
939 current_child = gtk_label_new (NULL);
940 gtk_widget_show (current_child);
941 gtk_container_add (GTK_CONTAINER (alignment),
945 g_return_if_fail (GTK_IS_LABEL (current_child));
947 if (tree_column->title)
948 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
951 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
955 if (GTK_IS_TREE_SORTABLE (model))
956 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
960 if (tree_column->show_sort_indicator)
962 gboolean alternative;
964 g_object_get (gtk_widget_get_settings (tree_column->tree_view),
965 "gtk-alternative-sort-arrows", &alternative,
968 switch (tree_column->sort_order)
970 case GTK_SORT_ASCENDING:
971 arrow_type = alternative ? GTK_ARROW_UP : GTK_ARROW_DOWN;
974 case GTK_SORT_DESCENDING:
975 arrow_type = alternative ? GTK_ARROW_DOWN : GTK_ARROW_UP;
979 g_warning (G_STRLOC": bad sort order");
984 gtk_arrow_set (GTK_ARROW (arrow),
988 /* Put arrow on the right if the text is left-or-center justified, and on the
989 * left otherwise; do this by packing boxes, so flipping text direction will
992 g_object_ref (arrow);
993 gtk_container_remove (GTK_CONTAINER (hbox), arrow);
995 if (tree_column->xalign <= 0.5)
997 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1001 gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1002 /* move it to the front */
1003 gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
1005 g_object_unref (arrow);
1007 if (tree_column->show_sort_indicator
1008 || (GTK_IS_TREE_SORTABLE (model) && tree_column->sort_column_id >= 0))
1009 gtk_widget_show (arrow);
1011 gtk_widget_hide (arrow);
1013 /* It's always safe to hide the button. It isn't always safe to show it, as
1014 * if you show it before it's realized, it'll get the wrong window. */
1015 if (tree_column->button &&
1016 tree_column->tree_view != NULL &&
1017 gtk_widget_get_realized (tree_column->tree_view))
1019 if (tree_column->visible)
1021 gtk_widget_show_now (tree_column->button);
1022 if (tree_column->window)
1024 if (tree_column->resizable)
1026 gdk_window_show (tree_column->window);
1027 gdk_window_raise (tree_column->window);
1031 gdk_window_hide (tree_column->window);
1037 gtk_widget_hide (tree_column->button);
1038 if (tree_column->window)
1039 gdk_window_hide (tree_column->window);
1043 if (tree_column->reorderable || tree_column->clickable)
1045 gtk_widget_set_can_focus (tree_column->button, TRUE);
1049 gtk_widget_set_can_focus (tree_column->button, FALSE);
1050 if (gtk_widget_has_focus (tree_column->button))
1052 GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
1053 if (gtk_widget_is_toplevel (toplevel))
1055 gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
1059 /* Queue a resize on the assumption that we always want to catch all changes
1060 * and columns don't change all that often.
1062 if (gtk_widget_get_realized (tree_column->tree_view))
1063 gtk_widget_queue_resize (tree_column->tree_view);
1067 /* Button signal handlers
1071 gtk_tree_view_column_button_event (GtkWidget *widget,
1075 GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
1077 g_return_val_if_fail (event != NULL, FALSE);
1079 if (event->type == GDK_BUTTON_PRESS &&
1080 column->reorderable &&
1081 ((GdkEventButton *)event)->button == 1)
1083 column->maybe_reordered = TRUE;
1084 gdk_window_get_pointer (GTK_BUTTON (widget)->event_window,
1088 gtk_widget_grab_focus (widget);
1091 if (event->type == GDK_BUTTON_RELEASE ||
1092 event->type == GDK_LEAVE_NOTIFY)
1093 column->maybe_reordered = FALSE;
1095 if (event->type == GDK_MOTION_NOTIFY &&
1096 column->maybe_reordered &&
1097 (gtk_drag_check_threshold (widget,
1100 (gint) ((GdkEventMotion *)event)->x,
1101 (gint) ((GdkEventMotion *)event)->y)))
1103 column->maybe_reordered = FALSE;
1104 _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
1107 if (column->clickable == FALSE)
1109 switch (event->type)
1111 case GDK_BUTTON_PRESS:
1112 case GDK_2BUTTON_PRESS:
1113 case GDK_3BUTTON_PRESS:
1114 case GDK_MOTION_NOTIFY:
1115 case GDK_BUTTON_RELEASE:
1116 case GDK_ENTER_NOTIFY:
1117 case GDK_LEAVE_NOTIFY:
1128 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
1130 g_signal_emit_by_name (data, "clicked");
1134 gtk_tree_view_column_mnemonic_activate (GtkWidget *widget,
1135 gboolean group_cycling,
1138 GtkTreeViewColumn *column = (GtkTreeViewColumn *)data;
1140 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), FALSE);
1142 GTK_TREE_VIEW (column->tree_view)->priv->focus_column = column;
1143 if (column->clickable)
1144 gtk_button_clicked (GTK_BUTTON (column->button));
1145 else if (gtk_widget_get_can_focus (column->button))
1146 gtk_widget_grab_focus (column->button);
1148 gtk_widget_grab_focus (column->tree_view);
1154 gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
1155 GtkTreeViewColumn *column)
1157 gint sort_column_id;
1160 if (gtk_tree_sortable_get_sort_column_id (sortable,
1164 if (sort_column_id == column->sort_column_id)
1166 gtk_tree_view_column_set_sort_indicator (column, TRUE);
1167 gtk_tree_view_column_set_sort_order (column, order);
1171 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1176 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1181 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
1184 gint sort_column_id;
1186 gboolean has_sort_column;
1187 gboolean has_default_sort_func;
1189 g_return_if_fail (tree_column->tree_view != NULL);
1192 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1195 has_default_sort_func =
1196 gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model));
1198 if (has_sort_column &&
1199 sort_column_id == tree_column->sort_column_id)
1201 if (order == GTK_SORT_ASCENDING)
1202 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1203 tree_column->sort_column_id,
1204 GTK_SORT_DESCENDING);
1205 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
1206 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1207 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1208 GTK_SORT_ASCENDING);
1210 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1211 tree_column->sort_column_id,
1212 GTK_SORT_ASCENDING);
1216 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1217 tree_column->sort_column_id,
1218 GTK_SORT_ASCENDING);
1224 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
1226 GtkTreeModel *model;
1228 if (tree_column->tree_view == NULL)
1231 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
1236 if (GTK_IS_TREE_SORTABLE (model) &&
1237 tree_column->sort_column_id != -1)
1239 gint real_sort_column_id;
1240 GtkSortType real_order;
1242 if (tree_column->sort_column_changed_signal == 0)
1243 tree_column->sort_column_changed_signal =
1244 g_signal_connect (model, "sort-column-changed",
1245 G_CALLBACK (gtk_tree_view_model_sort_column_changed),
1248 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
1249 &real_sort_column_id,
1251 (real_sort_column_id == tree_column->sort_column_id))
1253 gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
1254 gtk_tree_view_column_set_sort_order (tree_column, real_order);
1258 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1264 /* Exported Private Functions.
1265 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
1269 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
1271 GtkTreeView *tree_view;
1273 guint attributes_mask;
1276 tree_view = (GtkTreeView *)column->tree_view;
1277 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1279 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
1280 g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (tree_view)));
1281 g_return_if_fail (tree_view->priv->header_window != NULL);
1282 g_return_if_fail (column->button != NULL);
1284 gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
1286 if (column->visible)
1287 gtk_widget_show (column->button);
1289 attr.window_type = GDK_WINDOW_CHILD;
1290 attr.wclass = GDK_INPUT_ONLY;
1291 attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
1292 attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
1293 attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view)) |
1294 (GDK_BUTTON_PRESS_MASK |
1295 GDK_BUTTON_RELEASE_MASK |
1296 GDK_POINTER_MOTION_MASK |
1297 GDK_POINTER_MOTION_HINT_MASK |
1298 GDK_KEY_PRESS_MASK);
1299 attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
1300 attr.cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (tree_view->priv->header_window),
1301 GDK_SB_H_DOUBLE_ARROW);
1303 attr.width = TREE_VIEW_DRAG_WIDTH;
1304 attr.height = tree_view->priv->header_height;
1306 attr.x = (column->button->allocation.x + (rtl ? 0 : column->button->allocation.width)) - TREE_VIEW_DRAG_WIDTH / 2;
1307 column->window = gdk_window_new (tree_view->priv->header_window,
1308 &attr, attributes_mask);
1309 gdk_window_set_user_data (column->window, tree_view);
1311 gtk_tree_view_column_update_button (column);
1313 gdk_cursor_unref (attr.cursor);
1317 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
1319 g_return_if_fail (column != NULL);
1320 g_return_if_fail (column->window != NULL);
1322 gdk_window_set_user_data (column->window, NULL);
1323 gdk_window_destroy (column->window);
1324 column->window = NULL;
1328 _gtk_tree_view_column_unset_model (GtkTreeViewColumn *column,
1329 GtkTreeModel *old_model)
1331 if (column->sort_column_changed_signal)
1333 g_signal_handler_disconnect (old_model,
1334 column->sort_column_changed_signal);
1335 column->sort_column_changed_signal = 0;
1337 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1341 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
1342 GtkTreeView *tree_view)
1344 g_assert (column->tree_view == NULL);
1346 column->tree_view = GTK_WIDGET (tree_view);
1347 gtk_tree_view_column_create_button (column);
1349 column->property_changed_signal =
1350 g_signal_connect_swapped (tree_view,
1352 G_CALLBACK (gtk_tree_view_column_setup_sort_column_id_callback),
1355 gtk_tree_view_column_setup_sort_column_id_callback (column);
1359 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
1361 if (column->tree_view && column->button)
1363 gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
1365 if (column->property_changed_signal)
1367 g_signal_handler_disconnect (column->tree_view, column->property_changed_signal);
1368 column->property_changed_signal = 0;
1371 if (column->sort_column_changed_signal)
1373 g_signal_handler_disconnect (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view)),
1374 column->sort_column_changed_signal);
1375 column->sort_column_changed_signal = 0;
1378 column->tree_view = NULL;
1379 column->button = NULL;
1383 _gtk_tree_view_column_has_editable_cell (GtkTreeViewColumn *column)
1387 for (list = column->cell_list; list; list = list->next)
1388 if (((GtkTreeViewColumnCellInfo *)list->data)->cell->mode ==
1389 GTK_CELL_RENDERER_MODE_EDITABLE)
1395 /* gets cell being edited */
1397 _gtk_tree_view_column_get_edited_cell (GtkTreeViewColumn *column)
1401 for (list = column->cell_list; list; list = list->next)
1402 if (((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode)
1403 return ((GtkTreeViewColumnCellInfo *)list->data)->cell;
1409 _gtk_tree_view_column_count_special_cells (GtkTreeViewColumn *column)
1414 for (list = column->cell_list; list; list = list->next)
1416 GtkTreeViewColumnCellInfo *cellinfo = list->data;
1418 if ((cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
1419 cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE) &&
1420 cellinfo->cell->visible)
1428 _gtk_tree_view_column_get_cell_at_pos (GtkTreeViewColumn *column,
1434 list = gtk_tree_view_column_cell_first (column);
1435 for (; list; list = gtk_tree_view_column_cell_next (column, list))
1437 GtkTreeViewColumnCellInfo *cellinfo = list->data;
1438 if (current_x <= x && x <= current_x + cellinfo->real_width)
1439 return cellinfo->cell;
1440 current_x += cellinfo->real_width;
1446 /* Public Functions */
1450 * gtk_tree_view_column_new:
1452 * Creates a new #GtkTreeViewColumn.
1454 * Return value: A newly created #GtkTreeViewColumn.
1457 gtk_tree_view_column_new (void)
1459 GtkTreeViewColumn *tree_column;
1461 tree_column = g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, NULL);
1467 * gtk_tree_view_column_new_with_attributes:
1468 * @title: The title to set the header to.
1469 * @cell: The #GtkCellRenderer.
1470 * @Varargs: A %NULL-terminated list of attributes.
1472 * Creates a new #GtkTreeViewColumn with a number of default values. This is
1473 * equivalent to calling gtk_tree_view_column_set_title(),
1474 * gtk_tree_view_column_pack_start(), and
1475 * gtk_tree_view_column_set_attributes() on the newly created #GtkTreeViewColumn.
1477 * Here's a simple example:
1479 * enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS };
1482 * GtkTreeViewColumn *column;
1483 * GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1485 * column = gtk_tree_view_column_new_with_attributes ("Title",
1487 * "text", TEXT_COLUMN,
1488 * "foreground", COLOR_COLUMN,
1493 * Return value: A newly created #GtkTreeViewColumn.
1496 gtk_tree_view_column_new_with_attributes (const gchar *title,
1497 GtkCellRenderer *cell,
1500 GtkTreeViewColumn *retval;
1503 retval = gtk_tree_view_column_new ();
1505 gtk_tree_view_column_set_title (retval, title);
1506 gtk_tree_view_column_pack_start (retval, cell, TRUE);
1508 va_start (args, cell);
1509 gtk_tree_view_column_set_attributesv (retval, cell, args);
1515 static GtkTreeViewColumnCellInfo *
1516 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1517 GtkCellRenderer *cell_renderer)
1520 for (list = tree_column->cell_list; list; list = list->next)
1521 if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1522 return (GtkTreeViewColumnCellInfo *) list->data;
1528 * gtk_tree_view_column_pack_start:
1529 * @tree_column: A #GtkTreeViewColumn.
1530 * @cell: The #GtkCellRenderer.
1531 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1533 * Packs the @cell into the beginning of the column. If @expand is %FALSE, then
1534 * the @cell is allocated no more space than it needs. Any unused space is divided
1535 * evenly between cells for which @expand is %TRUE.
1538 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1539 GtkCellRenderer *cell,
1542 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tree_column), cell, expand);
1546 * gtk_tree_view_column_pack_end:
1547 * @tree_column: A #GtkTreeViewColumn.
1548 * @cell: The #GtkCellRenderer.
1549 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1551 * Adds the @cell to end of the column. If @expand is %FALSE, then the @cell
1552 * is allocated no more space than it needs. Any unused space is divided
1553 * evenly between cells for which @expand is %TRUE.
1556 gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
1557 GtkCellRenderer *cell,
1560 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (tree_column), cell, expand);
1564 * gtk_tree_view_column_clear:
1565 * @tree_column: A #GtkTreeViewColumn
1567 * Unsets all the mappings on all renderers on the @tree_column.
1570 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1572 gtk_cell_layout_clear (GTK_CELL_LAYOUT (tree_column));
1576 gtk_tree_view_column_cell_layout_get_cells (GtkCellLayout *layout)
1578 GtkTreeViewColumn *tree_column = GTK_TREE_VIEW_COLUMN (layout);
1579 GList *retval = NULL, *list;
1581 g_return_val_if_fail (tree_column != NULL, NULL);
1583 for (list = tree_column->cell_list; list; list = list->next)
1585 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1587 retval = g_list_append (retval, info->cell);
1594 * gtk_tree_view_column_get_cell_renderers:
1595 * @tree_column: A #GtkTreeViewColumn
1597 * Returns a newly-allocated #GList of all the cell renderers in the column,
1598 * in no particular order. The list must be freed with g_list_free().
1600 * Return value: A list of #GtkCellRenderers
1602 * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead.
1605 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1607 return gtk_tree_view_column_cell_layout_get_cells (GTK_CELL_LAYOUT (tree_column));
1611 * gtk_tree_view_column_add_attribute:
1612 * @tree_column: A #GtkTreeViewColumn.
1613 * @cell_renderer: the #GtkCellRenderer to set attributes on
1614 * @attribute: An attribute on the renderer
1615 * @column: The column position on the model to get the attribute from.
1617 * Adds an attribute mapping to the list in @tree_column. The @column is the
1618 * column of the model to get a value from, and the @attribute is the
1619 * parameter on @cell_renderer to be set from the value. So for example
1620 * if column 2 of the model contains strings, you could have the
1621 * "text" attribute of a #GtkCellRendererText get its values from
1625 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1626 GtkCellRenderer *cell_renderer,
1627 const gchar *attribute,
1630 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tree_column),
1631 cell_renderer, attribute, column);
1635 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1636 GtkCellRenderer *cell_renderer,
1642 attribute = va_arg (args, gchar *);
1644 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1646 while (attribute != NULL)
1648 column = va_arg (args, gint);
1649 gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1650 attribute = va_arg (args, gchar *);
1655 * gtk_tree_view_column_set_attributes:
1656 * @tree_column: A #GtkTreeViewColumn.
1657 * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1658 * @Varargs: A %NULL-terminated list of attributes.
1660 * Sets the attributes in the list as the attributes of @tree_column.
1661 * The attributes should be in attribute/column order, as in
1662 * gtk_tree_view_column_add_attribute(). All existing attributes
1663 * are removed, and replaced with the new attributes.
1666 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1667 GtkCellRenderer *cell_renderer,
1672 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1673 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1674 g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1676 va_start (args, cell_renderer);
1677 gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1683 * gtk_tree_view_column_set_cell_data_func:
1684 * @tree_column: A #GtkTreeViewColumn
1685 * @cell_renderer: A #GtkCellRenderer
1686 * @func: The #GtkTreeViewColumnFunc to use.
1687 * @func_data: The user data for @func.
1688 * @destroy: The destroy notification for @func_data
1690 * Sets the #GtkTreeViewColumnFunc to use for the column. This
1691 * function is used instead of the standard attributes mapping for
1692 * setting the column value, and should set the value of @tree_column's
1693 * cell renderer as appropriate. @func may be %NULL to remove an
1697 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
1698 GtkCellRenderer *cell_renderer,
1699 GtkTreeCellDataFunc func,
1701 GDestroyNotify destroy)
1703 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (tree_column),
1705 (GtkCellLayoutDataFunc)func,
1706 func_data, destroy);
1711 * gtk_tree_view_column_clear_attributes:
1712 * @tree_column: a #GtkTreeViewColumn
1713 * @cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1715 * Clears all existing attributes previously set with
1716 * gtk_tree_view_column_set_attributes().
1719 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1720 GtkCellRenderer *cell_renderer)
1722 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (tree_column),
1727 * gtk_tree_view_column_set_spacing:
1728 * @tree_column: A #GtkTreeViewColumn.
1729 * @spacing: distance between cell renderers in pixels.
1731 * Sets the spacing field of @tree_column, which is the number of pixels to
1732 * place between cell renderers packed into it.
1735 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1738 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1739 g_return_if_fail (spacing >= 0);
1741 if (tree_column->spacing == spacing)
1744 tree_column->spacing = spacing;
1745 if (tree_column->tree_view)
1746 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1750 * gtk_tree_view_column_get_spacing:
1751 * @tree_column: A #GtkTreeViewColumn.
1753 * Returns the spacing of @tree_column.
1755 * Return value: the spacing of @tree_column.
1758 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1760 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1762 return tree_column->spacing;
1765 /* Options for manipulating the columns */
1768 * gtk_tree_view_column_set_visible:
1769 * @tree_column: A #GtkTreeViewColumn.
1770 * @visible: %TRUE if the @tree_column is visible.
1772 * Sets the visibility of @tree_column.
1775 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1778 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1780 visible = !! visible;
1782 if (tree_column->visible == visible)
1785 tree_column->visible = visible;
1787 if (tree_column->visible)
1788 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1790 gtk_tree_view_column_update_button (tree_column);
1791 g_object_notify (G_OBJECT (tree_column), "visible");
1795 * gtk_tree_view_column_get_visible:
1796 * @tree_column: A #GtkTreeViewColumn.
1798 * Returns %TRUE if @tree_column is visible.
1800 * Return value: whether the column is visible or not. If it is visible, then
1801 * the tree will show the column.
1804 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1806 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1808 return tree_column->visible;
1812 * gtk_tree_view_column_set_resizable:
1813 * @tree_column: A #GtkTreeViewColumn
1814 * @resizable: %TRUE, if the column can be resized
1816 * If @resizable is %TRUE, then the user can explicitly resize the column by
1817 * grabbing the outer edge of the column button. If resizable is %TRUE and
1818 * sizing mode of the column is #GTK_TREE_VIEW_COLUMN_AUTOSIZE, then the sizing
1819 * mode is changed to #GTK_TREE_VIEW_COLUMN_GROW_ONLY.
1822 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1825 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1827 resizable = !! resizable;
1829 if (tree_column->resizable == resizable)
1832 tree_column->resizable = resizable;
1834 if (resizable && tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1835 gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1837 gtk_tree_view_column_update_button (tree_column);
1839 g_object_notify (G_OBJECT (tree_column), "resizable");
1843 * gtk_tree_view_column_get_resizable:
1844 * @tree_column: A #GtkTreeViewColumn
1846 * Returns %TRUE if the @tree_column can be resized by the end user.
1848 * Return value: %TRUE, if the @tree_column can be resized.
1851 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1853 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1855 return tree_column->resizable;
1860 * gtk_tree_view_column_set_sizing:
1861 * @tree_column: A #GtkTreeViewColumn.
1862 * @type: The #GtkTreeViewColumnSizing.
1864 * Sets the growth behavior of @tree_column to @type.
1867 gtk_tree_view_column_set_sizing (GtkTreeViewColumn *tree_column,
1868 GtkTreeViewColumnSizing type)
1870 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1872 if (type == tree_column->column_type)
1875 if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1876 gtk_tree_view_column_set_resizable (tree_column, FALSE);
1879 /* I was clearly on crack when I wrote this. I'm not sure what's supposed to
1880 * be below so I'll leave it until I figure it out.
1882 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1883 tree_column->requested_width != -1)
1885 gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1888 tree_column->column_type = type;
1890 gtk_tree_view_column_update_button (tree_column);
1892 g_object_notify (G_OBJECT (tree_column), "sizing");
1896 * gtk_tree_view_column_get_sizing:
1897 * @tree_column: A #GtkTreeViewColumn.
1899 * Returns the current type of @tree_column.
1901 * Return value: The type of @tree_column.
1903 GtkTreeViewColumnSizing
1904 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1906 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1908 return tree_column->column_type;
1912 * gtk_tree_view_column_get_width:
1913 * @tree_column: A #GtkTreeViewColumn.
1915 * Returns the current size of @tree_column in pixels.
1917 * Return value: The current width of @tree_column.
1920 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1922 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1924 return tree_column->width;
1928 * gtk_tree_view_column_set_fixed_width:
1929 * @tree_column: A #GtkTreeViewColumn.
1930 * @fixed_width: The size to set @tree_column to. Must be greater than 0.
1932 * Sets the size of the column in pixels. This is meaningful only if the sizing
1933 * type is #GTK_TREE_VIEW_COLUMN_FIXED. The size of the column is clamped to
1934 * the min/max width for the column. Please note that the min/max width of the
1935 * column doesn't actually affect the "fixed_width" property of the widget, just
1936 * the actual size when displayed.
1939 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1942 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1943 g_return_if_fail (fixed_width > 0);
1945 tree_column->fixed_width = fixed_width;
1946 tree_column->use_resized_width = FALSE;
1948 if (tree_column->tree_view &&
1949 gtk_widget_get_realized (tree_column->tree_view) &&
1950 tree_column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
1952 gtk_widget_queue_resize (tree_column->tree_view);
1955 g_object_notify (G_OBJECT (tree_column), "fixed-width");
1959 * gtk_tree_view_column_get_fixed_width:
1960 * @tree_column: a #GtkTreeViewColumn
1962 * Gets the fixed width of the column. This value is only meaning may not be
1963 * the actual width of the column on the screen, just what is requested.
1965 * Return value: the fixed width of the column
1968 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1970 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1972 return tree_column->fixed_width;
1976 * gtk_tree_view_column_set_min_width:
1977 * @tree_column: A #GtkTreeViewColumn.
1978 * @min_width: The minimum width of the column in pixels, or -1.
1980 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
1981 * minimum width is unset.
1984 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1987 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1988 g_return_if_fail (min_width >= -1);
1990 if (min_width == tree_column->min_width)
1993 if (tree_column->visible &&
1994 tree_column->tree_view != NULL &&
1995 gtk_widget_get_realized (tree_column->tree_view))
1997 if (min_width > tree_column->width)
1998 gtk_widget_queue_resize (tree_column->tree_view);
2001 tree_column->min_width = min_width;
2002 g_object_freeze_notify (G_OBJECT (tree_column));
2003 if (tree_column->max_width != -1 && tree_column->max_width < min_width)
2005 tree_column->max_width = min_width;
2006 g_object_notify (G_OBJECT (tree_column), "max-width");
2008 g_object_notify (G_OBJECT (tree_column), "min-width");
2009 g_object_thaw_notify (G_OBJECT (tree_column));
2011 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2012 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (tree_column->tree_view),
2017 * gtk_tree_view_column_get_min_width:
2018 * @tree_column: A #GtkTreeViewColumn.
2020 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
2023 * Return value: The minimum width of the @tree_column.
2026 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
2028 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2030 return tree_column->min_width;
2034 * gtk_tree_view_column_set_max_width:
2035 * @tree_column: A #GtkTreeViewColumn.
2036 * @max_width: The maximum width of the column in pixels, or -1.
2038 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
2039 * maximum width is unset. Note, the column can actually be wider than max
2040 * width if it's the last column in a view. In this case, the column expands to
2041 * fill any extra space.
2044 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
2047 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2048 g_return_if_fail (max_width >= -1);
2050 if (max_width == tree_column->max_width)
2053 if (tree_column->visible &&
2054 tree_column->tree_view != NULL &&
2055 gtk_widget_get_realized (tree_column->tree_view))
2057 if (max_width != -1 && max_width < tree_column->width)
2058 gtk_widget_queue_resize (tree_column->tree_view);
2061 tree_column->max_width = max_width;
2062 g_object_freeze_notify (G_OBJECT (tree_column));
2063 if (max_width != -1 && max_width < tree_column->min_width)
2065 tree_column->min_width = max_width;
2066 g_object_notify (G_OBJECT (tree_column), "min-width");
2068 g_object_notify (G_OBJECT (tree_column), "max-width");
2069 g_object_thaw_notify (G_OBJECT (tree_column));
2071 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2072 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (tree_column->tree_view),
2077 * gtk_tree_view_column_get_max_width:
2078 * @tree_column: A #GtkTreeViewColumn.
2080 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
2083 * Return value: The maximum width of the @tree_column.
2086 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
2088 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2090 return tree_column->max_width;
2094 * gtk_tree_view_column_clicked:
2095 * @tree_column: a #GtkTreeViewColumn
2097 * Emits the "clicked" signal on the column. This function will only work if
2098 * @tree_column is clickable.
2101 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
2103 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2105 if (tree_column->visible &&
2106 tree_column->button &&
2107 tree_column->clickable)
2108 gtk_button_clicked (GTK_BUTTON (tree_column->button));
2112 * gtk_tree_view_column_set_title:
2113 * @tree_column: A #GtkTreeViewColumn.
2114 * @title: The title of the @tree_column.
2116 * Sets the title of the @tree_column. If a custom widget has been set, then
2117 * this value is ignored.
2120 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
2125 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2127 new_title = g_strdup (title);
2128 g_free (tree_column->title);
2129 tree_column->title = new_title;
2131 gtk_tree_view_column_update_button (tree_column);
2132 g_object_notify (G_OBJECT (tree_column), "title");
2136 * gtk_tree_view_column_get_title:
2137 * @tree_column: A #GtkTreeViewColumn.
2139 * Returns the title of the widget.
2141 * Return value: the title of the column. This string should not be
2142 * modified or freed.
2144 G_CONST_RETURN gchar *
2145 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
2147 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2149 return tree_column->title;
2153 * gtk_tree_view_column_set_expand:
2154 * @tree_column: A #GtkTreeViewColumn
2155 * @expand: %TRUE if the column should take available extra space, %FALSE if not
2157 * Sets the column to take available extra space. This space is shared equally
2158 * amongst all columns that have the expand set to %TRUE. If no column has this
2159 * option set, then the last column gets all extra space. By default, every
2160 * column is created with this %FALSE.
2165 gtk_tree_view_column_set_expand (GtkTreeViewColumn *tree_column,
2168 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2170 expand = expand?TRUE:FALSE;
2171 if (tree_column->expand == expand)
2173 tree_column->expand = expand;
2175 if (tree_column->visible &&
2176 tree_column->tree_view != NULL &&
2177 gtk_widget_get_realized (tree_column->tree_view))
2179 /* We want to continue using the original width of the
2180 * column that includes additional space added by the user
2181 * resizing the columns and possibly extra (expanded) space, which
2182 * are not included in the resized width.
2184 tree_column->use_resized_width = FALSE;
2186 gtk_widget_queue_resize (tree_column->tree_view);
2189 g_object_notify (G_OBJECT (tree_column), "expand");
2193 * gtk_tree_view_column_get_expand:
2194 * @tree_column: a #GtkTreeViewColumn
2196 * Return %TRUE if the column expands to take any available space.
2198 * Return value: %TRUE, if the column expands
2203 gtk_tree_view_column_get_expand (GtkTreeViewColumn *tree_column)
2205 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2207 return tree_column->expand;
2211 * gtk_tree_view_column_set_clickable:
2212 * @tree_column: A #GtkTreeViewColumn.
2213 * @clickable: %TRUE if the header is active.
2215 * Sets the header to be active if @active is %TRUE. When the header is active,
2216 * then it can take keyboard focus, and can be clicked.
2219 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
2222 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2224 clickable = !! clickable;
2225 if (tree_column->clickable == clickable)
2228 tree_column->clickable = clickable;
2229 gtk_tree_view_column_update_button (tree_column);
2230 g_object_notify (G_OBJECT (tree_column), "clickable");
2234 * gtk_tree_view_column_get_clickable:
2235 * @tree_column: a #GtkTreeViewColumn
2237 * Returns %TRUE if the user can click on the header for the column.
2239 * Return value: %TRUE if user can click the column header.
2242 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
2244 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2246 return tree_column->clickable;
2250 * gtk_tree_view_column_set_widget:
2251 * @tree_column: A #GtkTreeViewColumn.
2252 * @widget: (allow-none): A child #GtkWidget, or %NULL.
2254 * Sets the widget in the header to be @widget. If widget is %NULL, then the
2255 * header button is set with a #GtkLabel set to the title of @tree_column.
2258 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
2261 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2262 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
2265 g_object_ref_sink (widget);
2267 if (tree_column->child)
2268 g_object_unref (tree_column->child);
2270 tree_column->child = widget;
2271 gtk_tree_view_column_update_button (tree_column);
2272 g_object_notify (G_OBJECT (tree_column), "widget");
2276 * gtk_tree_view_column_get_widget:
2277 * @tree_column: A #GtkTreeViewColumn.
2279 * Returns the #GtkWidget in the button on the column header. If a custom
2280 * widget has not been set then %NULL is returned.
2282 * Return value: The #GtkWidget in the column header, or %NULL
2285 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
2287 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2289 return tree_column->child;
2293 * gtk_tree_view_column_set_alignment:
2294 * @tree_column: A #GtkTreeViewColumn.
2295 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
2297 * Sets the alignment of the title or custom widget inside the column header.
2298 * The alignment determines its location inside the button -- 0.0 for left, 0.5
2299 * for center, 1.0 for right.
2302 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
2305 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2307 xalign = CLAMP (xalign, 0.0, 1.0);
2309 if (tree_column->xalign == xalign)
2312 tree_column->xalign = xalign;
2313 gtk_tree_view_column_update_button (tree_column);
2314 g_object_notify (G_OBJECT (tree_column), "alignment");
2318 * gtk_tree_view_column_get_alignment:
2319 * @tree_column: A #GtkTreeViewColumn.
2321 * Returns the current x alignment of @tree_column. This value can range
2322 * between 0.0 and 1.0.
2324 * Return value: The current alignent of @tree_column.
2327 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
2329 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
2331 return tree_column->xalign;
2335 * gtk_tree_view_column_set_reorderable:
2336 * @tree_column: A #GtkTreeViewColumn
2337 * @reorderable: %TRUE, if the column can be reordered.
2339 * If @reorderable is %TRUE, then the column can be reordered by the end user
2340 * dragging the header.
2343 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
2344 gboolean reorderable)
2346 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2349 gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
2351 if (tree_column->reorderable == (reorderable?TRUE:FALSE))
2354 tree_column->reorderable = (reorderable?TRUE:FALSE);
2355 gtk_tree_view_column_update_button (tree_column);
2356 g_object_notify (G_OBJECT (tree_column), "reorderable");
2360 * gtk_tree_view_column_get_reorderable:
2361 * @tree_column: A #GtkTreeViewColumn
2363 * Returns %TRUE if the @tree_column can be reordered by the user.
2365 * Return value: %TRUE if the @tree_column can be reordered by the user.
2368 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
2370 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2372 return tree_column->reorderable;
2377 * gtk_tree_view_column_set_sort_column_id:
2378 * @tree_column: a #GtkTreeViewColumn
2379 * @sort_column_id: The @sort_column_id of the model to sort on.
2381 * Sets the logical @sort_column_id that this column sorts on when this column
2382 * is selected for sorting. Doing so makes the column header clickable.
2385 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
2386 gint sort_column_id)
2388 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2389 g_return_if_fail (sort_column_id >= -1);
2391 if (tree_column->sort_column_id == sort_column_id)
2394 tree_column->sort_column_id = sort_column_id;
2396 /* Handle unsetting the id */
2397 if (sort_column_id == -1)
2399 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
2401 if (tree_column->sort_clicked_signal)
2403 g_signal_handler_disconnect (tree_column, tree_column->sort_clicked_signal);
2404 tree_column->sort_clicked_signal = 0;
2407 if (tree_column->sort_column_changed_signal)
2409 g_signal_handler_disconnect (model, tree_column->sort_column_changed_signal);
2410 tree_column->sort_column_changed_signal = 0;
2413 gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2414 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
2415 gtk_tree_view_column_set_clickable (tree_column, FALSE);
2416 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2420 gtk_tree_view_column_set_clickable (tree_column, TRUE);
2422 if (! tree_column->sort_clicked_signal)
2423 tree_column->sort_clicked_signal = g_signal_connect (tree_column,
2425 G_CALLBACK (gtk_tree_view_column_sort),
2428 gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
2429 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2433 * gtk_tree_view_column_get_sort_column_id:
2434 * @tree_column: a #GtkTreeViewColumn
2436 * Gets the logical @sort_column_id that the model sorts on when this
2437 * column is selected for sorting.
2438 * See gtk_tree_view_column_set_sort_column_id().
2440 * Return value: the current @sort_column_id for this column, or -1 if
2441 * this column can't be used for sorting.
2444 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
2446 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2448 return tree_column->sort_column_id;
2452 * gtk_tree_view_column_set_sort_indicator:
2453 * @tree_column: a #GtkTreeViewColumn
2454 * @setting: %TRUE to display an indicator that the column is sorted
2456 * Call this function with a @setting of %TRUE to display an arrow in
2457 * the header button indicating the column is sorted. Call
2458 * gtk_tree_view_column_set_sort_order() to change the direction of
2463 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
2466 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2468 setting = setting != FALSE;
2470 if (setting == tree_column->show_sort_indicator)
2473 tree_column->show_sort_indicator = setting;
2474 gtk_tree_view_column_update_button (tree_column);
2475 g_object_notify (G_OBJECT (tree_column), "sort-indicator");
2479 * gtk_tree_view_column_get_sort_indicator:
2480 * @tree_column: a #GtkTreeViewColumn
2482 * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2484 * Return value: whether the sort indicator arrow is displayed
2487 gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
2489 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2491 return tree_column->show_sort_indicator;
2495 * gtk_tree_view_column_set_sort_order:
2496 * @tree_column: a #GtkTreeViewColumn
2497 * @order: sort order that the sort indicator should indicate
2499 * Changes the appearance of the sort indicator.
2501 * This <emphasis>does not</emphasis> actually sort the model. Use
2502 * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2503 * support. This function is primarily for custom sorting behavior, and should
2504 * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2505 * that. For custom models, the mechanism will vary.
2507 * The sort indicator changes direction to indicate normal sort or reverse sort.
2508 * Note that you must have the sort indicator enabled to see anything when
2509 * calling this function; see gtk_tree_view_column_set_sort_indicator().
2512 gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
2515 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2517 if (order == tree_column->sort_order)
2520 tree_column->sort_order = order;
2521 gtk_tree_view_column_update_button (tree_column);
2522 g_object_notify (G_OBJECT (tree_column), "sort-order");
2526 * gtk_tree_view_column_get_sort_order:
2527 * @tree_column: a #GtkTreeViewColumn
2529 * Gets the value set by gtk_tree_view_column_set_sort_order().
2531 * Return value: the sort order the sort indicator is indicating
2534 gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
2536 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2538 return tree_column->sort_order;
2542 * gtk_tree_view_column_cell_set_cell_data:
2543 * @tree_column: A #GtkTreeViewColumn.
2544 * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2545 * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2546 * @is_expander: %TRUE, if the row has children
2547 * @is_expanded: %TRUE, if the row has visible children
2549 * Sets the cell renderer based on the @tree_model and @iter. That is, for
2550 * every attribute mapping in @tree_column, it will get a value from the set
2551 * column on the @iter, and use that value to set the attribute on the cell
2552 * renderer. This is used primarily by the #GtkTreeView.
2555 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2556 GtkTreeModel *tree_model,
2558 gboolean is_expander,
2559 gboolean is_expanded)
2562 GValue value = { 0, };
2565 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2567 if (tree_model == NULL)
2570 for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2572 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2573 GObject *cell = (GObject *) info->cell;
2575 list = info->attributes;
2577 g_object_freeze_notify (cell);
2579 if (info->cell->is_expander != is_expander)
2580 g_object_set (cell, "is-expander", is_expander, NULL);
2582 if (info->cell->is_expanded != is_expanded)
2583 g_object_set (cell, "is-expanded", is_expanded, NULL);
2585 while (list && list->next)
2587 gtk_tree_model_get_value (tree_model, iter,
2588 GPOINTER_TO_INT (list->next->data),
2590 g_object_set_property (cell, (gchar *) list->data, &value);
2591 g_value_unset (&value);
2592 list = list->next->next;
2596 (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2597 g_object_thaw_notify (G_OBJECT (info->cell));
2603 gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn *tree_column,
2604 const GdkRectangle *cell_area,
2607 GtkRequisition *minimal_size,
2608 GtkRequisition *desired_size)
2611 gboolean first_cell = TRUE;
2612 gint focus_line_width;
2614 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2618 minimal_size->height = 0;
2619 minimal_size->width = 0;
2624 desired_size->height = 0;
2625 desired_size->width = 0;
2628 gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
2630 for (list = tree_column->cell_list; list; list = list->next)
2632 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2634 GtkRequisition min_req, nat_req;
2636 g_object_get (info->cell, "visible", &visible, NULL);
2638 if (visible == FALSE)
2641 if (first_cell == FALSE)
2643 min_req.width += tree_column->spacing;
2644 nat_req.width += tree_column->spacing;
2647 /* XXX TODO: Cell renderers are not really doing height-for-width yet.
2649 gtk_extended_cell_get_desired_width (GTK_EXTENDED_CELL (info->cell),
2650 tree_column->tree_view,
2651 &min_req.width, &nat_req.width);
2652 gtk_extended_cell_get_height_for_width (GTK_EXTENDED_CELL (info->cell),
2653 tree_column->tree_view,
2655 &min_req.height, &nat_req.height);
2657 min_req.width += focus_line_width * 2;
2658 min_req.height += focus_line_width * 2;
2659 nat_req.width += focus_line_width * 2;
2660 nat_req.height += focus_line_width * 2;
2662 info->requested_width = MAX (info->requested_width, min_req.width);
2667 *minimal_size = min_req;
2670 *desired_size = nat_req;
2676 * gtk_tree_view_column_cell_get_size:
2677 * @tree_column: A #GtkTreeViewColumn.
2678 * @cell_area: (allow-none): The area a cell in the column will be allocated, or %NULL
2679 * @x_offset: (allow-none): location to return x offset of a cell relative to @cell_area, or %NULL
2680 * @y_offset: (allow-none): location to return y offset of a cell relative to @cell_area, or %NULL
2681 * @width: (allow-none): location to return width needed to render a cell, or %NULL
2682 * @height: (allow-none): location to return height needed to render a cell, or %NULL
2684 * Obtains the width and height needed to render the column. This is used
2685 * primarily by the #GtkTreeView.
2688 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2689 const GdkRectangle *cell_area,
2695 GtkRequisition min_req;
2697 gtk_tree_view_column_cell_get_real_size (tree_column, cell_area,
2698 x_offset, y_offset, &min_req, NULL);
2701 *width = min_req.width;
2704 *height = min_req.height;
2707 /* rendering, event handling and rendering focus are somewhat complicated, and
2708 * quite a bit of code. Rather than duplicate them, we put them together to
2709 * keep the code in one place.
2711 * To better understand what's going on, check out
2712 * docs/tree-column-sizing.png
2721 gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column,
2723 const GdkRectangle *background_area,
2724 const GdkRectangle *cell_area,
2727 const GdkRectangle *expose_area, /* RENDER */
2728 GdkRectangle *focus_rectangle, /* FOCUS */
2729 GtkCellEditable **editable_widget, /* EVENT */
2730 GdkEvent *event, /* EVENT */
2731 gchar *path_string) /* EVENT */
2734 GdkRectangle real_cell_area;
2735 GdkRectangle real_background_area;
2736 GdkRectangle real_expose_area = *cell_area;
2738 gint expand_cell_count = 0;
2739 gint full_requested_width = 0;
2741 gint min_x, min_y, max_x, max_y;
2742 gint focus_line_width;
2744 gint horizontal_separator;
2745 gboolean cursor_row = FALSE;
2746 gboolean first_cell = TRUE;
2748 /* If we have rtl text, we need to transform our areas */
2749 GdkRectangle rtl_cell_area;
2750 GdkRectangle rtl_background_area;
2757 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL);
2758 special_cells = _gtk_tree_view_column_count_special_cells (tree_column);
2760 if (special_cells > 1 && action == CELL_ACTION_FOCUS)
2762 GtkTreeViewColumnCellInfo *info = NULL;
2763 gboolean found_has_focus = FALSE;
2765 /* one should have focus */
2766 for (list = tree_column->cell_list; list; list = list->next)
2769 if (info && info->has_focus)
2771 found_has_focus = TRUE;
2776 if (!found_has_focus)
2778 /* give the first one focus */
2779 info = gtk_tree_view_column_cell_first (tree_column)->data;
2780 info->has_focus = TRUE;
2784 cursor_row = flags & GTK_CELL_RENDERER_FOCUSED;
2786 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
2787 "focus-line-width", &focus_line_width,
2788 "horizontal-separator", &horizontal_separator,
2791 real_cell_area = *cell_area;
2792 real_background_area = *background_area;
2795 real_cell_area.x += focus_line_width;
2796 real_cell_area.y += focus_line_width;
2797 real_cell_area.height -= 2 * focus_line_width;
2800 depth = real_background_area.width - real_cell_area.width;
2802 depth = real_cell_area.x - real_background_area.x;
2804 /* Find out how much extra space we have to allocate */
2805 for (list = tree_column->cell_list; list; list = list->next)
2807 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
2809 if (! info->cell->visible)
2812 if (info->expand == TRUE)
2813 expand_cell_count ++;
2814 full_requested_width += info->requested_width;
2817 full_requested_width += tree_column->spacing;
2822 extra_space = cell_area->width - full_requested_width;
2823 if (extra_space < 0)
2825 else if (extra_space > 0 && expand_cell_count > 0)
2826 extra_space /= expand_cell_count;
2828 /* iterate list for GTK_PACK_START cells */
2829 for (list = tree_column->cell_list; list; list = list->next)
2831 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2833 if (info->pack == GTK_PACK_END)
2836 if (! info->cell->visible)
2839 if ((info->has_focus || special_cells == 1) && cursor_row)
2840 flags |= GTK_CELL_RENDERER_FOCUSED;
2842 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2844 info->real_width = info->requested_width + (info->expand?extra_space:0);
2846 /* We constrain ourselves to only the width available */
2847 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
2849 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
2852 if (real_cell_area.x > cell_area->x + cell_area->width)
2855 real_cell_area.width = info->real_width;
2856 real_cell_area.width -= 2 * focus_line_width;
2860 real_background_area.width = info->real_width + depth;
2864 /* fill the rest of background for the last cell */
2865 real_background_area.width = background_area->x + background_area->width - real_background_area.x;
2868 rtl_cell_area = real_cell_area;
2869 rtl_background_area = real_background_area;
2873 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
2874 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
2878 if (action == CELL_ACTION_RENDER)
2880 gtk_cell_renderer_render (info->cell,
2882 tree_column->tree_view,
2883 &rtl_background_area,
2889 else if (action == CELL_ACTION_FOCUS)
2891 gint x_offset, y_offset, width, height;
2893 gtk_cell_renderer_get_size (info->cell,
2894 tree_column->tree_view,
2896 &x_offset, &y_offset,
2899 if (special_cells > 1)
2901 if (info->has_focus)
2903 min_x = rtl_cell_area.x + x_offset;
2904 max_x = min_x + width;
2905 min_y = rtl_cell_area.y + y_offset;
2906 max_y = min_y + height;
2911 if (min_x > (rtl_cell_area.x + x_offset))
2912 min_x = rtl_cell_area.x + x_offset;
2913 if (max_x < rtl_cell_area.x + x_offset + width)
2914 max_x = rtl_cell_area.x + x_offset + width;
2915 if (min_y > (rtl_cell_area.y + y_offset))
2916 min_y = rtl_cell_area.y + y_offset;
2917 if (max_y < rtl_cell_area.y + y_offset + height)
2918 max_y = rtl_cell_area.y + y_offset + height;
2922 else if (action == CELL_ACTION_EVENT)
2924 gboolean try_event = FALSE;
2928 if (special_cells == 1)
2930 /* only 1 activatable cell -> whole column can activate */
2931 if (cell_area->x <= ((GdkEventButton *)event)->x &&
2932 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
2935 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
2936 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
2937 /* only activate cell if the user clicked on an individual
2942 else if (special_cells > 1 && info->has_focus)
2944 else if (special_cells == 1)
2949 gboolean visible, mode;
2951 g_object_get (info->cell,
2952 "visible", &visible,
2955 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2957 if (gtk_cell_renderer_activate (info->cell,
2959 tree_column->tree_view,
2961 &rtl_background_area,
2965 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2969 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2972 gtk_cell_renderer_start_editing (info->cell,
2974 tree_column->tree_view,
2976 &rtl_background_area,
2980 if (*editable_widget != NULL)
2982 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2983 info->in_editing_mode = TRUE;
2984 gtk_tree_view_column_focus_cell (tree_column, info->cell);
2986 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2994 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2996 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
2997 real_background_area.x += real_background_area.width + tree_column->spacing;
2999 /* Only needed for first cell */
3003 /* iterate list for PACK_END cells */
3004 for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
3006 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
3008 if (info->pack == GTK_PACK_START)
3011 if (! info->cell->visible)
3014 if ((info->has_focus || special_cells == 1) && cursor_row)
3015 flags |= GTK_CELL_RENDERER_FOCUSED;
3017 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3019 info->real_width = info->requested_width + (info->expand?extra_space:0);
3021 /* We constrain ourselves to only the width available */
3022 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
3024 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
3027 if (real_cell_area.x > cell_area->x + cell_area->width)
3030 real_cell_area.width = info->real_width;
3031 real_cell_area.width -= 2 * focus_line_width;
3032 real_background_area.width = info->real_width + depth;
3034 rtl_cell_area = real_cell_area;
3035 rtl_background_area = real_background_area;
3038 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
3039 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
3043 if (action == CELL_ACTION_RENDER)
3045 gtk_cell_renderer_render (info->cell,
3047 tree_column->tree_view,
3048 &rtl_background_area,
3054 else if (action == CELL_ACTION_FOCUS)
3056 gint x_offset, y_offset, width, height;
3058 gtk_cell_renderer_get_size (info->cell,
3059 tree_column->tree_view,
3061 &x_offset, &y_offset,
3064 if (special_cells > 1)
3066 if (info->has_focus)
3068 min_x = rtl_cell_area.x + x_offset;
3069 max_x = min_x + width;
3070 min_y = rtl_cell_area.y + y_offset;
3071 max_y = min_y + height;
3076 if (min_x > (rtl_cell_area.x + x_offset))
3077 min_x = rtl_cell_area.x + x_offset;
3078 if (max_x < rtl_cell_area.x + x_offset + width)
3079 max_x = rtl_cell_area.x + x_offset + width;
3080 if (min_y > (rtl_cell_area.y + y_offset))
3081 min_y = rtl_cell_area.y + y_offset;
3082 if (max_y < rtl_cell_area.y + y_offset + height)
3083 max_y = rtl_cell_area.y + y_offset + height;
3087 else if (action == CELL_ACTION_EVENT)
3089 gboolean try_event = FALSE;
3093 if (special_cells == 1)
3095 /* only 1 activatable cell -> whole column can activate */
3096 if (cell_area->x <= ((GdkEventButton *)event)->x &&
3097 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
3100 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
3101 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
3102 /* only activate cell if the user clicked on an individual
3107 else if (special_cells > 1 && info->has_focus)
3109 else if (special_cells == 1)
3114 gboolean visible, mode;
3116 g_object_get (info->cell,
3117 "visible", &visible,
3120 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
3122 if (gtk_cell_renderer_activate (info->cell,
3124 tree_column->tree_view,
3126 &rtl_background_area,
3130 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3134 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
3137 gtk_cell_renderer_start_editing (info->cell,
3139 tree_column->tree_view,
3141 &rtl_background_area,
3145 if (*editable_widget != NULL)
3147 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
3148 info->in_editing_mode = TRUE;
3149 gtk_tree_view_column_focus_cell (tree_column, info->cell);
3151 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3158 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3160 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
3161 real_background_area.x += (real_background_area.width + tree_column->spacing);
3163 /* Only needed for first cell */
3167 /* fill focus_rectangle when required */
3168 if (action == CELL_ACTION_FOCUS)
3170 if (min_x >= max_x || min_y >= max_y)
3172 *focus_rectangle = *cell_area;
3173 /* don't change the focus_rectangle, just draw it nicely inside
3178 focus_rectangle->x = min_x - focus_line_width;
3179 focus_rectangle->y = min_y - focus_line_width;
3180 focus_rectangle->width = (max_x - min_x) + 2 * focus_line_width;
3181 focus_rectangle->height = (max_y - min_y) + 2 * focus_line_width;
3189 * gtk_tree_view_column_cell_render:
3190 * @tree_column: A #GtkTreeViewColumn.
3191 * @window: a #GdkDrawable to draw to
3192 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
3193 * @cell_area: area normally rendered by a cell renderer
3194 * @expose_area: area that actually needs updating
3195 * @flags: flags that affect rendering
3197 * Renders the cell contained by #tree_column. This is used primarily by the
3201 _gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
3203 const GdkRectangle *background_area,
3204 const GdkRectangle *cell_area,
3205 const GdkRectangle *expose_area,
3208 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3209 g_return_if_fail (background_area != NULL);
3210 g_return_if_fail (cell_area != NULL);
3211 g_return_if_fail (expose_area != NULL);
3213 gtk_tree_view_column_cell_process_action (tree_column,
3220 NULL, NULL, NULL, NULL);
3224 _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
3225 GtkCellEditable **editable_widget,
3228 const GdkRectangle *background_area,
3229 const GdkRectangle *cell_area,
3232 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
3234 return gtk_tree_view_column_cell_process_action (tree_column,
3247 _gtk_tree_view_column_get_focus_area (GtkTreeViewColumn *tree_column,
3248 const GdkRectangle *background_area,
3249 const GdkRectangle *cell_area,
3250 GdkRectangle *focus_area)
3252 gtk_tree_view_column_cell_process_action (tree_column,
3264 /* cell list manipulation */
3266 gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column)
3268 GList *list = tree_column->cell_list;
3270 /* first GTK_PACK_START cell we find */
3271 for ( ; list; list = list->next)
3273 GtkTreeViewColumnCellInfo *info = list->data;
3274 if (info->pack == GTK_PACK_START)
3278 /* hmm, else the *last* GTK_PACK_END cell */
3279 list = g_list_last (tree_column->cell_list);
3281 for ( ; list; list = list->prev)
3283 GtkTreeViewColumnCellInfo *info = list->data;
3284 if (info->pack == GTK_PACK_END)
3292 gtk_tree_view_column_cell_last (GtkTreeViewColumn *tree_column)
3294 GList *list = tree_column->cell_list;
3296 /* *first* GTK_PACK_END cell we find */
3297 for ( ; list ; list = list->next)
3299 GtkTreeViewColumnCellInfo *info = list->data;
3300 if (info->pack == GTK_PACK_END)
3304 /* hmm, else the last GTK_PACK_START cell */
3305 list = g_list_last (tree_column->cell_list);
3307 for ( ; list; list = list->prev)
3309 GtkTreeViewColumnCellInfo *info = list->data;
3310 if (info->pack == GTK_PACK_START)
3318 gtk_tree_view_column_cell_next (GtkTreeViewColumn *tree_column,
3322 GtkTreeViewColumnCellInfo *info = current->data;
3324 if (info->pack == GTK_PACK_START)
3326 for (list = current->next; list; list = list->next)
3328 GtkTreeViewColumnCellInfo *inf = list->data;
3329 if (inf->pack == GTK_PACK_START)
3333 /* out of GTK_PACK_START cells, get *last* GTK_PACK_END one */
3334 list = g_list_last (tree_column->cell_list);
3335 for (; list; list = list->prev)
3337 GtkTreeViewColumnCellInfo *inf = list->data;
3338 if (inf->pack == GTK_PACK_END)
3343 for (list = current->prev; list; list = list->prev)
3345 GtkTreeViewColumnCellInfo *inf = list->data;
3346 if (inf->pack == GTK_PACK_END)
3354 gtk_tree_view_column_cell_prev (GtkTreeViewColumn *tree_column,
3358 GtkTreeViewColumnCellInfo *info = current->data;
3360 if (info->pack == GTK_PACK_END)
3362 for (list = current->next; list; list = list->next)
3364 GtkTreeViewColumnCellInfo *inf = list->data;
3365 if (inf->pack == GTK_PACK_END)
3369 /* out of GTK_PACK_END, get last GTK_PACK_START one */
3370 list = g_list_last (tree_column->cell_list);
3371 for ( ; list; list = list->prev)
3373 GtkTreeViewColumnCellInfo *inf = list->data;
3374 if (inf->pack == GTK_PACK_START)
3379 for (list = current->prev; list; list = list->prev)
3381 GtkTreeViewColumnCellInfo *inf = list->data;
3382 if (inf->pack == GTK_PACK_START)
3390 _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
3398 count = _gtk_tree_view_column_count_special_cells (tree_column);
3399 rtl = gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL;
3401 /* if we are the current focus column and have multiple editable cells,
3402 * try to select the next one, else move the focus to the next column
3404 if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
3409 GList *list = tree_column->cell_list;
3410 GtkTreeViewColumnCellInfo *info = NULL;
3412 /* find current focussed cell */
3413 for ( ; list; list = list->next)
3416 if (info->has_focus)
3420 /* not a focussed cell in the focus column? */
3421 if (!list || !info || !info->has_focus)
3426 prev = gtk_tree_view_column_cell_next (tree_column, list);
3427 next = gtk_tree_view_column_cell_prev (tree_column, list);
3431 next = gtk_tree_view_column_cell_next (tree_column, list);
3432 prev = gtk_tree_view_column_cell_prev (tree_column, list);
3435 info->has_focus = FALSE;
3436 if (direction > 0 && next)
3439 info->has_focus = TRUE;
3442 else if (direction > 0 && !next && !right)
3444 /* keep focus on last cell */
3446 info = gtk_tree_view_column_cell_first (tree_column)->data;
3448 info = gtk_tree_view_column_cell_last (tree_column)->data;
3450 info->has_focus = TRUE;
3453 else if (direction < 0 && prev)
3456 info->has_focus = TRUE;
3459 else if (direction < 0 && !prev && !left)
3461 /* keep focus on first cell */
3463 info = gtk_tree_view_column_cell_last (tree_column)->data;
3465 info = gtk_tree_view_column_cell_first (tree_column)->data;
3467 info->has_focus = TRUE;
3474 /* we get focus, if we have multiple editable cells, give the correct one
3479 GList *list = tree_column->cell_list;
3481 /* clear focus first */
3482 for ( ; list ; list = list->next)
3484 GtkTreeViewColumnCellInfo *info = list->data;
3485 if (info->has_focus)
3486 info->has_focus = FALSE;
3493 list = gtk_tree_view_column_cell_last (tree_column);
3494 else if (direction < 0)
3495 list = gtk_tree_view_column_cell_first (tree_column);
3500 list = gtk_tree_view_column_cell_first (tree_column);
3501 else if (direction < 0)
3502 list = gtk_tree_view_column_cell_last (tree_column);
3506 ((GtkTreeViewColumnCellInfo *) list->data)->has_focus = TRUE;
3513 _gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column,
3515 const GdkRectangle *background_area,
3516 const GdkRectangle *cell_area,
3517 const GdkRectangle *expose_area,
3520 gint focus_line_width;
3521 GtkStateType cell_state;
3523 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3524 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
3525 "focus-line-width", &focus_line_width, NULL);
3526 if (tree_column->editable_widget)
3528 /* This function is only called on the editable row when editing.
3531 gtk_paint_focus (tree_column->tree_view->style,
3533 gtk_widget_get_state (tree_column->tree_view),
3535 tree_column->tree_view,
3537 cell_area->x - focus_line_width,
3538 cell_area->y - focus_line_width,
3539 cell_area->width + 2 * focus_line_width,
3540 cell_area->height + 2 * focus_line_width);
3545 GdkRectangle focus_rectangle;
3546 gtk_tree_view_column_cell_process_action (tree_column,
3556 cell_state = flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
3557 (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
3558 (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL));
3559 gtk_paint_focus (tree_column->tree_view->style,
3563 tree_column->tree_view,
3567 focus_rectangle.width,
3568 focus_rectangle.height);
3573 * gtk_tree_view_column_cell_is_visible:
3574 * @tree_column: A #GtkTreeViewColumn
3576 * Returns %TRUE if any of the cells packed into the @tree_column are visible.
3577 * For this to be meaningful, you must first initialize the cells with
3578 * gtk_tree_view_column_cell_set_cell_data()
3580 * Return value: %TRUE, if any of the cells packed into the @tree_column are currently visible
3583 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
3587 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
3589 for (list = tree_column->cell_list; list; list = list->next)
3591 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
3593 if (info->cell->visible)
3601 * gtk_tree_view_column_focus_cell:
3602 * @tree_column: A #GtkTreeViewColumn
3603 * @cell: A #GtkCellRenderer
3605 * Sets the current keyboard focus to be at @cell, if the column contains
3606 * 2 or more editable and activatable cells.
3611 gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
3612 GtkCellRenderer *cell)
3615 gboolean found_cell = FALSE;
3617 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3618 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
3620 if (_gtk_tree_view_column_count_special_cells (tree_column) < 2)
3623 for (list = tree_column->cell_list; list; list = list->next)
3625 GtkTreeViewColumnCellInfo *info = list->data;
3627 if (info->cell == cell)
3629 info->has_focus = TRUE;
3637 for (list = tree_column->cell_list; list; list = list->next)
3639 GtkTreeViewColumnCellInfo *info = list->data;
3641 if (info->cell != cell)
3642 info->has_focus = FALSE;
3645 /* FIXME: redraw? */
3650 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
3651 gboolean install_handler)
3655 for (list = tree_column->cell_list; list; list = list->next)
3657 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
3659 info->requested_width = 0;
3661 tree_column->dirty = TRUE;
3662 tree_column->requested_width = -1;
3663 tree_column->width = 0;
3665 if (tree_column->tree_view &&
3666 gtk_widget_get_realized (tree_column->tree_view))
3668 if (install_handler)
3669 _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (tree_column->tree_view));
3671 GTK_TREE_VIEW (tree_column->tree_view)->priv->mark_rows_col_dirty = TRUE;
3672 gtk_widget_queue_resize (tree_column->tree_view);
3677 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
3678 GtkCellEditable *cell_editable)
3680 g_return_if_fail (tree_column->editable_widget == NULL);
3682 tree_column->editable_widget = cell_editable;
3686 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
3690 g_return_if_fail (tree_column->editable_widget != NULL);
3692 tree_column->editable_widget = NULL;
3693 for (list = tree_column->cell_list; list; list = list->next)
3694 ((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode = FALSE;
3698 _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
3699 GtkCellRenderer *cell,
3704 GtkTreeViewColumnCellInfo *info;
3710 list = gtk_tree_view_column_cell_first (column);
3714 info = (GtkTreeViewColumnCellInfo *)list->data;
3716 list = gtk_tree_view_column_cell_next (column, list);
3718 if (info->cell == cell)
3721 if (info->cell->visible)
3722 l += info->real_width + column->spacing;
3727 info = (GtkTreeViewColumnCellInfo *)list->data;
3729 list = gtk_tree_view_column_cell_next (column, list);
3731 if (info->cell->visible)
3732 r += info->real_width + column->spacing;
3735 rtl = (gtk_widget_get_direction (GTK_WIDGET (column->tree_view)) == GTK_TEXT_DIR_RTL);
3737 *left = rtl ? r : l;
3740 *right = rtl ? l : r;
3744 * gtk_tree_view_column_cell_get_position:
3745 * @tree_column: a #GtkTreeViewColumn
3746 * @cell_renderer: a #GtkCellRenderer
3747 * @start_pos: return location for the horizontal position of @cell within
3748 * @tree_column, may be %NULL
3749 * @width: return location for the width of @cell, may be %NULL
3751 * Obtains the horizontal position and size of a cell in a column. If the
3752 * cell is not found in the column, @start_pos and @width are not changed and
3753 * %FALSE is returned.
3755 * Return value: %TRUE if @cell belongs to @tree_column.
3758 gtk_tree_view_column_cell_get_position (GtkTreeViewColumn *tree_column,
3759 GtkCellRenderer *cell_renderer,
3765 gboolean found_cell = FALSE;
3766 GtkTreeViewColumnCellInfo *cellinfo = NULL;
3768 list = gtk_tree_view_column_cell_first (tree_column);
3769 for (; list; list = gtk_tree_view_column_cell_next (tree_column, list))
3771 cellinfo = list->data;
3772 if (cellinfo->cell == cell_renderer)
3778 if (cellinfo->cell->visible)
3779 current_x += cellinfo->real_width;
3785 *start_pos = current_x;
3787 *width = cellinfo->real_width;
3794 * gtk_tree_view_column_queue_resize:
3795 * @tree_column: A #GtkTreeViewColumn
3797 * Flags the column, and the cell renderers added to this column, to have
3798 * their sizes renegotiated.
3803 gtk_tree_view_column_queue_resize (GtkTreeViewColumn *tree_column)
3805 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3807 if (tree_column->tree_view)
3808 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
3812 * gtk_tree_view_column_get_tree_view:
3813 * @tree_column: A #GtkTreeViewColumn
3815 * Returns the #GtkTreeView wherein @tree_column has been inserted. If
3816 * @column is currently not inserted in any tree view, %NULL is
3819 * Return value: The tree view wherein @column has been inserted if any,
3825 gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
3827 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3829 return tree_column->tree_view;
3834 * gtk_tree_view_column_get_desired_size:
3835 * @tree_column: A #GtkTreeViewColumn
3836 * @minimum_size: location for storing the minimum size, or %NULL
3837 * @natural_size: location for storing the preferred size, or %NULL
3840 * Retreives @tree_column's minimum and natural size.
3845 gtk_tree_view_column_get_desired_size (GtkTreeViewColumn *column,
3846 GtkRequisition *minimal_size,
3847 GtkRequisition *desired_size)
3849 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (column));
3851 gtk_tree_view_column_cell_get_real_size (column,
3853 minimal_size, desired_size);
3856 #define __GTK_TREE_VIEW_COLUMN_C__
3857 #include "gtkaliasdef.c"