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 "gtkextendedlayout.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 void gtk_tree_view_column_extended_layout_init (GtkExtendedLayoutIface *iface);
161 static guint tree_column_signals[LAST_SIGNAL] = { 0 };
163 G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT,
164 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
165 gtk_tree_view_column_cell_layout_init)
166 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
167 gtk_tree_view_column_buildable_init)
168 G_IMPLEMENT_INTERFACE (GTK_TYPE_EXTENDED_LAYOUT,
169 gtk_tree_view_column_extended_layout_init))
174 gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class)
176 GObjectClass *object_class;
178 object_class = (GObjectClass*) class;
180 class->clicked = NULL;
182 object_class->finalize = gtk_tree_view_column_finalize;
183 object_class->set_property = gtk_tree_view_column_set_property;
184 object_class->get_property = gtk_tree_view_column_get_property;
186 tree_column_signals[CLICKED] =
187 g_signal_new (I_("clicked"),
188 G_OBJECT_CLASS_TYPE (object_class),
190 G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked),
192 _gtk_marshal_VOID__VOID,
195 g_object_class_install_property (object_class,
197 g_param_spec_boolean ("visible",
199 P_("Whether to display the column"),
201 GTK_PARAM_READWRITE));
203 g_object_class_install_property (object_class,
205 g_param_spec_boolean ("resizable",
207 P_("Column is user-resizable"),
209 GTK_PARAM_READWRITE));
211 g_object_class_install_property (object_class,
213 g_param_spec_int ("width",
215 P_("Current width of the column"),
219 GTK_PARAM_READABLE));
220 g_object_class_install_property (object_class,
222 g_param_spec_int ("spacing",
224 P_("Space which is inserted between cells"),
228 GTK_PARAM_READWRITE));
229 g_object_class_install_property (object_class,
231 g_param_spec_enum ("sizing",
233 P_("Resize mode of the column"),
234 GTK_TYPE_TREE_VIEW_COLUMN_SIZING,
235 GTK_TREE_VIEW_COLUMN_GROW_ONLY,
236 GTK_PARAM_READWRITE));
238 g_object_class_install_property (object_class,
240 g_param_spec_int ("fixed-width",
242 P_("Current fixed width of the column"),
246 GTK_PARAM_READWRITE));
248 g_object_class_install_property (object_class,
250 g_param_spec_int ("min-width",
252 P_("Minimum allowed width of the column"),
256 GTK_PARAM_READWRITE));
258 g_object_class_install_property (object_class,
260 g_param_spec_int ("max-width",
262 P_("Maximum allowed width of the column"),
266 GTK_PARAM_READWRITE));
268 g_object_class_install_property (object_class,
270 g_param_spec_string ("title",
272 P_("Title to appear in column header"),
274 GTK_PARAM_READWRITE));
276 g_object_class_install_property (object_class,
278 g_param_spec_boolean ("expand",
280 P_("Column gets share of extra width allocated to the widget"),
282 GTK_PARAM_READWRITE));
284 g_object_class_install_property (object_class,
286 g_param_spec_boolean ("clickable",
288 P_("Whether the header can be clicked"),
290 GTK_PARAM_READWRITE));
293 g_object_class_install_property (object_class,
295 g_param_spec_object ("widget",
297 P_("Widget to put in column header button instead of column title"),
299 GTK_PARAM_READWRITE));
301 g_object_class_install_property (object_class,
303 g_param_spec_float ("alignment",
305 P_("X Alignment of the column header text or widget"),
309 GTK_PARAM_READWRITE));
311 g_object_class_install_property (object_class,
313 g_param_spec_boolean ("reorderable",
315 P_("Whether the column can be reordered around the headers"),
317 GTK_PARAM_READWRITE));
319 g_object_class_install_property (object_class,
321 g_param_spec_boolean ("sort-indicator",
322 P_("Sort indicator"),
323 P_("Whether to show a sort indicator"),
325 GTK_PARAM_READWRITE));
327 g_object_class_install_property (object_class,
329 g_param_spec_enum ("sort-order",
331 P_("Sort direction the sort indicator should indicate"),
334 GTK_PARAM_READWRITE));
337 * GtkTreeViewColumn:sort-column-id:
339 * Logical sort column ID this column sorts on when selected for sorting. Setting the sort column ID makes the column header
340 * clickable. Set to %-1 to make the column unsortable.
344 g_object_class_install_property (object_class,
346 g_param_spec_int ("sort-column-id",
347 P_("Sort column ID"),
348 P_("Logical sort column ID this column sorts on when selected for sorting"),
352 GTK_PARAM_READWRITE));
354 g_type_class_add_private (class, sizeof (GtkTreeViewColumnPrivate));
358 gtk_tree_view_column_buildable_init (GtkBuildableIface *iface)
360 iface->add_child = _gtk_cell_layout_buildable_add_child;
361 iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start;
362 iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end;
366 gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface)
368 iface->pack_start = gtk_tree_view_column_cell_layout_pack_start;
369 iface->pack_end = gtk_tree_view_column_cell_layout_pack_end;
370 iface->clear = gtk_tree_view_column_cell_layout_clear;
371 iface->add_attribute = gtk_tree_view_column_cell_layout_add_attribute;
372 iface->set_cell_data_func = gtk_tree_view_column_cell_layout_set_cell_data_func;
373 iface->clear_attributes = gtk_tree_view_column_cell_layout_clear_attributes;
374 iface->reorder = gtk_tree_view_column_cell_layout_reorder;
375 iface->get_cells = gtk_tree_view_column_cell_layout_get_cells;
379 gtk_tree_view_column_init (GtkTreeViewColumn *tree_column)
381 tree_column->button = NULL;
382 tree_column->xalign = 0.0;
383 tree_column->width = 0;
384 tree_column->spacing = 0;
385 tree_column->requested_width = -1;
386 tree_column->min_width = -1;
387 tree_column->max_width = -1;
388 tree_column->resized_width = 0;
389 tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY;
390 tree_column->visible = TRUE;
391 tree_column->resizable = FALSE;
392 tree_column->expand = FALSE;
393 tree_column->clickable = FALSE;
394 tree_column->dirty = TRUE;
395 tree_column->sort_order = GTK_SORT_ASCENDING;
396 tree_column->show_sort_indicator = FALSE;
397 tree_column->property_changed_signal = 0;
398 tree_column->sort_clicked_signal = 0;
399 tree_column->sort_column_changed_signal = 0;
400 tree_column->sort_column_id = -1;
401 tree_column->reorderable = FALSE;
402 tree_column->maybe_reordered = FALSE;
403 tree_column->fixed_width = 1;
404 tree_column->use_resized_width = FALSE;
405 tree_column->title = g_strdup ("");
409 gtk_tree_view_column_finalize (GObject *object)
411 GtkTreeViewColumn *tree_column = (GtkTreeViewColumn *) object;
414 for (list = tree_column->cell_list; list; list = list->next)
416 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
420 GDestroyNotify d = info->destroy;
422 info->destroy = NULL;
425 gtk_tree_view_column_clear_attributes_by_info (tree_column, info);
426 g_object_unref (info->cell);
430 g_free (tree_column->title);
431 g_list_free (tree_column->cell_list);
433 if (tree_column->child)
434 g_object_unref (tree_column->child);
436 G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->finalize (object);
440 gtk_tree_view_column_set_property (GObject *object,
445 GtkTreeViewColumn *tree_column;
447 tree_column = GTK_TREE_VIEW_COLUMN (object);
452 gtk_tree_view_column_set_visible (tree_column,
453 g_value_get_boolean (value));
457 gtk_tree_view_column_set_resizable (tree_column,
458 g_value_get_boolean (value));
462 gtk_tree_view_column_set_sizing (tree_column,
463 g_value_get_enum (value));
466 case PROP_FIXED_WIDTH:
467 gtk_tree_view_column_set_fixed_width (tree_column,
468 g_value_get_int (value));
472 gtk_tree_view_column_set_min_width (tree_column,
473 g_value_get_int (value));
477 gtk_tree_view_column_set_max_width (tree_column,
478 g_value_get_int (value));
482 gtk_tree_view_column_set_spacing (tree_column,
483 g_value_get_int (value));
487 gtk_tree_view_column_set_title (tree_column,
488 g_value_get_string (value));
492 gtk_tree_view_column_set_expand (tree_column,
493 g_value_get_boolean (value));
497 gtk_tree_view_column_set_clickable (tree_column,
498 g_value_get_boolean (value));
502 gtk_tree_view_column_set_widget (tree_column,
503 (GtkWidget*) g_value_get_object (value));
507 gtk_tree_view_column_set_alignment (tree_column,
508 g_value_get_float (value));
511 case PROP_REORDERABLE:
512 gtk_tree_view_column_set_reorderable (tree_column,
513 g_value_get_boolean (value));
516 case PROP_SORT_INDICATOR:
517 gtk_tree_view_column_set_sort_indicator (tree_column,
518 g_value_get_boolean (value));
521 case PROP_SORT_ORDER:
522 gtk_tree_view_column_set_sort_order (tree_column,
523 g_value_get_enum (value));
526 case PROP_SORT_COLUMN_ID:
527 gtk_tree_view_column_set_sort_column_id (tree_column,
528 g_value_get_int (value));
532 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
538 gtk_tree_view_column_get_property (GObject *object,
543 GtkTreeViewColumn *tree_column;
545 tree_column = GTK_TREE_VIEW_COLUMN (object);
550 g_value_set_boolean (value,
551 gtk_tree_view_column_get_visible (tree_column));
555 g_value_set_boolean (value,
556 gtk_tree_view_column_get_resizable (tree_column));
560 g_value_set_int (value,
561 gtk_tree_view_column_get_width (tree_column));
565 g_value_set_int (value,
566 gtk_tree_view_column_get_spacing (tree_column));
570 g_value_set_enum (value,
571 gtk_tree_view_column_get_sizing (tree_column));
574 case PROP_FIXED_WIDTH:
575 g_value_set_int (value,
576 gtk_tree_view_column_get_fixed_width (tree_column));
580 g_value_set_int (value,
581 gtk_tree_view_column_get_min_width (tree_column));
585 g_value_set_int (value,
586 gtk_tree_view_column_get_max_width (tree_column));
590 g_value_set_string (value,
591 gtk_tree_view_column_get_title (tree_column));
595 g_value_set_boolean (value,
596 gtk_tree_view_column_get_expand (tree_column));
600 g_value_set_boolean (value,
601 gtk_tree_view_column_get_clickable (tree_column));
605 g_value_set_object (value,
606 (GObject*) gtk_tree_view_column_get_widget (tree_column));
610 g_value_set_float (value,
611 gtk_tree_view_column_get_alignment (tree_column));
614 case PROP_REORDERABLE:
615 g_value_set_boolean (value,
616 gtk_tree_view_column_get_reorderable (tree_column));
619 case PROP_SORT_INDICATOR:
620 g_value_set_boolean (value,
621 gtk_tree_view_column_get_sort_indicator (tree_column));
624 case PROP_SORT_ORDER:
625 g_value_set_enum (value,
626 gtk_tree_view_column_get_sort_order (tree_column));
629 case PROP_SORT_COLUMN_ID:
630 g_value_set_int (value,
631 gtk_tree_view_column_get_sort_column_id (tree_column));
635 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
640 /* Implementation of GtkCellLayout interface
644 gtk_tree_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout,
645 GtkCellRenderer *cell,
648 GtkTreeViewColumn *column;
649 GtkTreeViewColumnCellInfo *cell_info;
651 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
652 column = GTK_TREE_VIEW_COLUMN (cell_layout);
653 g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell));
655 g_object_ref_sink (cell);
657 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
658 cell_info->cell = cell;
659 cell_info->expand = expand ? TRUE : FALSE;
660 cell_info->pack = GTK_PACK_START;
661 cell_info->has_focus = 0;
662 cell_info->attributes = NULL;
664 column->cell_list = g_list_append (column->cell_list, cell_info);
668 gtk_tree_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout,
669 GtkCellRenderer *cell,
672 GtkTreeViewColumn *column;
673 GtkTreeViewColumnCellInfo *cell_info;
675 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
676 column = GTK_TREE_VIEW_COLUMN (cell_layout);
677 g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell));
679 g_object_ref_sink (cell);
681 cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1);
682 cell_info->cell = cell;
683 cell_info->expand = expand ? TRUE : FALSE;
684 cell_info->pack = GTK_PACK_END;
685 cell_info->has_focus = 0;
686 cell_info->attributes = NULL;
688 column->cell_list = g_list_append (column->cell_list, cell_info);
692 gtk_tree_view_column_cell_layout_clear (GtkCellLayout *cell_layout)
694 GtkTreeViewColumn *column;
696 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
697 column = GTK_TREE_VIEW_COLUMN (cell_layout);
699 while (column->cell_list)
701 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)column->cell_list->data;
703 gtk_tree_view_column_cell_layout_clear_attributes (cell_layout, info->cell);
704 g_object_unref (info->cell);
706 column->cell_list = g_list_delete_link (column->cell_list,
712 gtk_tree_view_column_cell_layout_add_attribute (GtkCellLayout *cell_layout,
713 GtkCellRenderer *cell,
714 const gchar *attribute,
717 GtkTreeViewColumn *tree_column;
718 GtkTreeViewColumnCellInfo *info;
720 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
721 tree_column = GTK_TREE_VIEW_COLUMN (cell_layout);
723 info = gtk_tree_view_column_get_cell_info (tree_column, cell);
724 g_return_if_fail (info != NULL);
726 info->attributes = g_slist_prepend (info->attributes, GINT_TO_POINTER (column));
727 info->attributes = g_slist_prepend (info->attributes, g_strdup (attribute));
729 if (tree_column->tree_view)
730 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
734 gtk_tree_view_column_cell_layout_set_cell_data_func (GtkCellLayout *cell_layout,
735 GtkCellRenderer *cell,
736 GtkCellLayoutDataFunc func,
738 GDestroyNotify destroy)
740 GtkTreeViewColumn *column;
741 GtkTreeViewColumnCellInfo *info;
743 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
744 column = GTK_TREE_VIEW_COLUMN (cell_layout);
746 info = gtk_tree_view_column_get_cell_info (column, cell);
747 g_return_if_fail (info != NULL);
751 GDestroyNotify d = info->destroy;
753 info->destroy = NULL;
757 info->func = (GtkTreeCellDataFunc)func;
758 info->func_data = func_data;
759 info->destroy = destroy;
761 if (column->tree_view)
762 _gtk_tree_view_column_cell_set_dirty (column, TRUE);
766 gtk_tree_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout,
767 GtkCellRenderer *cell_renderer)
769 GtkTreeViewColumn *column;
770 GtkTreeViewColumnCellInfo *info;
772 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
773 column = GTK_TREE_VIEW_COLUMN (cell_layout);
775 info = gtk_tree_view_column_get_cell_info (column, cell_renderer);
777 gtk_tree_view_column_clear_attributes_by_info (column, info);
781 gtk_tree_view_column_cell_layout_reorder (GtkCellLayout *cell_layout,
782 GtkCellRenderer *cell,
786 GtkTreeViewColumn *column;
787 GtkTreeViewColumnCellInfo *info;
789 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout));
790 column = GTK_TREE_VIEW_COLUMN (cell_layout);
792 info = gtk_tree_view_column_get_cell_info (column, cell);
794 g_return_if_fail (info != NULL);
795 g_return_if_fail (position >= 0);
797 link = g_list_find (column->cell_list, info);
799 g_return_if_fail (link != NULL);
801 column->cell_list = g_list_delete_link (column->cell_list, link);
802 column->cell_list = g_list_insert (column->cell_list, info, position);
804 if (column->tree_view)
805 gtk_widget_queue_draw (column->tree_view);
809 gtk_tree_view_column_clear_attributes_by_info (GtkTreeViewColumn *tree_column,
810 GtkTreeViewColumnCellInfo *info)
814 list = info->attributes;
816 while (list && list->next)
819 list = list->next->next;
821 g_slist_free (info->attributes);
822 info->attributes = NULL;
824 if (tree_column->tree_view)
825 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
831 /* Button handling code
834 gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column)
836 GtkTreeView *tree_view;
840 tree_view = (GtkTreeView *) tree_column->tree_view;
842 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
843 g_return_if_fail (tree_column->button == NULL);
845 gtk_widget_push_composite_child ();
846 tree_column->button = gtk_button_new ();
847 gtk_widget_add_events (tree_column->button, GDK_POINTER_MOTION_MASK);
848 gtk_widget_pop_composite_child ();
850 /* make sure we own a reference to it as well. */
851 if (tree_view->priv->header_window)
852 gtk_widget_set_parent_window (tree_column->button, tree_view->priv->header_window);
853 gtk_widget_set_parent (tree_column->button, GTK_WIDGET (tree_view));
855 g_signal_connect (tree_column->button, "event",
856 G_CALLBACK (gtk_tree_view_column_button_event),
858 g_signal_connect (tree_column->button, "clicked",
859 G_CALLBACK (gtk_tree_view_column_button_clicked),
862 tree_column->alignment = gtk_alignment_new (tree_column->xalign, 0.5, 0.0, 0.0);
864 hbox = gtk_hbox_new (FALSE, 2);
865 tree_column->arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_IN);
867 if (tree_column->child)
868 child = tree_column->child;
871 child = gtk_label_new (tree_column->title);
872 gtk_widget_show (child);
875 g_signal_connect (child, "mnemonic-activate",
876 G_CALLBACK (gtk_tree_view_column_mnemonic_activate),
879 if (tree_column->xalign <= 0.5)
880 gtk_box_pack_end (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
882 gtk_box_pack_start (GTK_BOX (hbox), tree_column->arrow, FALSE, FALSE, 0);
884 gtk_box_pack_start (GTK_BOX (hbox), tree_column->alignment, TRUE, TRUE, 0);
886 gtk_container_add (GTK_CONTAINER (tree_column->alignment), child);
887 gtk_container_add (GTK_CONTAINER (tree_column->button), hbox);
889 gtk_widget_show (hbox);
890 gtk_widget_show (tree_column->alignment);
891 gtk_tree_view_column_update_button (tree_column);
895 gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column)
897 gint sort_column_id = -1;
899 GtkWidget *alignment;
901 GtkWidget *current_child;
902 GtkArrowType arrow_type = GTK_ARROW_NONE;
905 if (tree_column->tree_view)
906 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
910 /* Create a button if necessary */
911 if (tree_column->visible &&
912 tree_column->button == NULL &&
913 tree_column->tree_view &&
914 GTK_WIDGET_REALIZED (tree_column->tree_view))
915 gtk_tree_view_column_create_button (tree_column);
917 if (! tree_column->button)
920 hbox = GTK_BIN (tree_column->button)->child;
921 alignment = tree_column->alignment;
922 arrow = tree_column->arrow;
923 current_child = GTK_BIN (alignment)->child;
925 /* Set up the actual button */
926 gtk_alignment_set (GTK_ALIGNMENT (alignment), tree_column->xalign,
929 if (tree_column->child)
931 if (current_child != tree_column->child)
933 gtk_container_remove (GTK_CONTAINER (alignment),
935 gtk_container_add (GTK_CONTAINER (alignment),
941 if (current_child == NULL)
943 current_child = gtk_label_new (NULL);
944 gtk_widget_show (current_child);
945 gtk_container_add (GTK_CONTAINER (alignment),
949 g_return_if_fail (GTK_IS_LABEL (current_child));
951 if (tree_column->title)
952 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
955 gtk_label_set_text_with_mnemonic (GTK_LABEL (current_child),
959 if (GTK_IS_TREE_SORTABLE (model))
960 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
964 if (tree_column->show_sort_indicator)
966 gboolean alternative;
968 g_object_get (gtk_widget_get_settings (tree_column->tree_view),
969 "gtk-alternative-sort-arrows", &alternative,
972 switch (tree_column->sort_order)
974 case GTK_SORT_ASCENDING:
975 arrow_type = alternative ? GTK_ARROW_UP : GTK_ARROW_DOWN;
978 case GTK_SORT_DESCENDING:
979 arrow_type = alternative ? GTK_ARROW_DOWN : GTK_ARROW_UP;
983 g_warning (G_STRLOC": bad sort order");
988 gtk_arrow_set (GTK_ARROW (arrow),
992 /* Put arrow on the right if the text is left-or-center justified, and on the
993 * left otherwise; do this by packing boxes, so flipping text direction will
996 g_object_ref (arrow);
997 gtk_container_remove (GTK_CONTAINER (hbox), arrow);
999 if (tree_column->xalign <= 0.5)
1001 gtk_box_pack_end (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1005 gtk_box_pack_start (GTK_BOX (hbox), arrow, FALSE, FALSE, 0);
1006 /* move it to the front */
1007 gtk_box_reorder_child (GTK_BOX (hbox), arrow, 0);
1009 g_object_unref (arrow);
1011 if (tree_column->show_sort_indicator
1012 || (GTK_IS_TREE_SORTABLE (model) && tree_column->sort_column_id >= 0))
1013 gtk_widget_show (arrow);
1015 gtk_widget_hide (arrow);
1017 /* It's always safe to hide the button. It isn't always safe to show it, as
1018 * if you show it before it's realized, it'll get the wrong window. */
1019 if (tree_column->button &&
1020 tree_column->tree_view != NULL &&
1021 GTK_WIDGET_REALIZED (tree_column->tree_view))
1023 if (tree_column->visible)
1025 gtk_widget_show_now (tree_column->button);
1026 if (tree_column->window)
1028 if (tree_column->resizable)
1030 gdk_window_show (tree_column->window);
1031 gdk_window_raise (tree_column->window);
1035 gdk_window_hide (tree_column->window);
1041 gtk_widget_hide (tree_column->button);
1042 if (tree_column->window)
1043 gdk_window_hide (tree_column->window);
1047 if (tree_column->reorderable || tree_column->clickable)
1049 GTK_WIDGET_SET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
1053 GTK_WIDGET_UNSET_FLAGS (tree_column->button, GTK_CAN_FOCUS);
1054 if (GTK_WIDGET_HAS_FOCUS (tree_column->button))
1056 GtkWidget *toplevel = gtk_widget_get_toplevel (tree_column->tree_view);
1057 if (gtk_widget_is_toplevel (toplevel))
1059 gtk_window_set_focus (GTK_WINDOW (toplevel), NULL);
1063 /* Queue a resize on the assumption that we always want to catch all changes
1064 * and columns don't change all that often.
1066 if (GTK_WIDGET_REALIZED (tree_column->tree_view))
1067 gtk_widget_queue_resize (tree_column->tree_view);
1071 /* Button signal handlers
1075 gtk_tree_view_column_button_event (GtkWidget *widget,
1079 GtkTreeViewColumn *column = (GtkTreeViewColumn *) data;
1081 g_return_val_if_fail (event != NULL, FALSE);
1083 if (event->type == GDK_BUTTON_PRESS &&
1084 column->reorderable &&
1085 ((GdkEventButton *)event)->button == 1)
1087 column->maybe_reordered = TRUE;
1088 gdk_window_get_pointer (GTK_BUTTON (widget)->event_window,
1092 gtk_widget_grab_focus (widget);
1095 if (event->type == GDK_BUTTON_RELEASE ||
1096 event->type == GDK_LEAVE_NOTIFY)
1097 column->maybe_reordered = FALSE;
1099 if (event->type == GDK_MOTION_NOTIFY &&
1100 column->maybe_reordered &&
1101 (gtk_drag_check_threshold (widget,
1104 (gint) ((GdkEventMotion *)event)->x,
1105 (gint) ((GdkEventMotion *)event)->y)))
1107 column->maybe_reordered = FALSE;
1108 _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column);
1111 if (column->clickable == FALSE)
1113 switch (event->type)
1115 case GDK_BUTTON_PRESS:
1116 case GDK_2BUTTON_PRESS:
1117 case GDK_3BUTTON_PRESS:
1118 case GDK_MOTION_NOTIFY:
1119 case GDK_BUTTON_RELEASE:
1120 case GDK_ENTER_NOTIFY:
1121 case GDK_LEAVE_NOTIFY:
1132 gtk_tree_view_column_button_clicked (GtkWidget *widget, gpointer data)
1134 g_signal_emit_by_name (data, "clicked");
1138 gtk_tree_view_column_mnemonic_activate (GtkWidget *widget,
1139 gboolean group_cycling,
1142 GtkTreeViewColumn *column = (GtkTreeViewColumn *)data;
1144 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (column), FALSE);
1146 GTK_TREE_VIEW (column->tree_view)->priv->focus_column = column;
1147 if (column->clickable)
1148 gtk_button_clicked (GTK_BUTTON (column->button));
1149 else if (GTK_WIDGET_CAN_FOCUS (column->button))
1150 gtk_widget_grab_focus (column->button);
1152 gtk_widget_grab_focus (column->tree_view);
1158 gtk_tree_view_model_sort_column_changed (GtkTreeSortable *sortable,
1159 GtkTreeViewColumn *column)
1161 gint sort_column_id;
1164 if (gtk_tree_sortable_get_sort_column_id (sortable,
1168 if (sort_column_id == column->sort_column_id)
1170 gtk_tree_view_column_set_sort_indicator (column, TRUE);
1171 gtk_tree_view_column_set_sort_order (column, order);
1175 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1180 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1185 gtk_tree_view_column_sort (GtkTreeViewColumn *tree_column,
1188 gint sort_column_id;
1190 gboolean has_sort_column;
1191 gboolean has_default_sort_func;
1193 g_return_if_fail (tree_column->tree_view != NULL);
1196 gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1199 has_default_sort_func =
1200 gtk_tree_sortable_has_default_sort_func (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model));
1202 if (has_sort_column &&
1203 sort_column_id == tree_column->sort_column_id)
1205 if (order == GTK_SORT_ASCENDING)
1206 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1207 tree_column->sort_column_id,
1208 GTK_SORT_DESCENDING);
1209 else if (order == GTK_SORT_DESCENDING && has_default_sort_func)
1210 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1211 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
1212 GTK_SORT_ASCENDING);
1214 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1215 tree_column->sort_column_id,
1216 GTK_SORT_ASCENDING);
1220 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (GTK_TREE_VIEW (tree_column->tree_view)->priv->model),
1221 tree_column->sort_column_id,
1222 GTK_SORT_ASCENDING);
1228 gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_column)
1230 GtkTreeModel *model;
1232 if (tree_column->tree_view == NULL)
1235 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
1240 if (GTK_IS_TREE_SORTABLE (model) &&
1241 tree_column->sort_column_id != -1)
1243 gint real_sort_column_id;
1244 GtkSortType real_order;
1246 if (tree_column->sort_column_changed_signal == 0)
1247 tree_column->sort_column_changed_signal =
1248 g_signal_connect (model, "sort-column-changed",
1249 G_CALLBACK (gtk_tree_view_model_sort_column_changed),
1252 if (gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model),
1253 &real_sort_column_id,
1255 (real_sort_column_id == tree_column->sort_column_id))
1257 gtk_tree_view_column_set_sort_indicator (tree_column, TRUE);
1258 gtk_tree_view_column_set_sort_order (tree_column, real_order);
1262 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
1268 /* Exported Private Functions.
1269 * These should only be called by gtktreeview.c or gtktreeviewcolumn.c
1273 _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column)
1275 GtkTreeView *tree_view;
1277 guint attributes_mask;
1280 tree_view = (GtkTreeView *)column->tree_view;
1281 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
1283 g_return_if_fail (GTK_IS_TREE_VIEW (tree_view));
1284 g_return_if_fail (GTK_WIDGET_REALIZED (tree_view));
1285 g_return_if_fail (tree_view->priv->header_window != NULL);
1286 g_return_if_fail (column->button != NULL);
1288 gtk_widget_set_parent_window (column->button, tree_view->priv->header_window);
1290 if (column->visible)
1291 gtk_widget_show (column->button);
1293 attr.window_type = GDK_WINDOW_CHILD;
1294 attr.wclass = GDK_INPUT_ONLY;
1295 attr.visual = gtk_widget_get_visual (GTK_WIDGET (tree_view));
1296 attr.colormap = gtk_widget_get_colormap (GTK_WIDGET (tree_view));
1297 attr.event_mask = gtk_widget_get_events (GTK_WIDGET (tree_view)) |
1298 (GDK_BUTTON_PRESS_MASK |
1299 GDK_BUTTON_RELEASE_MASK |
1300 GDK_POINTER_MOTION_MASK |
1301 GDK_POINTER_MOTION_HINT_MASK |
1302 GDK_KEY_PRESS_MASK);
1303 attributes_mask = GDK_WA_CURSOR | GDK_WA_X | GDK_WA_Y;
1304 attr.cursor = gdk_cursor_new_for_display (gdk_drawable_get_display (tree_view->priv->header_window),
1305 GDK_SB_H_DOUBLE_ARROW);
1307 attr.width = TREE_VIEW_DRAG_WIDTH;
1308 attr.height = tree_view->priv->header_height;
1310 attr.x = (column->button->allocation.x + (rtl ? 0 : column->button->allocation.width)) - TREE_VIEW_DRAG_WIDTH / 2;
1311 column->window = gdk_window_new (tree_view->priv->header_window,
1312 &attr, attributes_mask);
1313 gdk_window_set_user_data (column->window, tree_view);
1315 gtk_tree_view_column_update_button (column);
1317 gdk_cursor_unref (attr.cursor);
1321 _gtk_tree_view_column_unrealize_button (GtkTreeViewColumn *column)
1323 g_return_if_fail (column != NULL);
1324 g_return_if_fail (column->window != NULL);
1326 gdk_window_set_user_data (column->window, NULL);
1327 gdk_window_destroy (column->window);
1328 column->window = NULL;
1332 _gtk_tree_view_column_unset_model (GtkTreeViewColumn *column,
1333 GtkTreeModel *old_model)
1335 if (column->sort_column_changed_signal)
1337 g_signal_handler_disconnect (old_model,
1338 column->sort_column_changed_signal);
1339 column->sort_column_changed_signal = 0;
1341 gtk_tree_view_column_set_sort_indicator (column, FALSE);
1345 _gtk_tree_view_column_set_tree_view (GtkTreeViewColumn *column,
1346 GtkTreeView *tree_view)
1348 g_assert (column->tree_view == NULL);
1350 column->tree_view = GTK_WIDGET (tree_view);
1351 gtk_tree_view_column_create_button (column);
1353 column->property_changed_signal =
1354 g_signal_connect_swapped (tree_view,
1356 G_CALLBACK (gtk_tree_view_column_setup_sort_column_id_callback),
1359 gtk_tree_view_column_setup_sort_column_id_callback (column);
1363 _gtk_tree_view_column_unset_tree_view (GtkTreeViewColumn *column)
1365 if (column->tree_view && column->button)
1367 gtk_container_remove (GTK_CONTAINER (column->tree_view), column->button);
1369 if (column->property_changed_signal)
1371 g_signal_handler_disconnect (column->tree_view, column->property_changed_signal);
1372 column->property_changed_signal = 0;
1375 if (column->sort_column_changed_signal)
1377 g_signal_handler_disconnect (gtk_tree_view_get_model (GTK_TREE_VIEW (column->tree_view)),
1378 column->sort_column_changed_signal);
1379 column->sort_column_changed_signal = 0;
1382 column->tree_view = NULL;
1383 column->button = NULL;
1387 _gtk_tree_view_column_has_editable_cell (GtkTreeViewColumn *column)
1391 for (list = column->cell_list; list; list = list->next)
1392 if (((GtkTreeViewColumnCellInfo *)list->data)->cell->mode ==
1393 GTK_CELL_RENDERER_MODE_EDITABLE)
1399 /* gets cell being edited */
1401 _gtk_tree_view_column_get_edited_cell (GtkTreeViewColumn *column)
1405 for (list = column->cell_list; list; list = list->next)
1406 if (((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode)
1407 return ((GtkTreeViewColumnCellInfo *)list->data)->cell;
1413 _gtk_tree_view_column_count_special_cells (GtkTreeViewColumn *column)
1418 for (list = column->cell_list; list; list = list->next)
1420 GtkTreeViewColumnCellInfo *cellinfo = list->data;
1422 if ((cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
1423 cellinfo->cell->mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE) &&
1424 cellinfo->cell->visible)
1432 _gtk_tree_view_column_get_cell_at_pos (GtkTreeViewColumn *column,
1438 list = gtk_tree_view_column_cell_first (column);
1439 for (; list; list = gtk_tree_view_column_cell_next (column, list))
1441 GtkTreeViewColumnCellInfo *cellinfo = list->data;
1442 if (current_x <= x && x <= current_x + cellinfo->real_width)
1443 return cellinfo->cell;
1444 current_x += cellinfo->real_width;
1450 /* Public Functions */
1454 * gtk_tree_view_column_new:
1456 * Creates a new #GtkTreeViewColumn.
1458 * Return value: A newly created #GtkTreeViewColumn.
1461 gtk_tree_view_column_new (void)
1463 GtkTreeViewColumn *tree_column;
1465 tree_column = g_object_new (GTK_TYPE_TREE_VIEW_COLUMN, NULL);
1471 * gtk_tree_view_column_new_with_attributes:
1472 * @title: The title to set the header to.
1473 * @cell: The #GtkCellRenderer.
1474 * @Varargs: A %NULL-terminated list of attributes.
1476 * Creates a new #GtkTreeViewColumn with a number of default values. This is
1477 * equivalent to calling gtk_tree_view_column_set_title(),
1478 * gtk_tree_view_column_pack_start(), and
1479 * gtk_tree_view_column_set_attributes() on the newly created #GtkTreeViewColumn.
1481 * Here's a simple example:
1483 * enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS };
1486 * GtkTreeViewColumn *column;
1487 * GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
1489 * column = gtk_tree_view_column_new_with_attributes ("Title",
1491 * "text", TEXT_COLUMN,
1492 * "foreground", COLOR_COLUMN,
1497 * Return value: A newly created #GtkTreeViewColumn.
1500 gtk_tree_view_column_new_with_attributes (const gchar *title,
1501 GtkCellRenderer *cell,
1504 GtkTreeViewColumn *retval;
1507 retval = gtk_tree_view_column_new ();
1509 gtk_tree_view_column_set_title (retval, title);
1510 gtk_tree_view_column_pack_start (retval, cell, TRUE);
1512 va_start (args, cell);
1513 gtk_tree_view_column_set_attributesv (retval, cell, args);
1519 static GtkTreeViewColumnCellInfo *
1520 gtk_tree_view_column_get_cell_info (GtkTreeViewColumn *tree_column,
1521 GtkCellRenderer *cell_renderer)
1524 for (list = tree_column->cell_list; list; list = list->next)
1525 if (((GtkTreeViewColumnCellInfo *)list->data)->cell == cell_renderer)
1526 return (GtkTreeViewColumnCellInfo *) list->data;
1532 * gtk_tree_view_column_pack_start:
1533 * @tree_column: A #GtkTreeViewColumn.
1534 * @cell: The #GtkCellRenderer.
1535 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1537 * Packs the @cell into the beginning of the column. If @expand is %FALSE, then
1538 * the @cell is allocated no more space than it needs. Any unused space is divided
1539 * evenly between cells for which @expand is %TRUE.
1542 gtk_tree_view_column_pack_start (GtkTreeViewColumn *tree_column,
1543 GtkCellRenderer *cell,
1546 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (tree_column), cell, expand);
1550 * gtk_tree_view_column_pack_end:
1551 * @tree_column: A #GtkTreeViewColumn.
1552 * @cell: The #GtkCellRenderer.
1553 * @expand: %TRUE if @cell is to be given extra space allocated to @tree_column.
1555 * Adds the @cell to end of the column. If @expand is %FALSE, then the @cell
1556 * is allocated no more space than it needs. Any unused space is divided
1557 * evenly between cells for which @expand is %TRUE.
1560 gtk_tree_view_column_pack_end (GtkTreeViewColumn *tree_column,
1561 GtkCellRenderer *cell,
1564 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (tree_column), cell, expand);
1568 * gtk_tree_view_column_clear:
1569 * @tree_column: A #GtkTreeViewColumn
1571 * Unsets all the mappings on all renderers on the @tree_column.
1574 gtk_tree_view_column_clear (GtkTreeViewColumn *tree_column)
1576 gtk_cell_layout_clear (GTK_CELL_LAYOUT (tree_column));
1580 gtk_tree_view_column_cell_layout_get_cells (GtkCellLayout *layout)
1582 GtkTreeViewColumn *tree_column = GTK_TREE_VIEW_COLUMN (layout);
1583 GList *retval = NULL, *list;
1585 g_return_val_if_fail (tree_column != NULL, NULL);
1587 for (list = tree_column->cell_list; list; list = list->next)
1589 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
1591 retval = g_list_append (retval, info->cell);
1598 * gtk_tree_view_column_get_cell_renderers:
1599 * @tree_column: A #GtkTreeViewColumn
1601 * Returns a newly-allocated #GList of all the cell renderers in the column,
1602 * in no particular order. The list must be freed with g_list_free().
1604 * Return value: A list of #GtkCellRenderers
1606 * Deprecated: 2.18: use gtk_cell_layout_get_cells() instead.
1609 gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column)
1611 return gtk_tree_view_column_cell_layout_get_cells (GTK_CELL_LAYOUT (tree_column));
1615 * gtk_tree_view_column_add_attribute:
1616 * @tree_column: A #GtkTreeViewColumn.
1617 * @cell_renderer: the #GtkCellRenderer to set attributes on
1618 * @attribute: An attribute on the renderer
1619 * @column: The column position on the model to get the attribute from.
1621 * Adds an attribute mapping to the list in @tree_column. The @column is the
1622 * column of the model to get a value from, and the @attribute is the
1623 * parameter on @cell_renderer to be set from the value. So for example
1624 * if column 2 of the model contains strings, you could have the
1625 * "text" attribute of a #GtkCellRendererText get its values from
1629 gtk_tree_view_column_add_attribute (GtkTreeViewColumn *tree_column,
1630 GtkCellRenderer *cell_renderer,
1631 const gchar *attribute,
1634 gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (tree_column),
1635 cell_renderer, attribute, column);
1639 gtk_tree_view_column_set_attributesv (GtkTreeViewColumn *tree_column,
1640 GtkCellRenderer *cell_renderer,
1646 attribute = va_arg (args, gchar *);
1648 gtk_tree_view_column_clear_attributes (tree_column, cell_renderer);
1650 while (attribute != NULL)
1652 column = va_arg (args, gint);
1653 gtk_tree_view_column_add_attribute (tree_column, cell_renderer, attribute, column);
1654 attribute = va_arg (args, gchar *);
1659 * gtk_tree_view_column_set_attributes:
1660 * @tree_column: A #GtkTreeViewColumn.
1661 * @cell_renderer: the #GtkCellRenderer we're setting the attributes of
1662 * @Varargs: A %NULL-terminated list of attributes.
1664 * Sets the attributes in the list as the attributes of @tree_column.
1665 * The attributes should be in attribute/column order, as in
1666 * gtk_tree_view_column_add_attribute(). All existing attributes
1667 * are removed, and replaced with the new attributes.
1670 gtk_tree_view_column_set_attributes (GtkTreeViewColumn *tree_column,
1671 GtkCellRenderer *cell_renderer,
1676 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1677 g_return_if_fail (GTK_IS_CELL_RENDERER (cell_renderer));
1678 g_return_if_fail (gtk_tree_view_column_get_cell_info (tree_column, cell_renderer));
1680 va_start (args, cell_renderer);
1681 gtk_tree_view_column_set_attributesv (tree_column, cell_renderer, args);
1687 * gtk_tree_view_column_set_cell_data_func:
1688 * @tree_column: A #GtkTreeViewColumn
1689 * @cell_renderer: A #GtkCellRenderer
1690 * @func: The #GtkTreeViewColumnFunc to use.
1691 * @func_data: The user data for @func.
1692 * @destroy: The destroy notification for @func_data
1694 * Sets the #GtkTreeViewColumnFunc to use for the column. This
1695 * function is used instead of the standard attributes mapping for
1696 * setting the column value, and should set the value of @tree_column's
1697 * cell renderer as appropriate. @func may be %NULL to remove an
1701 gtk_tree_view_column_set_cell_data_func (GtkTreeViewColumn *tree_column,
1702 GtkCellRenderer *cell_renderer,
1703 GtkTreeCellDataFunc func,
1705 GDestroyNotify destroy)
1707 gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (tree_column),
1709 (GtkCellLayoutDataFunc)func,
1710 func_data, destroy);
1715 * gtk_tree_view_column_clear_attributes:
1716 * @tree_column: a #GtkTreeViewColumn
1717 * @cell_renderer: a #GtkCellRenderer to clear the attribute mapping on.
1719 * Clears all existing attributes previously set with
1720 * gtk_tree_view_column_set_attributes().
1723 gtk_tree_view_column_clear_attributes (GtkTreeViewColumn *tree_column,
1724 GtkCellRenderer *cell_renderer)
1726 gtk_cell_layout_clear_attributes (GTK_CELL_LAYOUT (tree_column),
1731 * gtk_tree_view_column_set_spacing:
1732 * @tree_column: A #GtkTreeViewColumn.
1733 * @spacing: distance between cell renderers in pixels.
1735 * Sets the spacing field of @tree_column, which is the number of pixels to
1736 * place between cell renderers packed into it.
1739 gtk_tree_view_column_set_spacing (GtkTreeViewColumn *tree_column,
1742 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1743 g_return_if_fail (spacing >= 0);
1745 if (tree_column->spacing == spacing)
1748 tree_column->spacing = spacing;
1749 if (tree_column->tree_view)
1750 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1754 * gtk_tree_view_column_get_spacing:
1755 * @tree_column: A #GtkTreeViewColumn.
1757 * Returns the spacing of @tree_column.
1759 * Return value: the spacing of @tree_column.
1762 gtk_tree_view_column_get_spacing (GtkTreeViewColumn *tree_column)
1764 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1766 return tree_column->spacing;
1769 /* Options for manipulating the columns */
1772 * gtk_tree_view_column_set_visible:
1773 * @tree_column: A #GtkTreeViewColumn.
1774 * @visible: %TRUE if the @tree_column is visible.
1776 * Sets the visibility of @tree_column.
1779 gtk_tree_view_column_set_visible (GtkTreeViewColumn *tree_column,
1782 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1784 visible = !! visible;
1786 if (tree_column->visible == visible)
1789 tree_column->visible = visible;
1791 if (tree_column->visible)
1792 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
1794 gtk_tree_view_column_update_button (tree_column);
1795 g_object_notify (G_OBJECT (tree_column), "visible");
1799 * gtk_tree_view_column_get_visible:
1800 * @tree_column: A #GtkTreeViewColumn.
1802 * Returns %TRUE if @tree_column is visible.
1804 * Return value: whether the column is visible or not. If it is visible, then
1805 * the tree will show the column.
1808 gtk_tree_view_column_get_visible (GtkTreeViewColumn *tree_column)
1810 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1812 return tree_column->visible;
1816 * gtk_tree_view_column_set_resizable:
1817 * @tree_column: A #GtkTreeViewColumn
1818 * @resizable: %TRUE, if the column can be resized
1820 * If @resizable is %TRUE, then the user can explicitly resize the column by
1821 * grabbing the outer edge of the column button. If resizable is %TRUE and
1822 * sizing mode of the column is #GTK_TREE_VIEW_COLUMN_AUTOSIZE, then the sizing
1823 * mode is changed to #GTK_TREE_VIEW_COLUMN_GROW_ONLY.
1826 gtk_tree_view_column_set_resizable (GtkTreeViewColumn *tree_column,
1829 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1831 resizable = !! resizable;
1833 if (tree_column->resizable == resizable)
1836 tree_column->resizable = resizable;
1838 if (resizable && tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1839 gtk_tree_view_column_set_sizing (tree_column, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
1841 gtk_tree_view_column_update_button (tree_column);
1843 g_object_notify (G_OBJECT (tree_column), "resizable");
1847 * gtk_tree_view_column_get_resizable:
1848 * @tree_column: A #GtkTreeViewColumn
1850 * Returns %TRUE if the @tree_column can be resized by the end user.
1852 * Return value: %TRUE, if the @tree_column can be resized.
1855 gtk_tree_view_column_get_resizable (GtkTreeViewColumn *tree_column)
1857 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
1859 return tree_column->resizable;
1864 * gtk_tree_view_column_set_sizing:
1865 * @tree_column: A #GtkTreeViewColumn.
1866 * @type: The #GtkTreeViewColumnSizing.
1868 * Sets the growth behavior of @tree_column to @type.
1871 gtk_tree_view_column_set_sizing (GtkTreeViewColumn *tree_column,
1872 GtkTreeViewColumnSizing type)
1874 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1876 if (type == tree_column->column_type)
1879 if (type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
1880 gtk_tree_view_column_set_resizable (tree_column, FALSE);
1883 /* I was clearly on crack when I wrote this. I'm not sure what's supposed to
1884 * be below so I'll leave it until I figure it out.
1886 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE &&
1887 tree_column->requested_width != -1)
1889 gtk_tree_view_column_set_sizing (tree_column, tree_column->requested_width);
1892 tree_column->column_type = type;
1894 gtk_tree_view_column_update_button (tree_column);
1896 g_object_notify (G_OBJECT (tree_column), "sizing");
1900 * gtk_tree_view_column_get_sizing:
1901 * @tree_column: A #GtkTreeViewColumn.
1903 * Returns the current type of @tree_column.
1905 * Return value: The type of @tree_column.
1907 GtkTreeViewColumnSizing
1908 gtk_tree_view_column_get_sizing (GtkTreeViewColumn *tree_column)
1910 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1912 return tree_column->column_type;
1916 * gtk_tree_view_column_get_width:
1917 * @tree_column: A #GtkTreeViewColumn.
1919 * Returns the current size of @tree_column in pixels.
1921 * Return value: The current width of @tree_column.
1924 gtk_tree_view_column_get_width (GtkTreeViewColumn *tree_column)
1926 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1928 return tree_column->width;
1932 * gtk_tree_view_column_set_fixed_width:
1933 * @tree_column: A #GtkTreeViewColumn.
1934 * @fixed_width: The size to set @tree_column to. Must be greater than 0.
1936 * Sets the size of the column in pixels. This is meaningful only if the sizing
1937 * type is #GTK_TREE_VIEW_COLUMN_FIXED. The size of the column is clamped to
1938 * the min/max width for the column. Please note that the min/max width of the
1939 * column doesn't actually affect the "fixed_width" property of the widget, just
1940 * the actual size when displayed.
1943 gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column,
1946 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1947 g_return_if_fail (fixed_width > 0);
1949 tree_column->fixed_width = fixed_width;
1950 tree_column->use_resized_width = FALSE;
1952 if (tree_column->tree_view &&
1953 GTK_WIDGET_REALIZED (tree_column->tree_view) &&
1954 tree_column->column_type == GTK_TREE_VIEW_COLUMN_FIXED)
1956 gtk_widget_queue_resize (tree_column->tree_view);
1959 g_object_notify (G_OBJECT (tree_column), "fixed-width");
1963 * gtk_tree_view_column_get_fixed_width:
1964 * @tree_column: a #GtkTreeViewColumn
1966 * Gets the fixed width of the column. This value is only meaning may not be
1967 * the actual width of the column on the screen, just what is requested.
1969 * Return value: the fixed width of the column
1972 gtk_tree_view_column_get_fixed_width (GtkTreeViewColumn *tree_column)
1974 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
1976 return tree_column->fixed_width;
1980 * gtk_tree_view_column_set_min_width:
1981 * @tree_column: A #GtkTreeViewColumn.
1982 * @min_width: The minimum width of the column in pixels, or -1.
1984 * Sets the minimum width of the @tree_column. If @min_width is -1, then the
1985 * minimum width is unset.
1988 gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column,
1991 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
1992 g_return_if_fail (min_width >= -1);
1994 if (min_width == tree_column->min_width)
1997 if (tree_column->visible &&
1998 tree_column->tree_view != NULL &&
1999 GTK_WIDGET_REALIZED (tree_column->tree_view))
2001 if (min_width > tree_column->width)
2002 gtk_widget_queue_resize (tree_column->tree_view);
2005 tree_column->min_width = min_width;
2006 g_object_freeze_notify (G_OBJECT (tree_column));
2007 if (tree_column->max_width != -1 && tree_column->max_width < min_width)
2009 tree_column->max_width = min_width;
2010 g_object_notify (G_OBJECT (tree_column), "max-width");
2012 g_object_notify (G_OBJECT (tree_column), "min-width");
2013 g_object_thaw_notify (G_OBJECT (tree_column));
2015 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2016 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (tree_column->tree_view),
2021 * gtk_tree_view_column_get_min_width:
2022 * @tree_column: A #GtkTreeViewColumn.
2024 * Returns the minimum width in pixels of the @tree_column, or -1 if no minimum
2027 * Return value: The minimum width of the @tree_column.
2030 gtk_tree_view_column_get_min_width (GtkTreeViewColumn *tree_column)
2032 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2034 return tree_column->min_width;
2038 * gtk_tree_view_column_set_max_width:
2039 * @tree_column: A #GtkTreeViewColumn.
2040 * @max_width: The maximum width of the column in pixels, or -1.
2042 * Sets the maximum width of the @tree_column. If @max_width is -1, then the
2043 * maximum width is unset. Note, the column can actually be wider than max
2044 * width if it's the last column in a view. In this case, the column expands to
2045 * fill any extra space.
2048 gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column,
2051 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2052 g_return_if_fail (max_width >= -1);
2054 if (max_width == tree_column->max_width)
2057 if (tree_column->visible &&
2058 tree_column->tree_view != NULL &&
2059 GTK_WIDGET_REALIZED (tree_column->tree_view))
2061 if (max_width != -1 && max_width < tree_column->width)
2062 gtk_widget_queue_resize (tree_column->tree_view);
2065 tree_column->max_width = max_width;
2066 g_object_freeze_notify (G_OBJECT (tree_column));
2067 if (max_width != -1 && max_width < tree_column->min_width)
2069 tree_column->min_width = max_width;
2070 g_object_notify (G_OBJECT (tree_column), "min-width");
2072 g_object_notify (G_OBJECT (tree_column), "max-width");
2073 g_object_thaw_notify (G_OBJECT (tree_column));
2075 if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE)
2076 _gtk_tree_view_column_autosize (GTK_TREE_VIEW (tree_column->tree_view),
2081 * gtk_tree_view_column_get_max_width:
2082 * @tree_column: A #GtkTreeViewColumn.
2084 * Returns the maximum width in pixels of the @tree_column, or -1 if no maximum
2087 * Return value: The maximum width of the @tree_column.
2090 gtk_tree_view_column_get_max_width (GtkTreeViewColumn *tree_column)
2092 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), -1);
2094 return tree_column->max_width;
2098 * gtk_tree_view_column_clicked:
2099 * @tree_column: a #GtkTreeViewColumn
2101 * Emits the "clicked" signal on the column. This function will only work if
2102 * @tree_column is clickable.
2105 gtk_tree_view_column_clicked (GtkTreeViewColumn *tree_column)
2107 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2109 if (tree_column->visible &&
2110 tree_column->button &&
2111 tree_column->clickable)
2112 gtk_button_clicked (GTK_BUTTON (tree_column->button));
2116 * gtk_tree_view_column_set_title:
2117 * @tree_column: A #GtkTreeViewColumn.
2118 * @title: The title of the @tree_column.
2120 * Sets the title of the @tree_column. If a custom widget has been set, then
2121 * this value is ignored.
2124 gtk_tree_view_column_set_title (GtkTreeViewColumn *tree_column,
2129 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2131 new_title = g_strdup (title);
2132 g_free (tree_column->title);
2133 tree_column->title = new_title;
2135 gtk_tree_view_column_update_button (tree_column);
2136 g_object_notify (G_OBJECT (tree_column), "title");
2140 * gtk_tree_view_column_get_title:
2141 * @tree_column: A #GtkTreeViewColumn.
2143 * Returns the title of the widget.
2145 * Return value: the title of the column. This string should not be
2146 * modified or freed.
2148 G_CONST_RETURN gchar *
2149 gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column)
2151 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2153 return tree_column->title;
2157 * gtk_tree_view_column_set_expand:
2158 * @tree_column: A #GtkTreeViewColumn
2159 * @expand: %TRUE if the column should take available extra space, %FALSE if not
2161 * Sets the column to take available extra space. This space is shared equally
2162 * amongst all columns that have the expand set to %TRUE. If no column has this
2163 * option set, then the last column gets all extra space. By default, every
2164 * column is created with this %FALSE.
2169 gtk_tree_view_column_set_expand (GtkTreeViewColumn *tree_column,
2172 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2174 expand = expand?TRUE:FALSE;
2175 if (tree_column->expand == expand)
2177 tree_column->expand = expand;
2179 if (tree_column->visible &&
2180 tree_column->tree_view != NULL &&
2181 GTK_WIDGET_REALIZED (tree_column->tree_view))
2183 /* We want to continue using the original width of the
2184 * column that includes additional space added by the user
2185 * resizing the columns and possibly extra (expanded) space, which
2186 * are not included in the resized width.
2188 tree_column->use_resized_width = FALSE;
2190 gtk_widget_queue_resize (tree_column->tree_view);
2193 g_object_notify (G_OBJECT (tree_column), "expand");
2197 * gtk_tree_view_column_get_expand:
2198 * @tree_column: a #GtkTreeViewColumn
2200 * Return %TRUE if the column expands to take any available space.
2202 * Return value: %TRUE, if the column expands
2207 gtk_tree_view_column_get_expand (GtkTreeViewColumn *tree_column)
2209 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2211 return tree_column->expand;
2215 * gtk_tree_view_column_set_clickable:
2216 * @tree_column: A #GtkTreeViewColumn.
2217 * @clickable: %TRUE if the header is active.
2219 * Sets the header to be active if @active is %TRUE. When the header is active,
2220 * then it can take keyboard focus, and can be clicked.
2223 gtk_tree_view_column_set_clickable (GtkTreeViewColumn *tree_column,
2226 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2228 clickable = !! clickable;
2229 if (tree_column->clickable == clickable)
2232 tree_column->clickable = clickable;
2233 gtk_tree_view_column_update_button (tree_column);
2234 g_object_notify (G_OBJECT (tree_column), "clickable");
2238 * gtk_tree_view_column_get_clickable:
2239 * @tree_column: a #GtkTreeViewColumn
2241 * Returns %TRUE if the user can click on the header for the column.
2243 * Return value: %TRUE if user can click the column header.
2246 gtk_tree_view_column_get_clickable (GtkTreeViewColumn *tree_column)
2248 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2250 return tree_column->clickable;
2254 * gtk_tree_view_column_set_widget:
2255 * @tree_column: A #GtkTreeViewColumn.
2256 * @widget: (allow-none): A child #GtkWidget, or %NULL.
2258 * Sets the widget in the header to be @widget. If widget is %NULL, then the
2259 * header button is set with a #GtkLabel set to the title of @tree_column.
2262 gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column,
2265 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2266 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
2269 g_object_ref_sink (widget);
2271 if (tree_column->child)
2272 g_object_unref (tree_column->child);
2274 tree_column->child = widget;
2275 gtk_tree_view_column_update_button (tree_column);
2276 g_object_notify (G_OBJECT (tree_column), "widget");
2280 * gtk_tree_view_column_get_widget:
2281 * @tree_column: A #GtkTreeViewColumn.
2283 * Returns the #GtkWidget in the button on the column header. If a custom
2284 * widget has not been set then %NULL is returned.
2286 * Return value: The #GtkWidget in the column header, or %NULL
2289 gtk_tree_view_column_get_widget (GtkTreeViewColumn *tree_column)
2291 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
2293 return tree_column->child;
2297 * gtk_tree_view_column_set_alignment:
2298 * @tree_column: A #GtkTreeViewColumn.
2299 * @xalign: The alignment, which is between [0.0 and 1.0] inclusive.
2301 * Sets the alignment of the title or custom widget inside the column header.
2302 * The alignment determines its location inside the button -- 0.0 for left, 0.5
2303 * for center, 1.0 for right.
2306 gtk_tree_view_column_set_alignment (GtkTreeViewColumn *tree_column,
2309 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2311 xalign = CLAMP (xalign, 0.0, 1.0);
2313 if (tree_column->xalign == xalign)
2316 tree_column->xalign = xalign;
2317 gtk_tree_view_column_update_button (tree_column);
2318 g_object_notify (G_OBJECT (tree_column), "alignment");
2322 * gtk_tree_view_column_get_alignment:
2323 * @tree_column: A #GtkTreeViewColumn.
2325 * Returns the current x alignment of @tree_column. This value can range
2326 * between 0.0 and 1.0.
2328 * Return value: The current alignent of @tree_column.
2331 gtk_tree_view_column_get_alignment (GtkTreeViewColumn *tree_column)
2333 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0.5);
2335 return tree_column->xalign;
2339 * gtk_tree_view_column_set_reorderable:
2340 * @tree_column: A #GtkTreeViewColumn
2341 * @reorderable: %TRUE, if the column can be reordered.
2343 * If @reorderable is %TRUE, then the column can be reordered by the end user
2344 * dragging the header.
2347 gtk_tree_view_column_set_reorderable (GtkTreeViewColumn *tree_column,
2348 gboolean reorderable)
2350 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2353 gtk_tree_view_column_set_clickable (tree_column, TRUE);*/
2355 if (tree_column->reorderable == (reorderable?TRUE:FALSE))
2358 tree_column->reorderable = (reorderable?TRUE:FALSE);
2359 gtk_tree_view_column_update_button (tree_column);
2360 g_object_notify (G_OBJECT (tree_column), "reorderable");
2364 * gtk_tree_view_column_get_reorderable:
2365 * @tree_column: A #GtkTreeViewColumn
2367 * Returns %TRUE if the @tree_column can be reordered by the user.
2369 * Return value: %TRUE if the @tree_column can be reordered by the user.
2372 gtk_tree_view_column_get_reorderable (GtkTreeViewColumn *tree_column)
2374 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2376 return tree_column->reorderable;
2381 * gtk_tree_view_column_set_sort_column_id:
2382 * @tree_column: a #GtkTreeViewColumn
2383 * @sort_column_id: The @sort_column_id of the model to sort on.
2385 * Sets the logical @sort_column_id that this column sorts on when this column
2386 * is selected for sorting. Doing so makes the column header clickable.
2389 gtk_tree_view_column_set_sort_column_id (GtkTreeViewColumn *tree_column,
2390 gint sort_column_id)
2392 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2393 g_return_if_fail (sort_column_id >= -1);
2395 if (tree_column->sort_column_id == sort_column_id)
2398 tree_column->sort_column_id = sort_column_id;
2400 /* Handle unsetting the id */
2401 if (sort_column_id == -1)
2403 GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view));
2405 if (tree_column->sort_clicked_signal)
2407 g_signal_handler_disconnect (tree_column, tree_column->sort_clicked_signal);
2408 tree_column->sort_clicked_signal = 0;
2411 if (tree_column->sort_column_changed_signal)
2413 g_signal_handler_disconnect (model, tree_column->sort_column_changed_signal);
2414 tree_column->sort_column_changed_signal = 0;
2417 gtk_tree_view_column_set_sort_order (tree_column, GTK_SORT_ASCENDING);
2418 gtk_tree_view_column_set_sort_indicator (tree_column, FALSE);
2419 gtk_tree_view_column_set_clickable (tree_column, FALSE);
2420 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2424 gtk_tree_view_column_set_clickable (tree_column, TRUE);
2426 if (! tree_column->sort_clicked_signal)
2427 tree_column->sort_clicked_signal = g_signal_connect (tree_column,
2429 G_CALLBACK (gtk_tree_view_column_sort),
2432 gtk_tree_view_column_setup_sort_column_id_callback (tree_column);
2433 g_object_notify (G_OBJECT (tree_column), "sort-column-id");
2437 * gtk_tree_view_column_get_sort_column_id:
2438 * @tree_column: a #GtkTreeViewColumn
2440 * Gets the logical @sort_column_id that the model sorts on when this
2441 * column is selected for sorting.
2442 * See gtk_tree_view_column_set_sort_column_id().
2444 * Return value: the current @sort_column_id for this column, or -1 if
2445 * this column can't be used for sorting.
2448 gtk_tree_view_column_get_sort_column_id (GtkTreeViewColumn *tree_column)
2450 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2452 return tree_column->sort_column_id;
2456 * gtk_tree_view_column_set_sort_indicator:
2457 * @tree_column: a #GtkTreeViewColumn
2458 * @setting: %TRUE to display an indicator that the column is sorted
2460 * Call this function with a @setting of %TRUE to display an arrow in
2461 * the header button indicating the column is sorted. Call
2462 * gtk_tree_view_column_set_sort_order() to change the direction of
2467 gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column,
2470 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2472 setting = setting != FALSE;
2474 if (setting == tree_column->show_sort_indicator)
2477 tree_column->show_sort_indicator = setting;
2478 gtk_tree_view_column_update_button (tree_column);
2479 g_object_notify (G_OBJECT (tree_column), "sort-indicator");
2483 * gtk_tree_view_column_get_sort_indicator:
2484 * @tree_column: a #GtkTreeViewColumn
2486 * Gets the value set by gtk_tree_view_column_set_sort_indicator().
2488 * Return value: whether the sort indicator arrow is displayed
2491 gtk_tree_view_column_get_sort_indicator (GtkTreeViewColumn *tree_column)
2493 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
2495 return tree_column->show_sort_indicator;
2499 * gtk_tree_view_column_set_sort_order:
2500 * @tree_column: a #GtkTreeViewColumn
2501 * @order: sort order that the sort indicator should indicate
2503 * Changes the appearance of the sort indicator.
2505 * This <emphasis>does not</emphasis> actually sort the model. Use
2506 * gtk_tree_view_column_set_sort_column_id() if you want automatic sorting
2507 * support. This function is primarily for custom sorting behavior, and should
2508 * be used in conjunction with gtk_tree_sortable_set_sort_column() to do
2509 * that. For custom models, the mechanism will vary.
2511 * The sort indicator changes direction to indicate normal sort or reverse sort.
2512 * Note that you must have the sort indicator enabled to see anything when
2513 * calling this function; see gtk_tree_view_column_set_sort_indicator().
2516 gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column,
2519 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2521 if (order == tree_column->sort_order)
2524 tree_column->sort_order = order;
2525 gtk_tree_view_column_update_button (tree_column);
2526 g_object_notify (G_OBJECT (tree_column), "sort-order");
2530 * gtk_tree_view_column_get_sort_order:
2531 * @tree_column: a #GtkTreeViewColumn
2533 * Gets the value set by gtk_tree_view_column_set_sort_order().
2535 * Return value: the sort order the sort indicator is indicating
2538 gtk_tree_view_column_get_sort_order (GtkTreeViewColumn *tree_column)
2540 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), 0);
2542 return tree_column->sort_order;
2546 * gtk_tree_view_column_cell_set_cell_data:
2547 * @tree_column: A #GtkTreeViewColumn.
2548 * @tree_model: The #GtkTreeModel to to get the cell renderers attributes from.
2549 * @iter: The #GtkTreeIter to to get the cell renderer's attributes from.
2550 * @is_expander: %TRUE, if the row has children
2551 * @is_expanded: %TRUE, if the row has visible children
2553 * Sets the cell renderer based on the @tree_model and @iter. That is, for
2554 * every attribute mapping in @tree_column, it will get a value from the set
2555 * column on the @iter, and use that value to set the attribute on the cell
2556 * renderer. This is used primarily by the #GtkTreeView.
2559 gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column,
2560 GtkTreeModel *tree_model,
2562 gboolean is_expander,
2563 gboolean is_expanded)
2566 GValue value = { 0, };
2569 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2571 if (tree_model == NULL)
2574 for (cell_list = tree_column->cell_list; cell_list; cell_list = cell_list->next)
2576 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) cell_list->data;
2577 GObject *cell = (GObject *) info->cell;
2579 list = info->attributes;
2581 g_object_freeze_notify (cell);
2583 if (info->cell->is_expander != is_expander)
2584 g_object_set (cell, "is-expander", is_expander, NULL);
2586 if (info->cell->is_expanded != is_expanded)
2587 g_object_set (cell, "is-expanded", is_expanded, NULL);
2589 while (list && list->next)
2591 gtk_tree_model_get_value (tree_model, iter,
2592 GPOINTER_TO_INT (list->next->data),
2594 g_object_set_property (cell, (gchar *) list->data, &value);
2595 g_value_unset (&value);
2596 list = list->next->next;
2600 (* info->func) (tree_column, info->cell, tree_model, iter, info->func_data);
2601 g_object_thaw_notify (G_OBJECT (info->cell));
2607 * gtk_tree_view_column_cell_get_size:
2608 * @tree_column: A #GtkTreeViewColumn.
2609 * @cell_area: The area a cell in the column will be allocated, or %NULL
2610 * @x_offset: location to return x offset of a cell relative to @cell_area, or %NULL
2611 * @y_offset: location to return y offset of a cell relative to @cell_area, or %NULL
2612 * @width: location to return width needed to render a cell, or %NULL
2613 * @height: location to return height needed to render a cell, or %NULL
2615 * Obtains the width and height needed to render the column. This is used
2616 * primarily by the #GtkTreeView.
2619 gtk_tree_view_column_cell_get_real_size (GtkTreeViewColumn *tree_column,
2620 const GdkRectangle *cell_area,
2623 GtkRequisition *minimal_size,
2624 GtkRequisition *desired_size)
2627 gboolean first_cell = TRUE;
2628 gint focus_line_width;
2630 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
2632 minimal_size->height = 0;
2633 minimal_size->width = 0;
2634 desired_size->height = 0;
2635 desired_size->width = 0;
2637 gtk_widget_style_get (tree_column->tree_view, "focus-line-width", &focus_line_width, NULL);
2639 for (list = tree_column->cell_list; list; list = list->next)
2641 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2643 GtkRequisition min_req, nat_req;
2645 g_object_get (info->cell, "visible", &visible, NULL);
2647 if (visible == FALSE)
2650 if (first_cell == FALSE)
2652 min_req.width += tree_column->spacing;
2653 nat_req.width += tree_column->spacing;
2656 gtk_extended_layout_get_desired_size (GTK_EXTENDED_LAYOUT (info->cell),
2657 &min_req, &nat_req);
2659 min_req.width += focus_line_width * 2;
2660 min_req.height += focus_line_width * 2;
2661 nat_req.width += focus_line_width * 2;
2662 nat_req.height += focus_line_width * 2;
2664 info->requested_width = MAX (info->requested_width, min_req.width);
2669 *minimal_size = min_req;
2672 *desired_size = nat_req;
2677 gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column,
2678 const GdkRectangle *cell_area,
2684 GtkRequisition min_req;
2686 gtk_tree_view_column_cell_get_real_size (tree_column, cell_area,
2687 x_offset, y_offset, &min_req, NULL);
2690 *width = min_req.width;
2693 *height = min_req.height;
2696 /* rendering, event handling and rendering focus are somewhat complicated, and
2697 * quite a bit of code. Rather than duplicate them, we put them together to
2698 * keep the code in one place.
2700 * To better understand what's going on, check out
2701 * docs/tree-column-sizing.png
2710 gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column,
2712 const GdkRectangle *background_area,
2713 const GdkRectangle *cell_area,
2716 const GdkRectangle *expose_area, /* RENDER */
2717 GdkRectangle *focus_rectangle, /* FOCUS */
2718 GtkCellEditable **editable_widget, /* EVENT */
2719 GdkEvent *event, /* EVENT */
2720 gchar *path_string) /* EVENT */
2723 GdkRectangle real_cell_area;
2724 GdkRectangle real_background_area;
2725 GdkRectangle real_expose_area = *cell_area;
2727 gint expand_cell_count = 0;
2728 gint full_requested_width = 0;
2730 gint min_x, min_y, max_x, max_y;
2731 gint focus_line_width;
2733 gint horizontal_separator;
2734 gboolean cursor_row = FALSE;
2735 gboolean first_cell = TRUE;
2737 /* If we have rtl text, we need to transform our areas */
2738 GdkRectangle rtl_cell_area;
2739 GdkRectangle rtl_background_area;
2746 rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL);
2747 special_cells = _gtk_tree_view_column_count_special_cells (tree_column);
2749 if (special_cells > 1 && action == CELL_ACTION_FOCUS)
2751 GtkTreeViewColumnCellInfo *info = NULL;
2752 gboolean found_has_focus = FALSE;
2754 /* one should have focus */
2755 for (list = tree_column->cell_list; list; list = list->next)
2758 if (info && info->has_focus)
2760 found_has_focus = TRUE;
2765 if (!found_has_focus)
2767 /* give the first one focus */
2768 info = gtk_tree_view_column_cell_first (tree_column)->data;
2769 info->has_focus = TRUE;
2773 cursor_row = flags & GTK_CELL_RENDERER_FOCUSED;
2775 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
2776 "focus-line-width", &focus_line_width,
2777 "horizontal-separator", &horizontal_separator,
2780 real_cell_area = *cell_area;
2781 real_background_area = *background_area;
2784 real_cell_area.x += focus_line_width;
2785 real_cell_area.y += focus_line_width;
2786 real_cell_area.height -= 2 * focus_line_width;
2789 depth = real_background_area.width - real_cell_area.width;
2791 depth = real_cell_area.x - real_background_area.x;
2793 /* Find out how much extra space we have to allocate */
2794 for (list = tree_column->cell_list; list; list = list->next)
2796 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data;
2798 if (! info->cell->visible)
2801 if (info->expand == TRUE)
2802 expand_cell_count ++;
2803 full_requested_width += info->requested_width;
2806 full_requested_width += tree_column->spacing;
2811 extra_space = cell_area->width - full_requested_width;
2812 if (extra_space < 0)
2814 else if (extra_space > 0 && expand_cell_count > 0)
2815 extra_space /= expand_cell_count;
2817 /* iterate list for GTK_PACK_START cells */
2818 for (list = tree_column->cell_list; list; list = list->next)
2820 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2822 if (info->pack == GTK_PACK_END)
2825 if (! info->cell->visible)
2828 if ((info->has_focus || special_cells == 1) && cursor_row)
2829 flags |= GTK_CELL_RENDERER_FOCUSED;
2831 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2833 info->real_width = info->requested_width + (info->expand?extra_space:0);
2835 /* We constrain ourselves to only the width available */
2836 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
2838 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
2841 if (real_cell_area.x > cell_area->x + cell_area->width)
2844 real_cell_area.width = info->real_width;
2845 real_cell_area.width -= 2 * focus_line_width;
2849 real_background_area.width = info->real_width + depth;
2853 /* fill the rest of background for the last cell */
2854 real_background_area.width = background_area->x + background_area->width - real_background_area.x;
2857 rtl_cell_area = real_cell_area;
2858 rtl_background_area = real_background_area;
2862 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
2863 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
2867 if (action == CELL_ACTION_RENDER)
2869 gtk_cell_renderer_render (info->cell,
2871 tree_column->tree_view,
2872 &rtl_background_area,
2878 else if (action == CELL_ACTION_FOCUS)
2880 gint x_offset, y_offset, width, height;
2882 gtk_cell_renderer_get_size (info->cell,
2883 tree_column->tree_view,
2885 &x_offset, &y_offset,
2888 if (special_cells > 1)
2890 if (info->has_focus)
2892 min_x = rtl_cell_area.x + x_offset;
2893 max_x = min_x + width;
2894 min_y = rtl_cell_area.y + y_offset;
2895 max_y = min_y + height;
2900 if (min_x > (rtl_cell_area.x + x_offset))
2901 min_x = rtl_cell_area.x + x_offset;
2902 if (max_x < rtl_cell_area.x + x_offset + width)
2903 max_x = rtl_cell_area.x + x_offset + width;
2904 if (min_y > (rtl_cell_area.y + y_offset))
2905 min_y = rtl_cell_area.y + y_offset;
2906 if (max_y < rtl_cell_area.y + y_offset + height)
2907 max_y = rtl_cell_area.y + y_offset + height;
2911 else if (action == CELL_ACTION_EVENT)
2913 gboolean try_event = FALSE;
2917 if (special_cells == 1)
2919 /* only 1 activatable cell -> whole column can activate */
2920 if (cell_area->x <= ((GdkEventButton *)event)->x &&
2921 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
2924 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
2925 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
2926 /* only activate cell if the user clicked on an individual
2931 else if (special_cells > 1 && info->has_focus)
2933 else if (special_cells == 1)
2938 gboolean visible, mode;
2940 g_object_get (info->cell,
2941 "visible", &visible,
2944 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2946 if (gtk_cell_renderer_activate (info->cell,
2948 tree_column->tree_view,
2950 &rtl_background_area,
2954 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2958 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2961 gtk_cell_renderer_start_editing (info->cell,
2963 tree_column->tree_view,
2965 &rtl_background_area,
2969 if (*editable_widget != NULL)
2971 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
2972 info->in_editing_mode = TRUE;
2973 gtk_tree_view_column_focus_cell (tree_column, info->cell);
2975 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2983 flags &= ~GTK_CELL_RENDERER_FOCUSED;
2985 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
2986 real_background_area.x += real_background_area.width + tree_column->spacing;
2988 /* Only needed for first cell */
2992 /* iterate list for PACK_END cells */
2993 for (list = g_list_last (tree_column->cell_list); list; list = list->prev)
2995 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
2997 if (info->pack == GTK_PACK_START)
3000 if (! info->cell->visible)
3003 if ((info->has_focus || special_cells == 1) && cursor_row)
3004 flags |= GTK_CELL_RENDERER_FOCUSED;
3006 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3008 info->real_width = info->requested_width + (info->expand?extra_space:0);
3010 /* We constrain ourselves to only the width available */
3011 if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width)
3013 info->real_width = cell_area->x + cell_area->width - real_cell_area.x;
3016 if (real_cell_area.x > cell_area->x + cell_area->width)
3019 real_cell_area.width = info->real_width;
3020 real_cell_area.width -= 2 * focus_line_width;
3021 real_background_area.width = info->real_width + depth;
3023 rtl_cell_area = real_cell_area;
3024 rtl_background_area = real_background_area;
3027 rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width;
3028 rtl_background_area.x = background_area->x + background_area->width - (real_background_area.x - background_area->x) - real_background_area.width;
3032 if (action == CELL_ACTION_RENDER)
3034 gtk_cell_renderer_render (info->cell,
3036 tree_column->tree_view,
3037 &rtl_background_area,
3043 else if (action == CELL_ACTION_FOCUS)
3045 gint x_offset, y_offset, width, height;
3047 gtk_cell_renderer_get_size (info->cell,
3048 tree_column->tree_view,
3050 &x_offset, &y_offset,
3053 if (special_cells > 1)
3055 if (info->has_focus)
3057 min_x = rtl_cell_area.x + x_offset;
3058 max_x = min_x + width;
3059 min_y = rtl_cell_area.y + y_offset;
3060 max_y = min_y + height;
3065 if (min_x > (rtl_cell_area.x + x_offset))
3066 min_x = rtl_cell_area.x + x_offset;
3067 if (max_x < rtl_cell_area.x + x_offset + width)
3068 max_x = rtl_cell_area.x + x_offset + width;
3069 if (min_y > (rtl_cell_area.y + y_offset))
3070 min_y = rtl_cell_area.y + y_offset;
3071 if (max_y < rtl_cell_area.y + y_offset + height)
3072 max_y = rtl_cell_area.y + y_offset + height;
3076 else if (action == CELL_ACTION_EVENT)
3078 gboolean try_event = FALSE;
3082 if (special_cells == 1)
3084 /* only 1 activatable cell -> whole column can activate */
3085 if (cell_area->x <= ((GdkEventButton *)event)->x &&
3086 cell_area->x + cell_area->width > ((GdkEventButton *)event)->x)
3089 else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x &&
3090 rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x)
3091 /* only activate cell if the user clicked on an individual
3096 else if (special_cells > 1 && info->has_focus)
3098 else if (special_cells == 1)
3103 gboolean visible, mode;
3105 g_object_get (info->cell,
3106 "visible", &visible,
3109 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
3111 if (gtk_cell_renderer_activate (info->cell,
3113 tree_column->tree_view,
3115 &rtl_background_area,
3119 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3123 else if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
3126 gtk_cell_renderer_start_editing (info->cell,
3128 tree_column->tree_view,
3130 &rtl_background_area,
3134 if (*editable_widget != NULL)
3136 g_return_val_if_fail (GTK_IS_CELL_EDITABLE (*editable_widget), FALSE);
3137 info->in_editing_mode = TRUE;
3138 gtk_tree_view_column_focus_cell (tree_column, info->cell);
3140 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3147 flags &= ~GTK_CELL_RENDERER_FOCUSED;
3149 real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing);
3150 real_background_area.x += (real_background_area.width + tree_column->spacing);
3152 /* Only needed for first cell */
3156 /* fill focus_rectangle when required */
3157 if (action == CELL_ACTION_FOCUS)
3159 if (min_x >= max_x || min_y >= max_y)
3161 *focus_rectangle = *cell_area;
3162 /* don't change the focus_rectangle, just draw it nicely inside
3167 focus_rectangle->x = min_x - focus_line_width;
3168 focus_rectangle->y = min_y - focus_line_width;
3169 focus_rectangle->width = (max_x - min_x) + 2 * focus_line_width;
3170 focus_rectangle->height = (max_y - min_y) + 2 * focus_line_width;
3178 * gtk_tree_view_column_cell_render:
3179 * @tree_column: A #GtkTreeViewColumn.
3180 * @window: a #GdkDrawable to draw to
3181 * @background_area: entire cell area (including tree expanders and maybe padding on the sides)
3182 * @cell_area: area normally rendered by a cell renderer
3183 * @expose_area: area that actually needs updating
3184 * @flags: flags that affect rendering
3186 * Renders the cell contained by #tree_column. This is used primarily by the
3190 _gtk_tree_view_column_cell_render (GtkTreeViewColumn *tree_column,
3192 const GdkRectangle *background_area,
3193 const GdkRectangle *cell_area,
3194 const GdkRectangle *expose_area,
3197 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3198 g_return_if_fail (background_area != NULL);
3199 g_return_if_fail (cell_area != NULL);
3200 g_return_if_fail (expose_area != NULL);
3202 gtk_tree_view_column_cell_process_action (tree_column,
3209 NULL, NULL, NULL, NULL);
3213 _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column,
3214 GtkCellEditable **editable_widget,
3217 const GdkRectangle *background_area,
3218 const GdkRectangle *cell_area,
3221 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
3223 return gtk_tree_view_column_cell_process_action (tree_column,
3236 _gtk_tree_view_column_get_focus_area (GtkTreeViewColumn *tree_column,
3237 const GdkRectangle *background_area,
3238 const GdkRectangle *cell_area,
3239 GdkRectangle *focus_area)
3241 gtk_tree_view_column_cell_process_action (tree_column,
3253 /* cell list manipulation */
3255 gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column)
3257 GList *list = tree_column->cell_list;
3259 /* first GTK_PACK_START cell we find */
3260 for ( ; list; list = list->next)
3262 GtkTreeViewColumnCellInfo *info = list->data;
3263 if (info->pack == GTK_PACK_START)
3267 /* hmm, else the *last* GTK_PACK_END cell */
3268 list = g_list_last (tree_column->cell_list);
3270 for ( ; list; list = list->prev)
3272 GtkTreeViewColumnCellInfo *info = list->data;
3273 if (info->pack == GTK_PACK_END)
3281 gtk_tree_view_column_cell_last (GtkTreeViewColumn *tree_column)
3283 GList *list = tree_column->cell_list;
3285 /* *first* GTK_PACK_END cell we find */
3286 for ( ; list ; list = list->next)
3288 GtkTreeViewColumnCellInfo *info = list->data;
3289 if (info->pack == GTK_PACK_END)
3293 /* hmm, else the last GTK_PACK_START cell */
3294 list = g_list_last (tree_column->cell_list);
3296 for ( ; list; list = list->prev)
3298 GtkTreeViewColumnCellInfo *info = list->data;
3299 if (info->pack == GTK_PACK_START)
3307 gtk_tree_view_column_cell_next (GtkTreeViewColumn *tree_column,
3311 GtkTreeViewColumnCellInfo *info = current->data;
3313 if (info->pack == GTK_PACK_START)
3315 for (list = current->next; list; list = list->next)
3317 GtkTreeViewColumnCellInfo *inf = list->data;
3318 if (inf->pack == GTK_PACK_START)
3322 /* out of GTK_PACK_START cells, get *last* GTK_PACK_END one */
3323 list = g_list_last (tree_column->cell_list);
3324 for (; list; list = list->prev)
3326 GtkTreeViewColumnCellInfo *inf = list->data;
3327 if (inf->pack == GTK_PACK_END)
3332 for (list = current->prev; list; list = list->prev)
3334 GtkTreeViewColumnCellInfo *inf = list->data;
3335 if (inf->pack == GTK_PACK_END)
3343 gtk_tree_view_column_cell_prev (GtkTreeViewColumn *tree_column,
3347 GtkTreeViewColumnCellInfo *info = current->data;
3349 if (info->pack == GTK_PACK_END)
3351 for (list = current->next; list; list = list->next)
3353 GtkTreeViewColumnCellInfo *inf = list->data;
3354 if (inf->pack == GTK_PACK_END)
3358 /* out of GTK_PACK_END, get last GTK_PACK_START one */
3359 list = g_list_last (tree_column->cell_list);
3360 for ( ; list; list = list->prev)
3362 GtkTreeViewColumnCellInfo *inf = list->data;
3363 if (inf->pack == GTK_PACK_START)
3368 for (list = current->prev; list; list = list->prev)
3370 GtkTreeViewColumnCellInfo *inf = list->data;
3371 if (inf->pack == GTK_PACK_START)
3379 _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column,
3387 count = _gtk_tree_view_column_count_special_cells (tree_column);
3388 rtl = gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL;
3390 /* if we are the current focus column and have multiple editable cells,
3391 * try to select the next one, else move the focus to the next column
3393 if (GTK_TREE_VIEW (tree_column->tree_view)->priv->focus_column == tree_column)
3398 GList *list = tree_column->cell_list;
3399 GtkTreeViewColumnCellInfo *info = NULL;
3401 /* find current focussed cell */
3402 for ( ; list; list = list->next)
3405 if (info->has_focus)
3409 /* not a focussed cell in the focus column? */
3410 if (!list || !info || !info->has_focus)
3415 prev = gtk_tree_view_column_cell_next (tree_column, list);
3416 next = gtk_tree_view_column_cell_prev (tree_column, list);
3420 next = gtk_tree_view_column_cell_next (tree_column, list);
3421 prev = gtk_tree_view_column_cell_prev (tree_column, list);
3424 info->has_focus = FALSE;
3425 if (direction > 0 && next)
3428 info->has_focus = TRUE;
3431 else if (direction > 0 && !next && !right)
3433 /* keep focus on last cell */
3435 info = gtk_tree_view_column_cell_first (tree_column)->data;
3437 info = gtk_tree_view_column_cell_last (tree_column)->data;
3439 info->has_focus = TRUE;
3442 else if (direction < 0 && prev)
3445 info->has_focus = TRUE;
3448 else if (direction < 0 && !prev && !left)
3450 /* keep focus on first cell */
3452 info = gtk_tree_view_column_cell_last (tree_column)->data;
3454 info = gtk_tree_view_column_cell_first (tree_column)->data;
3456 info->has_focus = TRUE;
3463 /* we get focus, if we have multiple editable cells, give the correct one
3468 GList *list = tree_column->cell_list;
3470 /* clear focus first */
3471 for ( ; list ; list = list->next)
3473 GtkTreeViewColumnCellInfo *info = list->data;
3474 if (info->has_focus)
3475 info->has_focus = FALSE;
3482 list = gtk_tree_view_column_cell_last (tree_column);
3483 else if (direction < 0)
3484 list = gtk_tree_view_column_cell_first (tree_column);
3489 list = gtk_tree_view_column_cell_first (tree_column);
3490 else if (direction < 0)
3491 list = gtk_tree_view_column_cell_last (tree_column);
3495 ((GtkTreeViewColumnCellInfo *) list->data)->has_focus = TRUE;
3502 _gtk_tree_view_column_cell_draw_focus (GtkTreeViewColumn *tree_column,
3504 const GdkRectangle *background_area,
3505 const GdkRectangle *cell_area,
3506 const GdkRectangle *expose_area,
3509 gint focus_line_width;
3510 GtkStateType cell_state;
3512 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3513 gtk_widget_style_get (GTK_WIDGET (tree_column->tree_view),
3514 "focus-line-width", &focus_line_width, NULL);
3515 if (tree_column->editable_widget)
3517 /* This function is only called on the editable row when editing.
3520 gtk_paint_focus (tree_column->tree_view->style,
3522 GTK_WIDGET_STATE (tree_column->tree_view),
3524 tree_column->tree_view,
3526 cell_area->x - focus_line_width,
3527 cell_area->y - focus_line_width,
3528 cell_area->width + 2 * focus_line_width,
3529 cell_area->height + 2 * focus_line_width);
3534 GdkRectangle focus_rectangle;
3535 gtk_tree_view_column_cell_process_action (tree_column,
3545 cell_state = flags & GTK_CELL_RENDERER_SELECTED ? GTK_STATE_SELECTED :
3546 (flags & GTK_CELL_RENDERER_PRELIT ? GTK_STATE_PRELIGHT :
3547 (flags & GTK_CELL_RENDERER_INSENSITIVE ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL));
3548 gtk_paint_focus (tree_column->tree_view->style,
3552 tree_column->tree_view,
3556 focus_rectangle.width,
3557 focus_rectangle.height);
3562 * gtk_tree_view_column_cell_is_visible:
3563 * @tree_column: A #GtkTreeViewColumn
3565 * Returns %TRUE if any of the cells packed into the @tree_column are visible.
3566 * For this to be meaningful, you must first initialize the cells with
3567 * gtk_tree_view_column_cell_set_cell_data()
3569 * Return value: %TRUE, if any of the cells packed into the @tree_column are currently visible
3572 gtk_tree_view_column_cell_is_visible (GtkTreeViewColumn *tree_column)
3576 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), FALSE);
3578 for (list = tree_column->cell_list; list; list = list->next)
3580 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
3582 if (info->cell->visible)
3590 * gtk_tree_view_column_focus_cell:
3591 * @tree_column: A #GtkTreeViewColumn
3592 * @cell: A #GtkCellRenderer
3594 * Sets the current keyboard focus to be at @cell, if the column contains
3595 * 2 or more editable and activatable cells.
3600 gtk_tree_view_column_focus_cell (GtkTreeViewColumn *tree_column,
3601 GtkCellRenderer *cell)
3604 gboolean found_cell = FALSE;
3606 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3607 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
3609 if (_gtk_tree_view_column_count_special_cells (tree_column) < 2)
3612 for (list = tree_column->cell_list; list; list = list->next)
3614 GtkTreeViewColumnCellInfo *info = list->data;
3616 if (info->cell == cell)
3618 info->has_focus = TRUE;
3626 for (list = tree_column->cell_list; list; list = list->next)
3628 GtkTreeViewColumnCellInfo *info = list->data;
3630 if (info->cell != cell)
3631 info->has_focus = FALSE;
3634 /* FIXME: redraw? */
3639 _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column,
3640 gboolean install_handler)
3644 for (list = tree_column->cell_list; list; list = list->next)
3646 GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *) list->data;
3648 info->requested_width = 0;
3650 tree_column->dirty = TRUE;
3651 tree_column->requested_width = -1;
3652 tree_column->width = 0;
3654 if (tree_column->tree_view &&
3655 GTK_WIDGET_REALIZED (tree_column->tree_view))
3657 if (install_handler)
3658 _gtk_tree_view_install_mark_rows_col_dirty (GTK_TREE_VIEW (tree_column->tree_view));
3660 GTK_TREE_VIEW (tree_column->tree_view)->priv->mark_rows_col_dirty = TRUE;
3661 gtk_widget_queue_resize (tree_column->tree_view);
3666 _gtk_tree_view_column_start_editing (GtkTreeViewColumn *tree_column,
3667 GtkCellEditable *cell_editable)
3669 g_return_if_fail (tree_column->editable_widget == NULL);
3671 tree_column->editable_widget = cell_editable;
3675 _gtk_tree_view_column_stop_editing (GtkTreeViewColumn *tree_column)
3679 g_return_if_fail (tree_column->editable_widget != NULL);
3681 tree_column->editable_widget = NULL;
3682 for (list = tree_column->cell_list; list; list = list->next)
3683 ((GtkTreeViewColumnCellInfo *)list->data)->in_editing_mode = FALSE;
3687 _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column,
3688 GtkCellRenderer *cell,
3693 GtkTreeViewColumnCellInfo *info;
3699 list = gtk_tree_view_column_cell_first (column);
3703 info = (GtkTreeViewColumnCellInfo *)list->data;
3705 list = gtk_tree_view_column_cell_next (column, list);
3707 if (info->cell == cell)
3710 if (info->cell->visible)
3711 l += info->real_width + column->spacing;
3716 info = (GtkTreeViewColumnCellInfo *)list->data;
3718 list = gtk_tree_view_column_cell_next (column, list);
3720 if (info->cell->visible)
3721 r += info->real_width + column->spacing;
3724 rtl = (gtk_widget_get_direction (GTK_WIDGET (column->tree_view)) == GTK_TEXT_DIR_RTL);
3726 *left = rtl ? r : l;
3729 *right = rtl ? l : r;
3733 * gtk_tree_view_column_cell_get_position:
3734 * @tree_column: a #GtkTreeViewColumn
3735 * @cell_renderer: a #GtkCellRenderer
3736 * @start_pos: return location for the horizontal position of @cell within
3737 * @tree_column, may be %NULL
3738 * @width: return location for the width of @cell, may be %NULL
3740 * Obtains the horizontal position and size of a cell in a column. If the
3741 * cell is not found in the column, @start_pos and @width are not changed and
3742 * %FALSE is returned.
3744 * Return value: %TRUE if @cell belongs to @tree_column.
3747 gtk_tree_view_column_cell_get_position (GtkTreeViewColumn *tree_column,
3748 GtkCellRenderer *cell_renderer,
3754 gboolean found_cell = FALSE;
3755 GtkTreeViewColumnCellInfo *cellinfo = NULL;
3757 list = gtk_tree_view_column_cell_first (tree_column);
3758 for (; list; list = gtk_tree_view_column_cell_next (tree_column, list))
3760 cellinfo = list->data;
3761 if (cellinfo->cell == cell_renderer)
3767 if (cellinfo->cell->visible)
3768 current_x += cellinfo->real_width;
3774 *start_pos = current_x;
3776 *width = cellinfo->real_width;
3783 * gtk_tree_view_column_queue_resize:
3784 * @tree_column: A #GtkTreeViewColumn
3786 * Flags the column, and the cell renderers added to this column, to have
3787 * their sizes renegotiated.
3792 gtk_tree_view_column_queue_resize (GtkTreeViewColumn *tree_column)
3794 g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column));
3796 if (tree_column->tree_view)
3797 _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE);
3801 * gtk_tree_view_column_get_tree_view:
3802 * @tree_column: A #GtkTreeViewColumn
3804 * Returns the #GtkTreeView wherein @tree_column has been inserted. If
3805 * @column is currently not inserted in any tree view, %NULL is
3808 * Return value: The tree view wherein @column has been inserted if any,
3814 gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column)
3816 g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL);
3818 return tree_column->tree_view;
3822 gtk_tree_view_column_extended_layout_get_desired_size (GtkExtendedLayout *layout,
3823 GtkRequisition *minimal_size,
3824 GtkRequisition *desired_size)
3826 gtk_tree_view_column_cell_get_real_size (GTK_TREE_VIEW_COLUMN (layout),
3828 minimal_size, desired_size);
3832 gtk_tree_view_column_extended_layout_init (GtkExtendedLayoutIface *iface)
3834 iface->get_desired_size = gtk_tree_view_column_extended_layout_get_desired_size;
3838 #define __GTK_TREE_VIEW_COLUMN_C__
3839 #include "gtkaliasdef.c"