X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtktreeviewcolumn.c;h=70dfd24258be80b4ec09a8367317307058304631;hb=f35439bfacf90900e2c24f7ae3da173183c79d34;hp=838010484a69af61f881107e847dc87a31a9d497;hpb=6c935950b2ca743f59bc99a0ae43a45b6ec2e303;p=~andy%2Fgtk diff --git a/gtk/gtktreeviewcolumn.c b/gtk/gtktreeviewcolumn.c index 838010484..70dfd2425 100644 --- a/gtk/gtktreeviewcolumn.c +++ b/gtk/gtktreeviewcolumn.c @@ -17,6 +17,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include #include "gtktreeviewcolumn.h" #include "gtktreeview.h" @@ -28,7 +29,9 @@ #include "gtkhbox.h" #include "gtkmarshalers.h" #include "gtkarrow.h" +#include "gtkprivate.h" #include "gtkintl.h" +#include "gtkalias.h" enum { @@ -36,6 +39,7 @@ enum PROP_VISIBLE, PROP_RESIZABLE, PROP_WIDTH, + PROP_SPACING, PROP_SIZING, PROP_FIXED_WIDTH, PROP_MIN_WIDTH, @@ -73,8 +77,6 @@ struct _GtkTreeViewColumnCellInfo }; /* Type methods */ -static void gtk_tree_view_column_init (GtkTreeViewColumn *tree_column); -static void gtk_tree_view_column_class_init (GtkTreeViewColumnClass *klass); static void gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface); /* GObject methods */ @@ -110,6 +112,7 @@ static void gtk_tree_view_column_cell_layout_clear_attributes (GtkCellLayout static void gtk_tree_view_column_cell_layout_reorder (GtkCellLayout *cell_layout, GtkCellRenderer *cell, gint position); +static GList *gtk_tree_view_column_cell_layout_get_cells (GtkCellLayout *cell_layout); /* Button handling code */ static void gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column); @@ -148,49 +151,17 @@ static GList *gtk_tree_view_column_cell_prev (GtkTreeViewColum GList *current); static void gtk_tree_view_column_clear_attributes_by_info (GtkTreeViewColumn *tree_column, GtkTreeViewColumnCellInfo *info); +/* GtkBuildable implementation */ +static void gtk_tree_view_column_buildable_init (GtkBuildableIface *iface); -static GtkObjectClass *parent_class = NULL; static guint tree_column_signals[LAST_SIGNAL] = { 0 }; +G_DEFINE_TYPE_WITH_CODE (GtkTreeViewColumn, gtk_tree_view_column, GTK_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT, + gtk_tree_view_column_cell_layout_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, + gtk_tree_view_column_buildable_init)) -GType -gtk_tree_view_column_get_type (void) -{ - static GType tree_column_type = 0; - - if (!tree_column_type) - { - static const GTypeInfo tree_column_info = - { - sizeof (GtkTreeViewColumnClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_tree_view_column_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkTreeViewColumn), - 0, - (GInstanceInitFunc) gtk_tree_view_column_init - }; - - static const GInterfaceInfo cell_layout_info = - { - (GInterfaceInitFunc) gtk_tree_view_column_cell_layout_init, - NULL, - NULL - }; - - tree_column_type = - g_type_register_static (GTK_TYPE_OBJECT, "GtkTreeViewColumn", - &tree_column_info, 0); - - g_type_add_interface_static (tree_column_type, - GTK_TYPE_CELL_LAYOUT, - &cell_layout_info); - } - - return tree_column_type; -} static void gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) @@ -199,8 +170,6 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) object_class = (GObjectClass*) class; - parent_class = g_type_class_peek_parent (class); - class->clicked = NULL; object_class->finalize = gtk_tree_view_column_finalize; @@ -208,7 +177,7 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) object_class->get_property = gtk_tree_view_column_get_property; tree_column_signals[CLICKED] = - g_signal_new ("clicked", + g_signal_new (I_("clicked"), G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkTreeViewColumnClass, clicked), @@ -222,7 +191,7 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Visible"), P_("Whether to display the column"), TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_RESIZABLE, @@ -230,7 +199,7 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Resizable"), P_("Column is user-resizable"), FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_WIDTH, @@ -240,45 +209,54 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) 0, G_MAXINT, 0, - G_PARAM_READABLE)); + GTK_PARAM_READABLE)); + g_object_class_install_property (object_class, + PROP_SPACING, + g_param_spec_int ("spacing", + P_("Spacing"), + P_("Space which is inserted between cells"), + 0, + G_MAXINT, + 0, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SIZING, g_param_spec_enum ("sizing", P_("Sizing"), P_("Resize mode of the column"), GTK_TYPE_TREE_VIEW_COLUMN_SIZING, - GTK_TREE_VIEW_COLUMN_AUTOSIZE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_TREE_VIEW_COLUMN_GROW_ONLY, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_FIXED_WIDTH, - g_param_spec_int ("fixed_width", + g_param_spec_int ("fixed-width", P_("Fixed Width"), P_("Current fixed width of the column"), 1, G_MAXINT, 1, /* not useful */ - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_MIN_WIDTH, - g_param_spec_int ("min_width", + g_param_spec_int ("min-width", P_("Minimum Width"), P_("Minimum allowed width of the column"), -1, G_MAXINT, -1, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_MAX_WIDTH, - g_param_spec_int ("max_width", + g_param_spec_int ("max-width", P_("Maximum Width"), P_("Maximum allowed width of the column"), -1, G_MAXINT, -1, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_TITLE, @@ -286,7 +264,7 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Title"), P_("Title to appear in column header"), "", - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_EXPAND, @@ -294,15 +272,15 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Expand"), P_("Column gets share of extra width allocated to the widget"), FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_CLICKABLE, g_param_spec_boolean ("clickable", P_("Clickable"), P_("Whether the header can be clicked"), - TRUE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + FALSE, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, @@ -311,7 +289,7 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Widget"), P_("Widget to put in column header button instead of column title"), GTK_TYPE_WIDGET, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_ALIGNMENT, @@ -320,8 +298,8 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("X Alignment of the column header text or widget"), 0.0, 1.0, - 0.5, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + 0.0, + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_REORDERABLE, @@ -329,27 +307,35 @@ gtk_tree_view_column_class_init (GtkTreeViewColumnClass *class) P_("Reorderable"), P_("Whether the column can be reordered around the headers"), FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SORT_INDICATOR, - g_param_spec_boolean ("sort_indicator", + g_param_spec_boolean ("sort-indicator", P_("Sort indicator"), P_("Whether to show a sort indicator"), FALSE, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SORT_ORDER, - g_param_spec_enum ("sort_order", + g_param_spec_enum ("sort-order", P_("Sort order"), P_("Sort direction the sort indicator should indicate"), GTK_TYPE_SORT_TYPE, GTK_SORT_ASCENDING, - G_PARAM_READABLE | G_PARAM_WRITABLE)); + GTK_PARAM_READWRITE)); } +static void +gtk_tree_view_column_buildable_init (GtkBuildableIface *iface) +{ + iface->add_child = _gtk_cell_layout_buildable_add_child; + iface->custom_tag_start = _gtk_cell_layout_buildable_custom_tag_start; + iface->custom_tag_end = _gtk_cell_layout_buildable_custom_tag_end; +} + static void gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface) { @@ -360,6 +346,7 @@ gtk_tree_view_column_cell_layout_init (GtkCellLayoutIface *iface) iface->set_cell_data_func = gtk_tree_view_column_cell_layout_set_cell_data_func; iface->clear_attributes = gtk_tree_view_column_cell_layout_clear_attributes; iface->reorder = gtk_tree_view_column_cell_layout_reorder; + iface->get_cells = gtk_tree_view_column_cell_layout_get_cells; } static void @@ -368,6 +355,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->button = NULL; tree_column->xalign = 0.0; tree_column->width = 0; + tree_column->spacing = 0; tree_column->requested_width = -1; tree_column->min_width = -1; tree_column->max_width = -1; @@ -375,6 +363,7 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->column_type = GTK_TREE_VIEW_COLUMN_GROW_ONLY; tree_column->visible = TRUE; tree_column->resizable = FALSE; + tree_column->expand = FALSE; tree_column->clickable = FALSE; tree_column->dirty = TRUE; tree_column->sort_order = GTK_SORT_ASCENDING; @@ -385,7 +374,9 @@ gtk_tree_view_column_init (GtkTreeViewColumn *tree_column) tree_column->sort_column_id = -1; tree_column->reorderable = FALSE; tree_column->maybe_reordered = FALSE; + tree_column->fixed_width = 1; tree_column->use_resized_width = FALSE; + tree_column->title = g_strdup (""); } static void @@ -416,7 +407,7 @@ gtk_tree_view_column_finalize (GObject *object) if (tree_column->child) g_object_unref (tree_column->child); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gtk_tree_view_column_parent_class)->finalize (object); } static void @@ -461,6 +452,11 @@ gtk_tree_view_column_set_property (GObject *object, g_value_get_int (value)); break; + case PROP_SPACING: + gtk_tree_view_column_set_spacing (tree_column, + g_value_get_int (value)); + break; + case PROP_TITLE: gtk_tree_view_column_set_title (tree_column, g_value_get_string (value)); @@ -534,6 +530,11 @@ gtk_tree_view_column_get_property (GObject *object, gtk_tree_view_column_get_width (tree_column)); break; + case PROP_SPACING: + g_value_set_int (value, + gtk_tree_view_column_get_spacing (tree_column)); + break; + case PROP_SIZING: g_value_set_enum (value, gtk_tree_view_column_get_sizing (tree_column)); @@ -615,8 +616,7 @@ gtk_tree_view_column_cell_layout_pack_start (GtkCellLayout *cell_layout, column = GTK_TREE_VIEW_COLUMN (cell_layout); g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell)); - g_object_ref (cell); - gtk_object_sink (GTK_OBJECT (cell)); + g_object_ref_sink (cell); cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1); cell_info->cell = cell; @@ -640,8 +640,7 @@ gtk_tree_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout, column = GTK_TREE_VIEW_COLUMN (cell_layout); g_return_if_fail (! gtk_tree_view_column_get_cell_info (column, cell)); - g_object_ref (cell); - gtk_object_sink (GTK_OBJECT (cell)); + g_object_ref_sink (cell); cell_info = g_new0 (GtkTreeViewColumnCellInfo, 1); cell_info->cell = cell; @@ -656,23 +655,21 @@ gtk_tree_view_column_cell_layout_pack_end (GtkCellLayout *cell_layout, static void gtk_tree_view_column_cell_layout_clear (GtkCellLayout *cell_layout) { - GList *list; GtkTreeViewColumn *column; g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (cell_layout)); column = GTK_TREE_VIEW_COLUMN (cell_layout); - for (list = column->cell_list; list; list = list->next) + while (column->cell_list) { - GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data; + GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)column->cell_list->data; - gtk_tree_view_column_clear_attributes (column, info->cell); + gtk_tree_view_column_cell_layout_clear_attributes (cell_layout, info->cell); g_object_unref (info->cell); g_free (info); + column->cell_list = g_list_delete_link (column->cell_list, + column->cell_list); } - - g_list_free (column->cell_list); - column->cell_list = NULL; } static void @@ -740,7 +737,8 @@ gtk_tree_view_column_cell_layout_clear_attributes (GtkCellLayout *cell_layout column = GTK_TREE_VIEW_COLUMN (cell_layout); info = gtk_tree_view_column_get_cell_info (column, cell_renderer); - gtk_tree_view_column_clear_attributes_by_info (column, info); + if (info) + gtk_tree_view_column_clear_attributes_by_info (column, info); } static void @@ -764,10 +762,11 @@ gtk_tree_view_column_cell_layout_reorder (GtkCellLayout *cell_layout, g_return_if_fail (link != NULL); - column->cell_list = g_list_remove_link (column->cell_list, link); + column->cell_list = g_list_delete_link (column->cell_list, link); column->cell_list = g_list_insert (column->cell_list, info, position); - gtk_widget_queue_draw (column->tree_view); + if (column->tree_view) + gtk_widget_queue_draw (column->tree_view); } static void @@ -859,10 +858,18 @@ gtk_tree_view_column_create_button (GtkTreeViewColumn *tree_column) static void gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) { + gint sort_column_id = -1; GtkWidget *hbox; GtkWidget *alignment; GtkWidget *arrow; GtkWidget *current_child; + GtkArrowType arrow_type = GTK_ARROW_NONE; + GtkTreeModel *model; + + if (tree_column->tree_view) + model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_column->tree_view)); + else + model = NULL; /* Create a button if necessary */ if (tree_column->visible && @@ -913,25 +920,39 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) ""); } - switch (tree_column->sort_order) + if (GTK_IS_TREE_SORTABLE (model)) + gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), + &sort_column_id, + NULL); + + if (tree_column->show_sort_indicator) { - case GTK_SORT_ASCENDING: - gtk_arrow_set (GTK_ARROW (arrow), - GTK_ARROW_DOWN, - GTK_SHADOW_IN); - break; + gboolean alternative; - case GTK_SORT_DESCENDING: - gtk_arrow_set (GTK_ARROW (arrow), - GTK_ARROW_UP, - GTK_SHADOW_IN); - break; - - default: - g_warning (G_STRLOC": bad sort order"); - break; + g_object_get (gtk_widget_get_settings (tree_column->tree_view), + "gtk-alternative-sort-arrows", &alternative, + NULL); + + switch (tree_column->sort_order) + { + case GTK_SORT_ASCENDING: + arrow_type = alternative ? GTK_ARROW_UP : GTK_ARROW_DOWN; + break; + + case GTK_SORT_DESCENDING: + arrow_type = alternative ? GTK_ARROW_DOWN : GTK_ARROW_UP; + break; + + default: + g_warning (G_STRLOC": bad sort order"); + break; + } } + gtk_arrow_set (GTK_ARROW (arrow), + arrow_type, + GTK_SHADOW_IN); + /* Put arrow on the right if the text is left-or-center justified, and on the * left otherwise; do this by packing boxes, so flipping text direction will * reverse things @@ -951,7 +972,8 @@ gtk_tree_view_column_update_button (GtkTreeViewColumn *tree_column) } g_object_unref (arrow); - if (tree_column->show_sort_indicator) + if (tree_column->show_sort_indicator + || (GTK_IS_TREE_SORTABLE (model) && tree_column->sort_column_id >= 0)) gtk_widget_show (arrow); else gtk_widget_hide (arrow); @@ -1023,22 +1045,23 @@ gtk_tree_view_column_button_event (GtkWidget *widget, g_return_val_if_fail (event != NULL, FALSE); if (event->type == GDK_BUTTON_PRESS && - column->reorderable) + column->reorderable && + ((GdkEventButton *)event)->button == 1) { column->maybe_reordered = TRUE; - gdk_window_get_pointer (widget->window, + gdk_window_get_pointer (GTK_BUTTON (widget)->event_window, &column->drag_x, &column->drag_y, NULL); gtk_widget_grab_focus (widget); } - if (event->type == GDK_BUTTON_RELEASE && - column->maybe_reordered) + if (event->type == GDK_BUTTON_RELEASE || + event->type == GDK_LEAVE_NOTIFY) column->maybe_reordered = FALSE; - + if (event->type == GDK_MOTION_NOTIFY && - (column->maybe_reordered) && + column->maybe_reordered && (gtk_drag_check_threshold (widget, column->drag_x, column->drag_y, @@ -1046,10 +1069,6 @@ gtk_tree_view_column_button_event (GtkWidget *widget, (gint) ((GdkEventMotion *)event)->y))) { column->maybe_reordered = FALSE; - /* this is to change our drag_x to be relative to - * tree_view->priv->bin_window, instead of our window. - */ - column->drag_x -= column->button->allocation.x; _gtk_tree_view_column_start_drag (GTK_TREE_VIEW (column->tree_view), column); return TRUE; } @@ -1201,10 +1220,12 @@ gtk_tree_view_column_setup_sort_column_id_callback (GtkTreeViewColumn *tree_colu { gtk_tree_view_column_set_sort_indicator (tree_column, TRUE); gtk_tree_view_column_set_sort_order (tree_column, real_order); - - return; + } + else + { + gtk_tree_view_column_set_sort_indicator (tree_column, FALSE); } - } + } } @@ -1250,7 +1271,7 @@ _gtk_tree_view_column_realize_button (GtkTreeViewColumn *column) attr.width = TREE_VIEW_DRAG_WIDTH; attr.height = tree_view->priv->header_height; - attr.x = (column->button->allocation.x + (rtl ? 0 : column->button->allocation.width)) - 3; + attr.x = (column->button->allocation.x + (rtl ? 0 : column->button->allocation.width)) - TREE_VIEW_DRAG_WIDTH / 2; column->window = gdk_window_new (tree_view->priv->header_window, &attr, attributes_mask); gdk_window_set_user_data (column->window, tree_view); @@ -1281,6 +1302,7 @@ _gtk_tree_view_column_unset_model (GtkTreeViewColumn *column, column->sort_column_changed_signal); column->sort_column_changed_signal = 0; } + gtk_tree_view_column_set_sort_indicator (column, FALSE); } void @@ -1421,12 +1443,12 @@ gtk_tree_view_column_new (void) * gtk_tree_view_column_set_attributes() on the newly created #GtkTreeViewColumn. * * Here's a simple example: - * + * |[ * enum { TEXT_COLUMN, COLOR_COLUMN, N_COLUMNS }; * ... * { * GtkTreeViewColumn *column; - * GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); + * GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); * * column = gtk_tree_view_column_new_with_attributes ("Title", * renderer, @@ -1434,7 +1456,7 @@ gtk_tree_view_column_new (void) * "foreground", COLOR_COLUMN, * NULL); * } - * + * ]| * * Return value: A newly created #GtkTreeViewColumn. **/ @@ -1544,6 +1566,12 @@ gtk_tree_view_column_get_cell_renderers (GtkTreeViewColumn *tree_column) return retval; } +static GList * +gtk_tree_view_column_cell_layout_get_cells (GtkCellLayout *layout) +{ + return gtk_tree_view_column_get_cell_renderers (GTK_TREE_VIEW_COLUMN (layout)); +} + /** * gtk_tree_view_column_add_attribute: * @tree_column: A #GtkTreeViewColumn. @@ -1889,7 +1917,7 @@ gtk_tree_view_column_set_fixed_width (GtkTreeViewColumn *tree_column, gtk_widget_queue_resize (tree_column->tree_view); } - g_object_notify (G_OBJECT (tree_column), "fixed_width"); + g_object_notify (G_OBJECT (tree_column), "fixed-width"); } /** @@ -1940,9 +1968,9 @@ gtk_tree_view_column_set_min_width (GtkTreeViewColumn *tree_column, if (tree_column->max_width != -1 && tree_column->max_width < min_width) { tree_column->max_width = min_width; - g_object_notify (G_OBJECT (tree_column), "max_width"); + g_object_notify (G_OBJECT (tree_column), "max-width"); } - g_object_notify (G_OBJECT (tree_column), "min_width"); + g_object_notify (G_OBJECT (tree_column), "min-width"); g_object_thaw_notify (G_OBJECT (tree_column)); if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) @@ -2000,9 +2028,9 @@ gtk_tree_view_column_set_max_width (GtkTreeViewColumn *tree_column, if (max_width != -1 && max_width < tree_column->min_width) { tree_column->min_width = max_width; - g_object_notify (G_OBJECT (tree_column), "min_width"); + g_object_notify (G_OBJECT (tree_column), "min-width"); } - g_object_notify (G_OBJECT (tree_column), "max_width"); + g_object_notify (G_OBJECT (tree_column), "max-width"); g_object_thaw_notify (G_OBJECT (tree_column)); if (tree_column->column_type == GTK_TREE_VIEW_COLUMN_AUTOSIZE) @@ -2089,7 +2117,7 @@ gtk_tree_view_column_get_title (GtkTreeViewColumn *tree_column) /** * gtk_tree_view_column_set_expand: * @tree_column: A #GtkTreeViewColumn - * @expand: + * @expand: %TRUE if the column should take available extra space, %FALSE if not * * Sets the column to take available extra space. This space is shared equally * amongst all columns that have the expand set to %TRUE. If no column has this @@ -2121,7 +2149,7 @@ gtk_tree_view_column_set_expand (GtkTreeViewColumn *tree_column, /** * gtk_tree_view_column_get_expand: - * @tree_column: + * @tree_column: a #GtkTreeViewColumn * * Return %TRUE if the column expands to take any available space. * @@ -2192,10 +2220,7 @@ gtk_tree_view_column_set_widget (GtkTreeViewColumn *tree_column, g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget)); if (widget) - { - g_object_ref (widget); - gtk_object_sink (GTK_OBJECT (widget)); - } + g_object_ref_sink (widget); if (tree_column->child) g_object_unref (tree_column->child); @@ -2403,7 +2428,7 @@ gtk_tree_view_column_set_sort_indicator (GtkTreeViewColumn *tree_column, tree_column->show_sort_indicator = setting; gtk_tree_view_column_update_button (tree_column); - g_object_notify (G_OBJECT (tree_column), "sort_indicator"); + g_object_notify (G_OBJECT (tree_column), "sort-indicator"); } /** @@ -2450,7 +2475,7 @@ gtk_tree_view_column_set_sort_order (GtkTreeViewColumn *tree_column, tree_column->sort_order = order; gtk_tree_view_column_update_button (tree_column); - g_object_notify (G_OBJECT (tree_column), "sort_order"); + g_object_notify (G_OBJECT (tree_column), "sort-order"); } /** @@ -2494,7 +2519,6 @@ gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column, GList *cell_list; g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); - g_return_if_fail (tree_column->cell_list != NULL); if (tree_model == NULL) return; @@ -2509,10 +2533,10 @@ gtk_tree_view_column_cell_set_cell_data (GtkTreeViewColumn *tree_column, g_object_freeze_notify (cell); if (info->cell->is_expander != is_expander) - g_object_set (cell, "is_expander", is_expander, NULL); + g_object_set (cell, "is-expander", is_expander, NULL); if (info->cell->is_expanded != is_expanded) - g_object_set (cell, "is_expanded", is_expanded, NULL); + g_object_set (cell, "is-expanded", is_expanded, NULL); while (list && list->next) { @@ -2598,6 +2622,9 @@ gtk_tree_view_column_cell_get_size (GtkTreeViewColumn *tree_column, /* rendering, event handling and rendering focus are somewhat complicated, and * quite a bit of code. Rather than duplicate them, we put them together to * keep the code in one place. + * + * To better understand what's going on, check out + * docs/tree-column-sizing.png */ enum { CELL_ACTION_RENDER, @@ -2622,6 +2649,7 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, GdkRectangle real_cell_area; GdkRectangle real_background_area; GdkRectangle real_expose_area = *cell_area; + gint depth = 0; gint expand_cell_count = 0; gint full_requested_width = 0; gint extra_space; @@ -2630,6 +2658,7 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, gint special_cells; gint horizontal_separator; gboolean cursor_row = FALSE; + gboolean first_cell = TRUE; gboolean rtl; /* If we have rtl text, we need to transform our areas */ GdkRectangle rtl_cell_area; @@ -2677,9 +2706,17 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, real_cell_area = *cell_area; real_background_area = *background_area; + real_cell_area.x += focus_line_width; + real_cell_area.y += focus_line_width; + real_cell_area.height -= 2 * focus_line_width; - /* Find out how many extra space we have to allocate */ + if (rtl) + depth = real_background_area.width - real_cell_area.width; + else + depth = real_cell_area.x - real_background_area.x; + + /* Find out how much extra space we have to allocate */ for (list = tree_column->cell_list; list; list = list->next) { GtkTreeViewColumnCellInfo *info = (GtkTreeViewColumnCellInfo *)list->data; @@ -2690,10 +2727,14 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, if (info->expand == TRUE) expand_cell_count ++; full_requested_width += info->requested_width; - } - extra_space = cell_area->width + horizontal_separator - full_requested_width; + if (!first_cell) + full_requested_width += tree_column->spacing; + first_cell = FALSE; + } + + extra_space = cell_area->width - full_requested_width; if (extra_space < 0) extra_space = 0; else if (extra_space > 0 && expand_cell_count > 0) @@ -2717,13 +2758,31 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, info->real_width = info->requested_width + (info->expand?extra_space:0); + /* We constrain ourselves to only the width available */ + if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width) + { + info->real_width = cell_area->x + cell_area->width - real_cell_area.x; + } + + if (real_cell_area.x > cell_area->x + cell_area->width) + break; + real_cell_area.width = info->real_width; - real_background_area.width= - real_cell_area.x + real_cell_area.width - real_background_area.x; real_cell_area.width -= 2 * focus_line_width; + if (list->next) + { + real_background_area.width = info->real_width + depth; + } + else + { + /* fill the rest of background for the last cell */ + real_background_area.width = background_area->x + background_area->width - real_background_area.x; + } + rtl_cell_area = real_cell_area; rtl_background_area = real_background_area; + if (rtl) { rtl_cell_area.x = cell_area->x + cell_area->width - (real_cell_area.x - cell_area->x) - real_cell_area.width; @@ -2741,7 +2800,6 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, &real_expose_area, flags); } - /* FOCUS */ else if (action == CELL_ACTION_FOCUS) { @@ -2815,8 +2873,8 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, event, tree_column->tree_view, path_string, - background_area, - cell_area, + &rtl_background_area, + &rtl_cell_area, flags)) { flags &= ~GTK_CELL_RENDERER_FOCUSED; @@ -2830,8 +2888,8 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, event, tree_column->tree_view, path_string, - background_area, - cell_area, + &rtl_background_area, + &rtl_cell_area, flags); if (*editable_widget != NULL) @@ -2850,8 +2908,11 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, flags &= ~GTK_CELL_RENDERER_FOCUSED; - real_cell_area.x += (real_cell_area.width + tree_column->spacing); - real_background_area.x += (real_background_area.width + tree_column->spacing); + real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing); + real_background_area.x += real_background_area.width + tree_column->spacing; + + /* Only needed for first cell */ + depth = 0; } /* iterate list for PACK_END cells */ @@ -2872,10 +2933,18 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, info->real_width = info->requested_width + (info->expand?extra_space:0); + /* We constrain ourselves to only the width available */ + if (real_cell_area.x - focus_line_width + info->real_width > cell_area->x + cell_area->width) + { + info->real_width = cell_area->x + cell_area->width - real_cell_area.x; + } + + if (real_cell_area.x > cell_area->x + cell_area->width) + break; + real_cell_area.width = info->real_width; - real_background_area.width = - real_cell_area.x + real_cell_area.width - real_background_area.x; real_cell_area.width -= 2 * focus_line_width; + real_background_area.width = info->real_width + depth; rtl_cell_area = real_cell_area; rtl_background_area = real_background_area; @@ -2943,8 +3012,8 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, cell_area->x + cell_area->width > ((GdkEventButton *)event)->x) try_event = TRUE; } - else if (real_cell_area.x <= ((GdkEventButton *)event)->x && - real_cell_area.x + real_cell_area.width > ((GdkEventButton *)event)->x) + else if (rtl_cell_area.x <= ((GdkEventButton *)event)->x && + rtl_cell_area.x + rtl_cell_area.width > ((GdkEventButton *)event)->x) /* only activate cell if the user clicked on an individual * cell */ @@ -2969,8 +3038,8 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, event, tree_column->tree_view, path_string, - background_area, - cell_area, + &rtl_background_area, + &rtl_cell_area, flags)) { flags &= ~GTK_CELL_RENDERER_FOCUSED; @@ -2984,8 +3053,8 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, event, tree_column->tree_view, path_string, - background_area, - cell_area, + &rtl_background_area, + &rtl_cell_area, flags); if (*editable_widget != NULL) @@ -3003,8 +3072,11 @@ gtk_tree_view_column_cell_process_action (GtkTreeViewColumn *tree_column, flags &= ~GTK_CELL_RENDERER_FOCUSED; - real_cell_area.x += (real_cell_area.width + tree_column->spacing); + real_cell_area.x += (real_cell_area.width + 2 * focus_line_width + tree_column->spacing); real_background_area.x += (real_background_area.width + tree_column->spacing); + + /* Only needed for first cell */ + depth = 0; } /* fill focus_rectangle when required */ @@ -3086,6 +3158,24 @@ _gtk_tree_view_column_cell_event (GtkTreeViewColumn *tree_column, path_string); } +void +_gtk_tree_view_column_get_focus_area (GtkTreeViewColumn *tree_column, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GdkRectangle *focus_area) +{ + gtk_tree_view_column_cell_process_action (tree_column, + NULL, + background_area, + cell_area, + 0, + CELL_ACTION_FOCUS, + NULL, + focus_area, + NULL, NULL, NULL); +} + + /* cell list manipulation */ static GList * gtk_tree_view_column_cell_first (GtkTreeViewColumn *tree_column) @@ -3218,8 +3308,10 @@ _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, gboolean right) { gint count; + gboolean rtl; count = _gtk_tree_view_column_count_special_cells (tree_column); + rtl = gtk_widget_get_direction (GTK_WIDGET (tree_column->tree_view)) == GTK_TEXT_DIR_RTL; /* if we are the current focus column and have multiple editable cells, * try to select the next one, else move the focus to the next column @@ -3244,8 +3336,16 @@ _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, if (!list || !info || !info->has_focus) return FALSE; - next = gtk_tree_view_column_cell_next (tree_column, list); - prev = gtk_tree_view_column_cell_prev (tree_column, list); + if (rtl) + { + prev = gtk_tree_view_column_cell_next (tree_column, list); + next = gtk_tree_view_column_cell_prev (tree_column, list); + } + else + { + next = gtk_tree_view_column_cell_next (tree_column, list); + prev = gtk_tree_view_column_cell_prev (tree_column, list); + } info->has_focus = FALSE; if (direction > 0 && next) @@ -3256,8 +3356,12 @@ _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, } else if (direction > 0 && !next && !right) { - /* keep focus on latest cell */ - info = gtk_tree_view_column_cell_last (tree_column)->data; + /* keep focus on last cell */ + if (rtl) + info = gtk_tree_view_column_cell_first (tree_column)->data; + else + info = gtk_tree_view_column_cell_last (tree_column)->data; + info->has_focus = TRUE; return TRUE; } @@ -3270,7 +3374,11 @@ _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, else if (direction < 0 && !prev && !left) { /* keep focus on first cell */ - info = gtk_tree_view_column_cell_first (tree_column)->data; + if (rtl) + info = gtk_tree_view_column_cell_last (tree_column)->data; + else + info = gtk_tree_view_column_cell_first (tree_column)->data; + info->has_focus = TRUE; return TRUE; } @@ -3293,11 +3401,26 @@ _gtk_tree_view_column_cell_focus (GtkTreeViewColumn *tree_column, info->has_focus = FALSE; } - if (direction > 0) - ((GtkTreeViewColumnCellInfo *)gtk_tree_view_column_cell_first (tree_column)->data)->has_focus = TRUE; - else if (direction < 0) - ((GtkTreeViewColumnCellInfo *)gtk_tree_view_column_cell_last (tree_column)->data)->has_focus = TRUE; + list = NULL; + if (rtl) + { + if (direction > 0) + list = gtk_tree_view_column_cell_last (tree_column); + else if (direction < 0) + list = gtk_tree_view_column_cell_first (tree_column); + } + else + { + if (direction > 0) + list = gtk_tree_view_column_cell_first (tree_column); + else if (direction < 0) + list = gtk_tree_view_column_cell_last (tree_column); + } + + if (list) + ((GtkTreeViewColumnCellInfo *) list->data)->has_focus = TRUE; } + return TRUE; } @@ -3451,7 +3574,6 @@ _gtk_tree_view_column_cell_set_dirty (GtkTreeViewColumn *tree_column, info->requested_width = 0; } tree_column->dirty = TRUE; - tree_column->resized_width = MAX (tree_column->requested_width, tree_column->button_request); tree_column->requested_width = -1; tree_column->width = 0; @@ -3494,56 +3616,43 @@ _gtk_tree_view_column_get_neighbor_sizes (GtkTreeViewColumn *column, gint *right) { GList *list; + GtkTreeViewColumnCellInfo *info; + gint l, r; + gboolean rtl; - if (left) - { - *left = 0; - list = gtk_tree_view_column_cell_first (column); + l = r = 0; - for (; list; list = gtk_tree_view_column_cell_next (column, list)) - { - GtkTreeViewColumnCellInfo *info = - (GtkTreeViewColumnCellInfo *)list->data; + list = gtk_tree_view_column_cell_first (column); - if (info->cell == cell) - break; + while (list) + { + info = (GtkTreeViewColumnCellInfo *)list->data; + + list = gtk_tree_view_column_cell_next (column, list); - if (info->cell->visible) - *left += info->real_width; - } + if (info->cell == cell) + break; + + if (info->cell->visible) + l += info->real_width + column->spacing; } - if (right) + while (list) { - GList *next; - - *right = 0; - list = gtk_tree_view_column_cell_first (column); - - for (; list; list = gtk_tree_view_column_cell_next (column, list)) - { - GtkTreeViewColumnCellInfo *info = - (GtkTreeViewColumnCellInfo *)list->data; + info = (GtkTreeViewColumnCellInfo *)list->data; + + list = gtk_tree_view_column_cell_next (column, list); - if (info->cell == cell) - break; - } + if (info->cell->visible) + r += info->real_width + column->spacing; + } - /* skip cell */ - next = gtk_tree_view_column_cell_next (column, list); - if (list && next) - { - list = next; - for ( ; list; list = gtk_tree_view_column_cell_next (column, list)) - { - GtkTreeViewColumnCellInfo *info = - (GtkTreeViewColumnCellInfo *)list->data; + rtl = (gtk_widget_get_direction (GTK_WIDGET (column->tree_view)) == GTK_TEXT_DIR_RTL); + if (left) + *left = rtl ? r : l; - if (info->cell->visible) - *right += info->real_width; - } - } - } + if (right) + *right = rtl ? l : r; } /** @@ -3596,3 +3705,44 @@ gtk_tree_view_column_cell_get_position (GtkTreeViewColumn *tree_column, return found_cell; } +/** + * gtk_tree_view_column_queue_resize: + * @tree_column: A #GtkTreeViewColumn + * + * Flags the column, and the cell renderers added to this column, to have + * their sizes renegotiated. + * + * Since: 2.8 + **/ +void +gtk_tree_view_column_queue_resize (GtkTreeViewColumn *tree_column) +{ + g_return_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column)); + + if (tree_column->tree_view) + _gtk_tree_view_column_cell_set_dirty (tree_column, TRUE); +} + +/** + * gtk_tree_view_column_get_tree_view: + * @tree_column: A #GtkTreeViewColumn + * + * Returns the #GtkTreeView wherein @tree_column has been inserted. If + * @column is currently not inserted in any tree view, %NULL is + * returned. + * + * Return value: The tree view wherein @column has been inserted if any, + * %NULL otherwise. + * + * Since: 2.12 + */ +GtkWidget * +gtk_tree_view_column_get_tree_view (GtkTreeViewColumn *tree_column) +{ + g_return_val_if_fail (GTK_IS_TREE_VIEW_COLUMN (tree_column), NULL); + + return tree_column->tree_view; +} + +#define __GTK_TREE_VIEW_COLUMN_C__ +#include "gtkaliasdef.c"