X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkiconview.c;h=0c6dc038ce354701c740569e7f2b9e35d77f2ef9;hb=1c796018d1dcba002766673c4070c9d98e95fadb;hp=93367b6415ca241a63493509f30b4949b0c23009;hpb=d736d06db8390e84cfa9649e14b577556d3dc452;p=~andy%2Fgtk diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 93367b641..0c6dc038c 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -44,7 +44,7 @@ #include "gtktreednd.h" #include "gtktypebuiltins.h" #include "gtkprivate.h" -#include "a11y/gtkiconviewaccessible.h" +#include "a11y/gtkiconviewaccessibleprivate.h" /** * SECTION:gtkiconview @@ -107,12 +107,11 @@ enum PROP_TOOLTIP_COLUMN, PROP_ITEM_PADDING, PROP_CELL_AREA, - - /* For scrollable interface */ PROP_HADJUSTMENT, PROP_VADJUSTMENT, PROP_HSCROLL_POLICY, - PROP_VSCROLL_POLICY + PROP_VSCROLL_POLICY, + PROP_ACTIVATE_ON_SINGLE_CLICK }; /* GObject vfuncs */ @@ -644,6 +643,22 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) GTK_TYPE_CELL_AREA, GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * GtkIconView:activate-on-single-click: + * + * The activate-on-single-click property specifies whether the "item-activated" signal + * will be emitted after a single click. + * + * Since: 3.8 + */ + g_object_class_install_property (gobject_class, + PROP_ACTIVATE_ON_SINGLE_CLICK, + g_param_spec_boolean ("activate-on-single-click", + P_("Activate on Single Click"), + P_("Activate row on a single click"), + FALSE, + GTK_PARAM_READWRITE)); + /* Scrollable interface properties */ g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment"); g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment"); @@ -673,10 +688,12 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) * @path: the #GtkTreePath for the activated item * * The ::item-activated signal is emitted when the method - * gtk_icon_view_item_activated() is called or the user double - * clicks an item. It is also emitted when a non-editable item - * is selected and one of the keys: Space, Return or Enter is - * pressed. + * gtk_icon_view_item_activated() is called, when the user double + * clicks an item with the "activate-on-single-click" property set + * to %FALSE, or when the user single clicks an item when the + * "activate-on-single-click" property set to %TRUE. It is also + * emitted when a non-editable item is selected and one of the keys: + * Space, Return or Enter is pressed. */ icon_view_signals[ITEM_ACTIVATED] = g_signal_new (I_("item-activated"), @@ -969,11 +986,15 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->column_spacing = 6; icon_view->priv->margin = 6; icon_view->priv->item_padding = 6; + icon_view->priv->activate_on_single_click = FALSE; icon_view->priv->draw_focus = TRUE; icon_view->priv->row_contexts = g_ptr_array_new_with_free_func ((GDestroyNotify)g_object_unref); + + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (icon_view)), + GTK_STYLE_CLASS_VIEW); } /* GObject methods */ @@ -1093,6 +1114,10 @@ gtk_icon_view_set_property (GObject *object, gtk_icon_view_set_item_padding (icon_view, g_value_get_int (value)); break; + case PROP_ACTIVATE_ON_SINGLE_CLICK: + gtk_icon_view_set_activate_on_single_click (icon_view, g_value_get_boolean (value)); + break; + case PROP_CELL_AREA: /* Construct-only, can only be assigned once */ area = g_value_get_object (value); @@ -1189,6 +1214,10 @@ gtk_icon_view_get_property (GObject *object, g_value_set_int (value, icon_view->priv->item_padding); break; + case PROP_ACTIVATE_ON_SINGLE_CLICK: + g_value_set_boolean (value, icon_view->priv->activate_on_single_click); + break; + case PROP_CELL_AREA: g_value_set_object (value, icon_view->priv->cell_area); break; @@ -1272,7 +1301,7 @@ gtk_icon_view_realize (GtkWidget *widget) window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gtk_widget_set_window (widget, window); - gdk_window_set_user_data (window, widget); + gtk_widget_register_window (widget, window); gtk_widget_get_allocation (widget, &allocation); @@ -1293,15 +1322,11 @@ gtk_icon_view_realize (GtkWidget *widget) icon_view->priv->bin_window = gdk_window_new (window, &attributes, attributes_mask); - gdk_window_set_user_data (icon_view->priv->bin_window, widget); + gtk_widget_register_window (widget, icon_view->priv->bin_window); context = gtk_widget_get_style_context (widget); - - gtk_style_context_save (context); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW); gtk_style_context_set_background (context, icon_view->priv->bin_window); gtk_style_context_set_background (context, window); - gtk_style_context_restore (context); gdk_window_show (icon_view->priv->bin_window); } @@ -1313,7 +1338,7 @@ gtk_icon_view_unrealize (GtkWidget *widget) icon_view = GTK_ICON_VIEW (widget); - gdk_window_set_user_data (icon_view->priv->bin_window, NULL); + gtk_widget_unregister_window (widget, icon_view->priv->bin_window); gdk_window_destroy (icon_view->priv->bin_window); icon_view->priv->bin_window = NULL; @@ -1330,14 +1355,8 @@ _gtk_icon_view_update_background (GtkIconView *icon_view) GtkStyleContext *context; context = gtk_widget_get_style_context (widget); - - gtk_style_context_save (context); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_VIEW); - gtk_style_context_set_background (context, gtk_widget_get_window (widget)); gtk_style_context_set_background (context, icon_view->priv->bin_window); - - gtk_style_context_restore (context); } } @@ -1393,6 +1412,31 @@ adjust_wrap_width (GtkIconView *icon_view) } } +/* General notes about layout + * + * The icon view is layouted like this: + * + * +----------+ s +----------+ + * | padding | p | padding | + * | +------+ | a | +------+ | + * | | cell | | c | | cell | | + * | +------+ | i | +------+ | + * | | n | | + * +----------+ g +----------+ + * + * In size request and allocation code, there are 3 sizes that are used: + * * cell size + * This is the size returned by gtk_cell_area_get_preferred_foo(). In places + * where code is interacting with the cell area and renderers this is useful. + * * padded size + * This is the cell size plus the item padding on each side. + * * spaced size + * This is the padded size plus the spacing. This is what's used for most + * calculations because it can (ab)use the following formula: + * iconview_size = 2 * margin + n_items * spaced_size - spacing + * So when reading this code and fixing my bugs where I confuse these two, be + * aware of this distinction. + */ static void cell_area_get_preferred_size (GtkIconView *icon_view, GtkCellAreaContext *context, @@ -1431,6 +1475,12 @@ cell_area_get_preferred_size (GtkIconView *icon_view, } } +static gboolean +gtk_icon_view_is_empty (GtkIconView *icon_view) +{ + return icon_view->priv->items == NULL; +} + static void gtk_icon_view_get_preferred_item_size (GtkIconView *icon_view, GtkOrientation orientation, @@ -1442,6 +1492,8 @@ gtk_icon_view_get_preferred_item_size (GtkIconView *icon_view, GtkCellAreaContext *context; GList *items; + g_assert (!gtk_icon_view_is_empty (icon_view)); + context = gtk_cell_area_create_context (priv->cell_area); for_size -= 2 * priv->item_padding; @@ -1498,9 +1550,9 @@ gtk_icon_view_get_preferred_item_size (GtkIconView *icon_view, } if (minimum) - *minimum += 2 * priv->item_padding; + *minimum = MAX (1, *minimum + 2 * priv->item_padding); if (natural) - *natural += 2 * priv->item_padding; + *natural = MAX (1, *natural + 2 * priv->item_padding); g_object_unref (context); } @@ -1515,19 +1567,24 @@ gtk_icon_view_compute_n_items_for_size (GtkIconView *icon_view, gint *max_item_size) { GtkIconViewPrivate *priv = icon_view->priv; - int minimum, natural; + int minimum, natural, spacing; g_return_if_fail (min_item_size == NULL || min_items != NULL); g_return_if_fail (max_item_size == NULL || max_items != NULL); + g_return_if_fail (!gtk_icon_view_is_empty (icon_view)); gtk_icon_view_get_preferred_item_size (icon_view, orientation, -1, &minimum, &natural); - size -= 2 * priv->margin; if (orientation == GTK_ORIENTATION_HORIZONTAL) - size += priv->column_spacing; + spacing = priv->column_spacing; else - size += priv->row_spacing; + spacing = priv->row_spacing; + size -= 2 * priv->margin; + size += spacing; + minimum += spacing; + natural += spacing; + if (priv->columns > 0) { if (orientation == GTK_ORIENTATION_HORIZONTAL) @@ -1549,17 +1606,6 @@ gtk_icon_view_compute_n_items_for_size (GtkIconView *icon_view, } else { - if (orientation == GTK_ORIENTATION_HORIZONTAL) - { - minimum += priv->column_spacing; - natural += priv->column_spacing; - } - else - { - minimum += priv->row_spacing; - natural += priv->row_spacing; - } - if (max_items) { if (size <= minimum) @@ -1580,22 +1626,16 @@ gtk_icon_view_compute_n_items_for_size (GtkIconView *icon_view, if (min_item_size) { *min_item_size = size / *min_items; - if (orientation == GTK_ORIENTATION_HORIZONTAL) - *min_item_size -= priv->column_spacing; - else - *min_item_size -= priv->row_spacing; - *min_item_size = MIN (*min_item_size, natural); + *min_item_size = CLAMP (*min_item_size, minimum, natural); + *min_item_size -= spacing; *min_item_size -= 2 * priv->item_padding; } if (max_item_size) { *max_item_size = size / *max_items; - if (orientation == GTK_ORIENTATION_HORIZONTAL) - *max_item_size -= priv->column_spacing; - else - *max_item_size -= priv->row_spacing; - *max_item_size = MIN (*max_item_size, natural); + *max_item_size = CLAMP (*max_item_size, minimum, natural); + *max_item_size -= spacing; *max_item_size -= 2 * priv->item_padding; } } @@ -1615,6 +1655,12 @@ gtk_icon_view_get_preferred_width (GtkWidget *widget, GtkIconViewPrivate *priv = icon_view->priv; int item_min, item_nat; + if (gtk_icon_view_is_empty (icon_view)) + { + *minimum = *natural = 2 * priv->margin; + return; + } + gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_HORIZONTAL, -1, &item_min, &item_nat); if (priv->columns > 0) @@ -1626,16 +1672,8 @@ gtk_icon_view_get_preferred_width (GtkWidget *widget, { int n_items = gtk_icon_view_get_n_items (icon_view); - if (n_items == 0) - { - *minimum = 0; - *natural = 0; - } - else - { - *minimum = item_min; - *natural = item_nat * n_items + priv->column_spacing * (n_items - 1); - } + *minimum = item_min; + *natural = item_nat * n_items + priv->column_spacing * (n_items - 1); } *minimum += 2 * priv->margin; @@ -1652,12 +1690,18 @@ gtk_icon_view_get_preferred_width_for_height (GtkWidget *widget, GtkIconViewPrivate *priv = icon_view->priv; int item_min, item_nat, rows, row_height, n_items; + if (gtk_icon_view_is_empty (icon_view)) + { + *minimum = *natural = 2 * priv->margin; + return; + } + gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_VERTICAL, height, &rows, &row_height, NULL, NULL); n_items = gtk_icon_view_get_n_items (icon_view); gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_HORIZONTAL, row_height, &item_min, &item_nat); - *minimum = item_min * ((n_items + rows - 1) / rows); - *natural = item_nat * ((n_items + rows - 1) / rows); + *minimum = (item_min + priv->column_spacing) * ((n_items + rows - 1) / rows) - priv->column_spacing; + *natural = (item_nat + priv->column_spacing) * ((n_items + rows - 1) / rows) - priv->column_spacing; *minimum += 2 * priv->margin; *natural += 2 * priv->margin; @@ -1672,6 +1716,12 @@ gtk_icon_view_get_preferred_height (GtkWidget *widget, GtkIconViewPrivate *priv = icon_view->priv; int item_min, item_nat, n_items; + if (gtk_icon_view_is_empty (icon_view)) + { + *minimum = *natural = 2 * priv->margin; + return; + } + gtk_icon_view_get_preferred_item_size (icon_view, GTK_ORIENTATION_VERTICAL, -1, &item_min, &item_nat); n_items = gtk_icon_view_get_n_items (icon_view); @@ -1684,16 +1734,8 @@ gtk_icon_view_get_preferred_height (GtkWidget *widget, } else { - if (n_items == 0) - { - *minimum = 0; - *natural = 0; - } - else - { - *minimum = item_min; - *natural = item_nat * n_items + priv->row_spacing * (n_items - 1); - } + *minimum = item_min; + *natural = item_nat * n_items + priv->row_spacing * (n_items - 1); } *minimum += 2 * priv->margin; @@ -1710,6 +1752,12 @@ gtk_icon_view_get_preferred_height_for_width (GtkWidget *widget, GtkIconViewPrivate *priv = icon_view->priv; int item_min, item_nat, columns, column_width, n_items; + if (gtk_icon_view_is_empty (icon_view)) + { + *minimum = *natural = 2 * priv->margin; + return; + } + gtk_icon_view_compute_n_items_for_size (icon_view, GTK_ORIENTATION_HORIZONTAL, width, NULL, NULL, &columns, &column_width); n_items = gtk_icon_view_get_n_items (icon_view); @@ -1794,9 +1842,16 @@ gtk_icon_view_draw (GtkWidget *widget, gint dest_index; GtkIconViewDropPosition dest_pos; GtkIconViewItem *dest_item = NULL; + GtkStyleContext *context; icon_view = GTK_ICON_VIEW (widget); + context = gtk_widget_get_style_context (widget); + gtk_render_background (context, cr, + 0, 0, + gtk_widget_get_allocated_width (widget), + gtk_widget_get_allocated_height (widget)); + if (!gtk_cairo_should_draw_window (cr, icon_view->priv->bin_window)) return FALSE; @@ -2230,7 +2285,7 @@ gtk_icon_view_button_press (GtkWidget *widget, &cell); /* - * We consider only the the cells' area as the item area if the + * We consider only the cells' area as the item area if the * item is not selected, but if it *is* selected, the complete * selection rectangle is considered to be part of the item. */ @@ -2326,7 +2381,9 @@ gtk_icon_view_button_press (GtkWidget *widget, icon_view->priv->draw_focus = FALSE; } - if (event->button == GDK_BUTTON_PRIMARY && event->type == GDK_2BUTTON_PRESS) + if (!icon_view->priv->activate_on_single_click + && event->button == GDK_BUTTON_PRIMARY + && event->type == GDK_2BUTTON_PRESS) { item = _gtk_icon_view_get_item_at_coords (icon_view, event->x, event->y, @@ -2352,6 +2409,12 @@ gtk_icon_view_button_press (GtkWidget *widget, return event->button == GDK_BUTTON_PRIMARY; } +static gboolean +button_event_modifies_selection (GdkEventButton *event) +{ + return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0; +} + static gboolean gtk_icon_view_button_release (GtkWidget *widget, GdkEventButton *event) @@ -2367,6 +2430,28 @@ gtk_icon_view_button_release (GtkWidget *widget, remove_scroll_timeout (icon_view); + if (event->button == GDK_BUTTON_PRIMARY + && icon_view->priv->activate_on_single_click + && !button_event_modifies_selection (event) + && icon_view->priv->last_single_clicked != NULL) + { + GtkIconViewItem *item; + + item = _gtk_icon_view_get_item_at_coords (icon_view, + event->x, event->y, + FALSE, + NULL); + if (item == icon_view->priv->last_single_clicked) + { + GtkTreePath *path; + path = gtk_tree_path_new_from_indices (item->index, -1); + gtk_icon_view_item_activated (icon_view, path); + gtk_tree_path_free (path); + } + + icon_view->priv->last_single_clicked = NULL; + } + return TRUE; } @@ -2830,7 +2915,7 @@ gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment, if (icon_view->priv->doing_rubberband) gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view)); - + _gtk_icon_view_accessible_adjustment_changed (icon_view); } } @@ -2854,7 +2939,12 @@ gtk_icon_view_layout (GtkIconView *icon_view) gint n_columns, n_rows, n_items; gint col, row; GtkRequestedSize *sizes; + gboolean rtl; + + if (gtk_icon_view_is_empty (icon_view)) + return; + rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL; n_items = gtk_icon_view_get_n_items (icon_view); gtk_icon_view_compute_n_items_for_size (icon_view, @@ -2864,16 +2954,9 @@ gtk_icon_view_layout (GtkIconView *icon_view) &n_columns, &item_width); n_rows = (n_items + n_columns - 1) / n_columns; - if (n_columns <= 1) - { - /* We might need vertical scrolling here */ - int min_width = item_width + 2 * priv->item_padding + 2 * priv->margin; - priv->width = MAX (min_width, gtk_widget_get_allocated_width (widget)); - } - else - { - priv->width = gtk_widget_get_allocated_width (widget); - } + priv->width = n_columns * (item_width + 2 * priv->item_padding + priv->column_spacing) - priv->column_spacing; + priv->width += 2 * priv->margin; + priv->width = MAX (priv->width, gtk_widget_get_allocated_width (widget)); /* Clear the per row contexts */ g_ptr_array_set_size (icon_view->priv->row_contexts, 0); @@ -2952,8 +3035,13 @@ gtk_icon_view_layout (GtkIconView *icon_view) item->cell_area.height = sizes[row].minimum_size; item->row = row; item->col = col; + if (rtl) + { + item->cell_area.x = priv->width - item_width - item->cell_area.x; + item->col = n_columns - 1 - col; + } } - + priv->height += sizes[row].minimum_size + priv->item_padding + priv->row_spacing; } @@ -2996,7 +3084,7 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, GtkIconViewPrivate *priv = icon_view->priv; GtkCellAreaContext *context; - if (priv->model == NULL) + if (priv->model == NULL || item->cell_area.width <= 0 || item->cell_area.height <= 0) return; _gtk_icon_view_set_cell_data (icon_view, item); @@ -3005,19 +3093,16 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, state = gtk_widget_get_state_flags (widget); gtk_style_context_save (style_context); - gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_VIEW); gtk_style_context_add_class (style_context, GTK_STYLE_CLASS_CELL); state &= ~(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_PRELIGHT); + if ((state & GTK_STATE_FLAG_FOCUSED) && + item == icon_view->priv->cursor_item) + flags |= GTK_CELL_RENDERER_FOCUSED; + if (item->selected) { - if ((state & GTK_STATE_FLAG_FOCUSED) && - item == icon_view->priv->cursor_item) - { - flags |= GTK_CELL_RENDERER_FOCUSED; - } - state |= GTK_STATE_FLAG_SELECTED; flags |= GTK_CELL_RENDERER_SELECTED; } @@ -4418,6 +4503,69 @@ gtk_icon_view_get_item_at_pos (GtkIconView *icon_view, return (item != NULL); } +/** + * gtk_icon_view_get_cell_rect: + * @icon_view: a #GtkIconView + * @path: a #GtkTreePath + * @cell: (allow-none): a #GtkCellRenderer or %NULL + * @rect: (out): rectangle to fill with cell rect + * + * Fills the bounding rectangle in widget coordinates for the cell specified by + * @path and @cell. If @cell is %NULL the main cell area is used. + * + * This function is only valid if @icon_view is realized. + * + * Return value: %FALSE if there is no such item, %TRUE otherwise + * + * Since: 3.6 + */ +gboolean +gtk_icon_view_get_cell_rect (GtkIconView *icon_view, + GtkTreePath *path, + GtkCellRenderer *cell, + GdkRectangle *rect) +{ + GtkIconViewItem *item = NULL; + gint x, y; + + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE); + g_return_val_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell), FALSE); + + if (gtk_tree_path_get_depth (path) > 0) + item = g_list_nth_data (icon_view->priv->items, + gtk_tree_path_get_indices(path)[0]); + + if (!item) + return FALSE; + + if (cell) + { + GtkCellAreaContext *context; + + context = g_ptr_array_index (icon_view->priv->row_contexts, item->row); + _gtk_icon_view_set_cell_data (icon_view, item); + gtk_cell_area_get_cell_allocation (icon_view->priv->cell_area, context, + GTK_WIDGET (icon_view), + cell, &item->cell_area, rect); + } + else + { + rect->x = item->cell_area.x - icon_view->priv->item_padding; + rect->y = item->cell_area.y - icon_view->priv->item_padding; + rect->width = item->cell_area.width + icon_view->priv->item_padding * 2; + rect->height = item->cell_area.height + icon_view->priv->item_padding * 2; + } + + if (icon_view->priv->bin_window) + { + gdk_window_get_position (icon_view->priv->bin_window, &x, &y); + rect->x += x; + rect->y += y; + } + + return TRUE; +} + /** * gtk_icon_view_set_tooltip_item: * @icon_view: a #GtkIconView @@ -4462,46 +4610,15 @@ gtk_icon_view_set_tooltip_cell (GtkIconView *icon_view, GtkCellRenderer *cell) { GdkRectangle rect; - GtkIconViewItem *item = NULL; - gint x, y; - + g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); g_return_if_fail (GTK_IS_TOOLTIP (tooltip)); g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell)); - if (gtk_tree_path_get_depth (path) > 0) - item = g_list_nth_data (icon_view->priv->items, - gtk_tree_path_get_indices(path)[0]); - - if (!item) + if (!gtk_icon_view_get_cell_rect (icon_view, path, cell, &rect)) return; - if (cell) - { - GtkCellAreaContext *context; - - context = g_ptr_array_index (icon_view->priv->row_contexts, item->row); - _gtk_icon_view_set_cell_data (icon_view, item); - gtk_cell_area_get_cell_allocation (icon_view->priv->cell_area, context, - GTK_WIDGET (icon_view), - cell, &item->cell_area, &rect); - } - else - { - rect.x = item->cell_area.x - icon_view->priv->item_padding; - rect.y = item->cell_area.y - icon_view->priv->item_padding; - rect.width = item->cell_area.width + icon_view->priv->item_padding * 2; - rect.height = item->cell_area.height + icon_view->priv->item_padding * 2; - } - - if (icon_view->priv->bin_window) - { - gdk_window_get_position (icon_view->priv->bin_window, &x, &y); - rect.x += x; - rect.y += y; - } - - gtk_tooltip_set_tip_area (tooltip, &rect); + gtk_tooltip_set_tip_area (tooltip, &rect); } @@ -4511,7 +4628,8 @@ gtk_icon_view_set_tooltip_cell (GtkIconView *icon_view, * @x: (inout): the x coordinate (relative to widget coordinates) * @y: (inout): the y coordinate (relative to widget coordinates) * @keyboard_tip: whether this is a keyboard tooltip or not - * @model: (out) (allow-none): a pointer to receive a #GtkTreeModel or %NULL + * @model: (out) (allow-none) (transfer none): a pointer to receive a + * #GtkTreeModel or %NULL * @path: (out) (allow-none): a pointer to receive a #GtkTreePath or %NULL * @iter: (out) (allow-none): a pointer to receive a #GtkTreeIter or %NULL * @@ -4836,6 +4954,8 @@ void gtk_icon_view_set_model (GtkIconView *icon_view, GtkTreeModel *model) { + gboolean dirty; + g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model)); @@ -4852,6 +4972,8 @@ gtk_icon_view_set_model (GtkIconView *icon_view, if (icon_view->priv->cell_area) gtk_cell_area_stop_editing (icon_view->priv->cell_area, TRUE); + dirty = gtk_icon_view_unselect_all_internal (icon_view); + if (model) { GType column_type; @@ -4936,6 +5058,9 @@ gtk_icon_view_set_model (GtkIconView *icon_view, g_object_notify (G_OBJECT (icon_view), "model"); + if (dirty) + g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0); + gtk_widget_queue_resize (GTK_WIDGET (icon_view)); } @@ -5307,7 +5432,7 @@ gtk_icon_view_unselect_path (GtkIconView *icon_view, * * To free the return value, use: * |[ - * g_list_free_full (list, (GDestroyNotify) gtk_tree_patch_free); + * g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); * ]| * * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row. @@ -6684,7 +6809,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, /* Drag-and-Drop support */ /** * gtk_icon_view_enable_model_drag_source: - * @icon_view: a #GtkIconTreeView + * @icon_view: a #GtkIconView * @start_button_mask: Mask of allowed buttons to start drag * @targets: (array length=n_targets): the table of targets that the drag will * support @@ -7108,6 +7233,49 @@ gtk_icon_view_set_reorderable (GtkIconView *icon_view, g_object_notify (G_OBJECT (icon_view), "reorderable"); } +/** + * gtk_icon_view_set_activate_on_single_click: + * @icon_view: a #GtkIconView + * @single: %TRUE to emit item-activated on a single click + * + * Causes the #GtkIconView::item-activated signal to be emitted on + * a single click instead of a double click. + * + * Since: 3.8 + **/ +void +gtk_icon_view_set_activate_on_single_click (GtkIconView *icon_view, + gboolean single) +{ + g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); + + single = single != FALSE; + + if (icon_view->priv->activate_on_single_click == single) + return; + + icon_view->priv->activate_on_single_click = single; + g_object_notify (G_OBJECT (icon_view), "activate-on-single-click"); +} + +/** + * gtk_icon_view_get_activate_on_single_click: + * @icon_view: a #GtkIconView + * + * Gets the setting set by gtk_icon_view_set_activate_on_single_click(). + * + * Return value: %TRUE if item-activated will be emitted on a single click + * + * Since: 3.8 + **/ +gboolean +gtk_icon_view_get_activate_on_single_click (GtkIconView *icon_view) +{ + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE); + + return icon_view->priv->activate_on_single_click; +} + static gboolean gtk_icon_view_buildable_custom_tag_start (GtkBuildable *buildable, GtkBuilder *builder,