X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;ds=sidebyside;f=gtk%2Fgtkiconview.c;h=f8f830ae02ebb0c44dc7d1c92e7f4c90068045e9;hb=9e661ed0e91a5709afcc46cdeaea4d711a885da7;hp=32c28ab7282e9e1ebabb5793d6267e38a0d9f4fd;hpb=bbc726431d0b0911dd048b8dc7d34477f75c6096;p=~andy%2Fgtk diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 32c28ab72..f8f830ae0 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -39,16 +39,24 @@ #include "gtkentry.h" #include "gtkcombobox.h" #include "gtktextbuffer.h" +#include "gtksizerequest.h" #include "gtktreednd.h" #include "gtkprivate.h" -#include "gtkalias.h" -#undef DEBUG_ICON_VIEW +/** + * SECTION:gtkiconview + * @title: GtkIconView + * @short_description: A widget which displays a list of icons in a grid + * + * #GtkIconView provides an alternative view on a list model. + * It displays the model as a grid of icons with labels. Like + * #GtkTreeView, it allows to select one or multiple items + * (depending on the selection mode, see gtk_icon_view_set_selection_mode()). + * In addition to selection with the arrow keys, #GtkIconView supports + * rubberband selection, which is controlled by dragging the pointer. + */ #define SCROLL_EDGE_SIZE 15 -#define ITEM_PADDING 6 - -#define GTK_ICON_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ICON_VIEW, GtkIconViewPrivate)) typedef struct _GtkIconViewItem GtkIconViewItem; struct _GtkIconViewItem @@ -125,6 +133,7 @@ struct _GtkIconViewPrivate gboolean doing_rubberband; gint rubberband_x1, rubberband_y1; gint rubberband_x2, rubberband_y2; + GdkDevice *rubberband_device; guint scroll_timeout_id; gint scroll_value_diff; @@ -142,7 +151,7 @@ struct _GtkIconViewPrivate gint cursor_cell; - GtkOrientation orientation; + GtkOrientation item_orientation; gint columns; gint item_width; @@ -150,6 +159,7 @@ struct _GtkIconViewPrivate gint row_spacing; gint column_spacing; gint margin; + gint item_padding; gint text_column; gint markup_column; @@ -166,10 +176,7 @@ struct _GtkIconViewPrivate gint press_start_x; gint press_start_y; - GtkTargetList *source_targets; GdkDragAction source_actions; - - GtkTargetList *dest_targets; GdkDragAction dest_actions; GtkTreeRowReference *dest_item; @@ -187,7 +194,9 @@ struct _GtkIconViewPrivate guint empty_view_drop :1; guint ctrl_pressed : 1; - guint shift_pressed : 1; + guint shift_pressed : 1; + + guint draw_focus : 1; }; /* Signals */ @@ -210,9 +219,9 @@ enum PROP_0, PROP_PIXBUF_COLUMN, PROP_TEXT_COLUMN, - PROP_MARKUP_COLUMN, + PROP_MARKUP_COLUMN, PROP_SELECTION_MODE, - PROP_ORIENTATION, + PROP_ITEM_ORIENTATION, PROP_MODEL, PROP_COLUMNS, PROP_ITEM_WIDTH, @@ -221,7 +230,8 @@ enum PROP_COLUMN_SPACING, PROP_MARGIN, PROP_REORDERABLE, - PROP_TOOLTIP_COLUMN + PROP_TOOLTIP_COLUMN, + PROP_ITEM_PADDING }; /* GObject vfuncs */ @@ -235,11 +245,8 @@ static void gtk_icon_view_get_property (GObject guint prop_id, GValue *value, GParamSpec *pspec); - -/* GtkObject vfuncs */ -static void gtk_icon_view_destroy (GtkObject *object); - /* GtkWidget vfuncs */ +static void gtk_icon_view_destroy (GtkWidget *widget); static void gtk_icon_view_realize (GtkWidget *widget); static void gtk_icon_view_unrealize (GtkWidget *widget); static void gtk_icon_view_style_set (GtkWidget *widget, @@ -250,8 +257,8 @@ static void gtk_icon_view_size_request (GtkWidget GtkRequisition *requisition); static void gtk_icon_view_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gboolean gtk_icon_view_expose (GtkWidget *widget, - GdkEventExpose *expose); +static gboolean gtk_icon_view_draw (GtkWidget *widget, + cairo_t *cr); static gboolean gtk_icon_view_motion (GtkWidget *widget, GdkEventMotion *event); static gboolean gtk_icon_view_button_press (GtkWidget *widget, @@ -288,17 +295,13 @@ static void gtk_icon_view_adjustment_changed (GtkAdj GtkIconView *icon_view); static void gtk_icon_view_layout (GtkIconView *icon_view); static void gtk_icon_view_paint_item (GtkIconView *icon_view, - cairo_t *cr, - + cairo_t *cr, GtkIconViewItem *item, - GdkRectangle *area, - GdkDrawable *drawable, - gint x, - gint y, - gboolean draw_focus); + gint x, + gint y, + gboolean draw_focus); static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view, - cairo_t *cr, - GdkRectangle *area); + cairo_t *cr); static void gtk_icon_view_queue_draw_path (GtkIconView *icon_view, GtkTreePath *path); static void gtk_icon_view_queue_draw_item (GtkIconView *icon_view, @@ -308,6 +311,7 @@ static void gtk_icon_view_set_cursor_item (GtkIco GtkIconViewItem *item, gint cursor_cell); static void gtk_icon_view_start_rubberbanding (GtkIconView *icon_view, + GdkDevice *device, gint x, gint y); static void gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view); @@ -449,8 +453,6 @@ static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_ GdkEventMotion *event); static void remove_scroll_timeout (GtkIconView *icon_view); -static void clear_dest_info (GtkIconView *icon_view); -static void clear_source_info (GtkIconView *icon_view); static void adjust_wrap_width (GtkIconView *icon_view, GtkIconViewItem *item); @@ -482,7 +484,6 @@ static void gtk_icon_view_class_init (GtkIconViewClass *klass) { GObjectClass *gobject_class; - GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; GtkBindingSet *binding_set; @@ -492,7 +493,6 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_type_class_add_private (klass, sizeof (GtkIconViewPrivate)); gobject_class = (GObjectClass *) klass; - object_class = (GtkObjectClass *) klass; widget_class = (GtkWidgetClass *) klass; container_class = (GtkContainerClass *) klass; @@ -500,15 +500,14 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) gobject_class->set_property = gtk_icon_view_set_property; gobject_class->get_property = gtk_icon_view_get_property; - object_class->destroy = gtk_icon_view_destroy; - + widget_class->destroy = gtk_icon_view_destroy; widget_class->realize = gtk_icon_view_realize; widget_class->unrealize = gtk_icon_view_unrealize; widget_class->style_set = gtk_icon_view_style_set; widget_class->get_accessible = gtk_icon_view_get_accessible; widget_class->size_request = gtk_icon_view_size_request; widget_class->size_allocate = gtk_icon_view_size_allocate; - widget_class->expose_event = gtk_icon_view_expose; + widget_class->draw = gtk_icon_view_draw; widget_class->motion_notify_event = gtk_icon_view_motion; widget_class->button_press_event = gtk_icon_view_button_press; widget_class->button_release_event = gtk_icon_view_button_release; @@ -717,19 +716,18 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) 0, G_MAXINT, 6, GTK_PARAM_READWRITE)); - /** - * GtkIconView:orientation: + * GtkIconView:item-orientation: * - * The orientation property specifies how the cells (i.e. the icon and + * The item-orientation property specifies how the cells (i.e. the icon and * the text) of the item are positioned relative to each other. * * Since: 2.6 */ g_object_class_install_property (gobject_class, - PROP_ORIENTATION, - g_param_spec_enum ("orientation", - P_("Orientation"), + PROP_ITEM_ORIENTATION, + g_param_spec_enum ("item-orientation", + P_("Item Orientation"), P_("How the text and icon of each item are positioned relative to each other"), GTK_TYPE_ORIENTATION, GTK_ORIENTATION_VERTICAL, @@ -761,6 +759,22 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) -1, GTK_PARAM_READWRITE)); + /** + * GtkIconView:item-padding: + * + * The item-padding property specifies the padding around each + * of the icon view's item. + * + * Since: 2.18 + */ + g_object_class_install_property (gobject_class, + PROP_ITEM_PADDING, + g_param_spec_int ("item-padding", + P_("Item Padding"), + P_("Padding around icon view items"), + 0, G_MAXINT, 6, + GTK_PARAM_READWRITE)); + /* Style properties */ @@ -780,6 +794,15 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) GTK_PARAM_READABLE)); /* Signals */ + /** + * GtkIconView::set-scroll-adjustments + * @horizontal: the horizontal #GtkAdjustment + * @vertical: the vertical #GtkAdjustment + * + * Set the scroll adjustments for the icon view. Usually scrolled containers + * like #GtkScrolledWindow will emit this signal to connect two instances + * of #GtkScrollbar to the scroll directions of the #GtkIconView. + */ widget_class->set_scroll_adjustments_signal = g_signal_new (I_("set-scroll-adjustments"), G_TYPE_FROM_CLASS (gobject_class), @@ -790,6 +813,17 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) G_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); + /** + * GtkIconView::item-activated: + * @iconview: the object on which the signal is emitted + * @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. + */ icon_view_signals[ITEM_ACTIVATED] = g_signal_new (I_("item-activated"), G_TYPE_FROM_CLASS (gobject_class), @@ -800,6 +834,13 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) G_TYPE_NONE, 1, GTK_TYPE_TREE_PATH); + /** + * GtkIconView::selection-changed: + * @iconview: the object on which the signal is emitted + * + * The ::selection-changed signal is emitted when the selection + * (i.e. the set of selected items) changes. + */ icon_view_signals[SELECTION_CHANGED] = g_signal_new (I_("selection-changed"), G_TYPE_FROM_CLASS (gobject_class), @@ -809,6 +850,19 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GtkIconView::select-all: + * @iconview: the object on which the signal is emitted + * + * A keybinding signal + * which gets emitted when the user selects all items. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control selection + * programmatically. + * + * The default binding for this signal is Ctrl-a. + */ icon_view_signals[SELECT_ALL] = g_signal_new (I_("select-all"), G_TYPE_FROM_CLASS (gobject_class), @@ -818,6 +872,19 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GtkIconView::unselect-all: + * @iconview: the object on which the signal is emitted + * + * A keybinding signal + * which gets emitted when the user unselects all items. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control selection + * programmatically. + * + * The default binding for this signal is Ctrl-Shift-a. + */ icon_view_signals[UNSELECT_ALL] = g_signal_new (I_("unselect-all"), G_TYPE_FROM_CLASS (gobject_class), @@ -827,6 +894,20 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GtkIconView::select-cursor-item: + * @iconview: the object on which the signal is emitted + * + * A keybinding signal + * which gets emitted when the user selects the item that is currently + * focused. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control selection + * programmatically. + * + * There is no default binding for this signal. + */ icon_view_signals[SELECT_CURSOR_ITEM] = g_signal_new (I_("select-cursor-item"), G_TYPE_FROM_CLASS (gobject_class), @@ -836,6 +917,21 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GtkIconView::toggle-cursor-item: + * @iconview: the object on which the signal is emitted + * + * A keybinding signal + * which gets emitted when the user toggles whether the currently + * focused item is selected or not. The exact effect of this + * depend on the selection mode. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control selection + * programmatically. + * + * There is no default binding for this signal is Ctrl-Space. + */ icon_view_signals[TOGGLE_CURSOR_ITEM] = g_signal_new (I_("toggle-cursor-item"), G_TYPE_FROM_CLASS (gobject_class), @@ -845,6 +941,20 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + /** + * GtkIconView::activate-cursor-item: + * @iconview: the object on which the signal is emitted + * + * A keybinding signal + * which gets emitted when the user activates the currently + * focused item. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control activation + * programmatically. + * + * The default bindings for this signal are Space, Return and Enter. + */ icon_view_signals[ACTIVATE_CURSOR_ITEM] = g_signal_new (I_("activate-cursor-item"), G_TYPE_FROM_CLASS (gobject_class), @@ -854,6 +964,30 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) _gtk_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); + /** + * GtkIconView::move-cursor: + * @iconview: the object which received the signal + * @step: the granularity of the move, as a #GtkMovementStep + * @count: the number of @step units to move + * + * The ::move-cursor signal is a + * keybinding signal + * which gets emitted when the user initiates a cursor movement. + * + * Applications should not connect to it, but may emit it with + * g_signal_emit_by_name() if they need to control the cursor + * programmatically. + * + * The default bindings for this signal include + * + * Arrow keys which move by individual steps + * Home/End keys which move to the first/last item + * PageUp/PageDown which move by "pages" + * + * + * All of these will extend the selection when combined with + * the Shift modifier. + */ icon_view_signals[MOVE_CURSOR] = g_signal_new (I_("move-cursor"), G_TYPE_FROM_CLASS (gobject_class), @@ -866,70 +1000,70 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) G_TYPE_INT); /* Key bindings */ - gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", 0); - gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0); - gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_space, 0, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "activate-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "activate-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "activate-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "activate-cursor-item", 0); - gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, + gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "activate-cursor-item", 0); - gtk_icon_view_add_move_binding (binding_set, GDK_Up, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Up, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_MOVEMENT_DISPLAY_LINES, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_Down, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Down, 0, GTK_MOVEMENT_DISPLAY_LINES, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Down, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_MOVEMENT_DISPLAY_LINES, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK, GTK_MOVEMENT_DISPLAY_LINES, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK, GTK_MOVEMENT_DISPLAY_LINES, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_Home, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Home, 0, GTK_MOVEMENT_BUFFER_ENDS, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Home, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0, GTK_MOVEMENT_BUFFER_ENDS, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_End, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_End, 0, GTK_MOVEMENT_BUFFER_ENDS, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_End, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0, GTK_MOVEMENT_BUFFER_ENDS, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_Page_Up, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_MOVEMENT_PAGES, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, GTK_MOVEMENT_PAGES, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_Page_Down, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_MOVEMENT_PAGES, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, GTK_MOVEMENT_PAGES, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_Right, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Right, 0, GTK_MOVEMENT_VISUAL_POSITIONS, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_Left, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Left, 0, GTK_MOVEMENT_VISUAL_POSITIONS, -1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Right, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Right, 0, GTK_MOVEMENT_VISUAL_POSITIONS, 1); - gtk_icon_view_add_move_binding (binding_set, GDK_KP_Left, 0, + gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Left, 0, GTK_MOVEMENT_VISUAL_POSITIONS, -1); } @@ -958,8 +1092,10 @@ gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface) static void gtk_icon_view_init (GtkIconView *icon_view) { - icon_view->priv = GTK_ICON_VIEW_GET_PRIVATE (icon_view); - + icon_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (icon_view, + GTK_TYPE_ICON_VIEW, + GtkIconViewPrivate); + icon_view->priv->width = 0; icon_view->priv->height = 0; icon_view->priv->selection_mode = GTK_SELECTION_SINGLE; @@ -973,7 +1109,7 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->pixbuf_cell = -1; icon_view->priv->tooltip_column = -1; - GTK_WIDGET_SET_FLAGS (icon_view, GTK_CAN_FOCUS); + gtk_widget_set_can_focus (GTK_WIDGET (icon_view), TRUE); gtk_icon_view_set_adjustments (icon_view, NULL, NULL); @@ -981,7 +1117,7 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->n_cells = 0; icon_view->priv->cursor_cell = -1; - icon_view->priv->orientation = GTK_ORIENTATION_VERTICAL; + icon_view->priv->item_orientation = GTK_ORIENTATION_VERTICAL; icon_view->priv->columns = -1; icon_view->priv->item_width = -1; @@ -989,49 +1125,9 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->row_spacing = 6; icon_view->priv->column_spacing = 6; icon_view->priv->margin = 6; -} - -static void -gtk_icon_view_destroy (GtkObject *object) -{ - GtkIconView *icon_view; - - icon_view = GTK_ICON_VIEW (object); - - gtk_icon_view_stop_editing (icon_view, TRUE); - - gtk_icon_view_set_model (icon_view, NULL); - - if (icon_view->priv->layout_idle_id != 0) - { - g_source_remove (icon_view->priv->layout_idle_id); - icon_view->priv->layout_idle_id = 0; - } - - if (icon_view->priv->scroll_to_path != NULL) - { - gtk_tree_row_reference_free (icon_view->priv->scroll_to_path); - icon_view->priv->scroll_to_path = NULL; - } - - remove_scroll_timeout (icon_view); - - if (icon_view->priv->hadjustment != NULL) - { - g_object_unref (icon_view->priv->hadjustment); - icon_view->priv->hadjustment = NULL; - } - - if (icon_view->priv->vadjustment != NULL) - { - g_object_unref (icon_view->priv->vadjustment); - icon_view->priv->vadjustment = NULL; - } - - clear_dest_info (icon_view); - clear_source_info (icon_view); + icon_view->priv->item_padding = 6; - GTK_OBJECT_CLASS (gtk_icon_view_parent_class)->destroy (object); + icon_view->priv->draw_focus = TRUE; } /* GObject methods */ @@ -1071,8 +1167,8 @@ gtk_icon_view_set_property (GObject *object, case PROP_MODEL: gtk_icon_view_set_model (icon_view, g_value_get_object (value)); break; - case PROP_ORIENTATION: - gtk_icon_view_set_orientation (icon_view, g_value_get_enum (value)); + case PROP_ITEM_ORIENTATION: + gtk_icon_view_set_item_orientation (icon_view, g_value_get_enum (value)); break; case PROP_COLUMNS: gtk_icon_view_set_columns (icon_view, g_value_get_int (value)); @@ -1100,6 +1196,10 @@ gtk_icon_view_set_property (GObject *object, gtk_icon_view_set_tooltip_column (icon_view, g_value_get_int (value)); break; + case PROP_ITEM_PADDING: + gtk_icon_view_set_item_padding (icon_view, g_value_get_int (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1133,8 +1233,8 @@ gtk_icon_view_get_property (GObject *object, case PROP_MODEL: g_value_set_object (value, icon_view->priv->model); break; - case PROP_ORIENTATION: - g_value_set_enum (value, icon_view->priv->orientation); + case PROP_ITEM_ORIENTATION: + g_value_set_enum (value, icon_view->priv->item_orientation); break; case PROP_COLUMNS: g_value_set_int (value, icon_view->priv->columns); @@ -1161,47 +1261,92 @@ gtk_icon_view_get_property (GObject *object, g_value_set_int (value, icon_view->priv->tooltip_column); break; + case PROP_ITEM_PADDING: + g_value_set_int (value, icon_view->priv->item_padding); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -/* GtkWidget signals */ +/* GtkWidget methods */ +static void +gtk_icon_view_destroy (GtkWidget *widget) +{ + GtkIconView *icon_view = GTK_ICON_VIEW (widget); + + gtk_icon_view_stop_editing (icon_view, TRUE); + + gtk_icon_view_set_model (icon_view, NULL); + + if (icon_view->priv->layout_idle_id != 0) + { + g_source_remove (icon_view->priv->layout_idle_id); + icon_view->priv->layout_idle_id = 0; + } + + if (icon_view->priv->scroll_to_path != NULL) + { + gtk_tree_row_reference_free (icon_view->priv->scroll_to_path); + icon_view->priv->scroll_to_path = NULL; + } + + remove_scroll_timeout (icon_view); + + if (icon_view->priv->hadjustment != NULL) + { + g_object_unref (icon_view->priv->hadjustment); + icon_view->priv->hadjustment = NULL; + } + + if (icon_view->priv->vadjustment != NULL) + { + g_object_unref (icon_view->priv->vadjustment); + icon_view->priv->vadjustment = NULL; + } + + GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->destroy (widget); +} + static void gtk_icon_view_realize (GtkWidget *widget) { - GtkIconView *icon_view; + GtkIconView *icon_view = GTK_ICON_VIEW (widget); + GtkAllocation allocation; + GdkWindow *window; GdkWindowAttr attributes; gint attributes_mask; - - icon_view = GTK_ICON_VIEW (widget); - GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + gtk_widget_set_realized (widget, TRUE); + + gtk_widget_get_allocation (widget, &allocation); /* Make the main, clipping window */ attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; + attributes.x = allocation.x; + attributes.y = allocation.y; + attributes.width = allocation.width; + attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; + + 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); - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_back_pixmap (widget->window, NULL, FALSE); - gdk_window_set_user_data (widget->window, widget); + gtk_widget_get_allocation (widget, &allocation); /* Make the window for the icon view */ attributes.x = 0; attributes.y = 0; - attributes.width = MAX (icon_view->priv->width, widget->allocation.width); - attributes.height = MAX (icon_view->priv->height, widget->allocation.height); + attributes.width = MAX (icon_view->priv->width, allocation.width); + attributes.height = MAX (icon_view->priv->height, allocation.height); attributes.event_mask = (GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | @@ -1211,12 +1356,13 @@ gtk_icon_view_realize (GtkWidget *widget) GDK_KEY_RELEASE_MASK) | gtk_widget_get_events (widget); - icon_view->priv->bin_window = gdk_window_new (widget->window, + icon_view->priv->bin_window = gdk_window_new (window, &attributes, attributes_mask); gdk_window_set_user_data (icon_view->priv->bin_window, widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]); + gtk_widget_style_attach (widget); + gdk_window_set_background (icon_view->priv->bin_window, + >k_widget_get_style (widget)->base[gtk_widget_get_state (widget)]); gdk_window_show (icon_view->priv->bin_window); } @@ -1240,11 +1386,16 @@ gtk_icon_view_state_changed (GtkWidget *widget, GtkStateType previous_state) { GtkIconView *icon_view = GTK_ICON_VIEW (widget); + GtkStateType state; + GtkStyle *style; - if (GTK_WIDGET_REALIZED (widget)) + if (gtk_widget_get_realized (widget)) { - gdk_window_set_background (widget->window, &widget->style->base[widget->state]); - gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]); + style = gtk_widget_get_style (widget); + state = gtk_widget_get_state (widget); + + gdk_window_set_background (gtk_widget_get_window (widget), &style->base[state]); + gdk_window_set_background (icon_view->priv->bin_window, &style->base[state]); } gtk_widget_queue_draw (widget); @@ -1255,11 +1406,16 @@ gtk_icon_view_style_set (GtkWidget *widget, GtkStyle *previous_style) { GtkIconView *icon_view = GTK_ICON_VIEW (widget); + GtkStateType state; + GtkStyle *style; - if (GTK_WIDGET_REALIZED (widget)) + if (gtk_widget_get_realized (widget)) { - gdk_window_set_background (widget->window, &widget->style->base[widget->state]); - gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]); + style = gtk_widget_get_style (widget); + state = gtk_widget_get_state (widget); + + gdk_window_set_background (gtk_widget_get_window (widget), &style->base[state]); + gdk_window_set_background (icon_view->priv->bin_window, &style->base[state]); } gtk_widget_queue_resize (widget); @@ -1284,9 +1440,10 @@ gtk_icon_view_size_request (GtkWidget *widget, tmp_list = tmp_list->next; - if (GTK_WIDGET_VISIBLE (child->widget)) - gtk_widget_size_request (child->widget, &child_requisition); - } + if (gtk_widget_get_visible (child->widget)) + gtk_widget_get_preferred_size (child->widget, + &child_requisition, NULL); + } } static void @@ -1302,10 +1459,10 @@ gtk_icon_view_allocate_children (GtkIconView *icon_view) /* totally ignore our child's requisition */ if (child->cell < 0) { - allocation.x = child->item->x + ITEM_PADDING; - allocation.y = child->item->y + ITEM_PADDING; - allocation.width = child->item->width - ITEM_PADDING * 2; - allocation.height = child->item->height - ITEM_PADDING * 2; + allocation.x = child->item->x + icon_view->priv->item_padding; + allocation.y = child->item->y + icon_view->priv->item_padding; + allocation.width = child->item->width - icon_view->priv->item_padding * 2; + allocation.height = child->item->height - icon_view->priv->item_padding * 2; } else { @@ -1329,11 +1486,11 @@ gtk_icon_view_size_allocate (GtkWidget *widget, GtkAdjustment *hadjustment, *vadjustment; - widget->allocation = *allocation; - - if (GTK_WIDGET_REALIZED (widget)) + gtk_widget_set_allocation (widget, allocation); + + if (gtk_widget_get_realized (widget)) { - gdk_window_move_resize (widget->window, + gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height); gdk_window_resize (icon_view->priv->bin_window, @@ -1366,7 +1523,7 @@ gtk_icon_view_size_allocate (GtkWidget *widget, if (vadjustment->value > vadjustment->upper - vadjustment->page_size) gtk_adjustment_set_value (vadjustment, vadjustment->upper - vadjustment->page_size); - if (GTK_WIDGET_REALIZED (widget) && + if (gtk_widget_get_realized (widget) && icon_view->priv->scroll_to_path) { GtkTreePath *path; @@ -1388,12 +1545,11 @@ gtk_icon_view_size_allocate (GtkWidget *widget, } static gboolean -gtk_icon_view_expose (GtkWidget *widget, - GdkEventExpose *expose) +gtk_icon_view_draw (GtkWidget *widget, + cairo_t *cr) { GtkIconView *icon_view; GList *icons; - cairo_t *cr; GtkTreePath *path; gint dest_index; GtkIconViewDropPosition dest_pos; @@ -1401,10 +1557,18 @@ gtk_icon_view_expose (GtkWidget *widget, icon_view = GTK_ICON_VIEW (widget); - if (expose->window != icon_view->priv->bin_window) + if (!gtk_cairo_should_draw_window (cr, icon_view->priv->bin_window)) return FALSE; - cr = gdk_cairo_create (icon_view->priv->bin_window); + cairo_save (cr); + + gtk_cairo_transform_to_window (cr, widget, icon_view->priv->bin_window); + + /* If a layout has been scheduled, do it now so that all + * cell view items have valid sizes before we proceed. */ + if (icon_view->priv->layout_idle_id != 0) + gtk_icon_view_layout (icon_view); + cairo_set_line_width (cr, 1.); gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos); @@ -1420,100 +1584,90 @@ gtk_icon_view_expose (GtkWidget *widget, for (icons = icon_view->priv->items; icons; icons = icons->next) { GtkIconViewItem *item = icons->data; - GdkRectangle area; - area.x = item->x; - area.y = item->y; - area.width = item->width; - area.height = item->height; - - if (gdk_region_rect_in (expose->region, &area) == GDK_OVERLAP_RECTANGLE_OUT) - continue; - - gtk_icon_view_paint_item (icon_view, cr, item, &expose->area, - icon_view->priv->bin_window, - item->x, item->y, TRUE); - - if (dest_index == item->index) - dest_item = item; + cairo_save (cr); + + cairo_rectangle (cr, item->x, item->y, item->width, item->height); + cairo_clip (cr); + + if (gdk_cairo_get_clip_rectangle (cr, NULL)) + { + gtk_icon_view_paint_item (icon_view, cr, item, + item->x, item->y, + icon_view->priv->draw_focus); + + if (dest_index == item->index) + dest_item = item; + } + + cairo_restore (cr); } if (dest_item) { + GtkStateType state; + GtkStyle *style; + + style = gtk_widget_get_style (widget); + state = gtk_widget_get_state (widget); + switch (dest_pos) { case GTK_ICON_VIEW_DROP_INTO: - gtk_paint_focus (widget->style, - icon_view->priv->bin_window, - GTK_WIDGET_STATE (widget), - NULL, - widget, - "iconview-drop-indicator", - dest_item->x, dest_item->y, - dest_item->width, dest_item->height); + gtk_paint_focus (style, + cr, + state, + widget, + "iconview-drop-indicator", + dest_item->x, dest_item->y, + dest_item->width, dest_item->height); break; case GTK_ICON_VIEW_DROP_ABOVE: - gtk_paint_focus (widget->style, - icon_view->priv->bin_window, - GTK_WIDGET_STATE (widget), - NULL, - widget, - "iconview-drop-indicator", - dest_item->x, dest_item->y - 1, - dest_item->width, 2); + gtk_paint_focus (style, + cr, + state, + widget, + "iconview-drop-indicator", + dest_item->x, dest_item->y - 1, + dest_item->width, 2); break; case GTK_ICON_VIEW_DROP_LEFT: - gtk_paint_focus (widget->style, - icon_view->priv->bin_window, - GTK_WIDGET_STATE (widget), - NULL, - widget, - "iconview-drop-indicator", - dest_item->x - 1, dest_item->y, - 2, dest_item->height); + gtk_paint_focus (style, + cr, + state, + widget, + "iconview-drop-indicator", + dest_item->x - 1, dest_item->y, + 2, dest_item->height); break; case GTK_ICON_VIEW_DROP_BELOW: - gtk_paint_focus (widget->style, - icon_view->priv->bin_window, - GTK_WIDGET_STATE (widget), - NULL, - widget, - "iconview-drop-indicator", - dest_item->x, dest_item->y + dest_item->height - 1, - dest_item->width, 2); + gtk_paint_focus (style, + cr, + state, + widget, + "iconview-drop-indicator", + dest_item->x, dest_item->y + dest_item->height - 1, + dest_item->width, 2); break; case GTK_ICON_VIEW_DROP_RIGHT: - gtk_paint_focus (widget->style, - icon_view->priv->bin_window, - GTK_WIDGET_STATE (widget), - NULL, - widget, - "iconview-drop-indicator", - dest_item->x + dest_item->width - 1, dest_item->y, - 2, dest_item->height); + gtk_paint_focus (style, + cr, + state, + widget, + "iconview-drop-indicator", + dest_item->x + dest_item->width - 1, dest_item->y, + 2, dest_item->height); case GTK_ICON_VIEW_NO_DROP: ; break; } } if (icon_view->priv->doing_rubberband) - { - GdkRectangle *rectangles; - gint n_rectangles; - - gdk_region_get_rectangles (expose->region, - &rectangles, - &n_rectangles); - - while (n_rectangles--) - gtk_icon_view_paint_rubberband (icon_view, cr, &rectangles[n_rectangles]); - - g_free (rectangles); - } + gtk_icon_view_paint_rubberband (icon_view, cr); - cairo_destroy (cr); + cairo_restore (cr); - GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->expose_event (widget, expose); + GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->draw (widget, cr); return TRUE; } @@ -1536,6 +1690,7 @@ static gboolean gtk_icon_view_motion (GtkWidget *widget, GdkEventMotion *event) { + GtkAllocation allocation; GtkIconView *icon_view; gint abs_y; @@ -1552,12 +1707,14 @@ gtk_icon_view_motion (GtkWidget *widget, (icon_view->priv->vadjustment->upper - icon_view->priv->vadjustment->lower)); - if (abs_y < 0 || abs_y > widget->allocation.height) + gtk_widget_get_allocation (widget, &allocation); + + if (abs_y < 0 || abs_y > allocation.height) { if (abs_y < 0) icon_view->priv->scroll_value_diff = abs_y; else - icon_view->priv->scroll_value_diff = abs_y - widget->allocation.height; + icon_view->priv->scroll_value_diff = abs_y - allocation.height; icon_view->priv->event_last_x = event->x; icon_view->priv->event_last_y = event->y; @@ -1696,7 +1853,7 @@ gtk_icon_view_put (GtkIconView *icon_view, icon_view->priv->children = g_list_append (icon_view->priv->children, child); - if (GTK_WIDGET_REALIZED (icon_view)) + if (gtk_widget_get_realized (GTK_WIDGET (icon_view))) gtk_widget_set_parent_window (child->widget, icon_view->priv->bin_window); gtk_widget_set_parent (widget, GTK_WIDGET (icon_view)); @@ -1722,7 +1879,7 @@ gtk_icon_view_remove_widget (GtkCellEditable *editable, info->editing = FALSE; } - if (GTK_WIDGET_HAS_FOCUS (editable)) + if (gtk_widget_has_focus (GTK_WIDGET (editable))) gtk_widget_grab_focus (GTK_WIDGET (icon_view)); g_signal_handlers_disconnect_by_func (editable, @@ -1839,11 +1996,11 @@ gtk_icon_view_stop_editing (GtkIconView *icon_view, * gtk_icon_view_set_cursor: * @icon_view: A #GtkIconView * @path: A #GtkTreePath - * @cell: One of the cell renderers of @icon_view, or %NULL + * @cell: (allow-none): One of the cell renderers of @icon_view, or %NULL * @start_editing: %TRUE if the specified cell should start being edited. * * Sets the current keyboard focus to be at @path, and selects it. This is - * useful when you want to focus the user's attention on a particular item. + * useful when you want to focus the user's attention on a particular item. * If @cell is not %NULL, then focus is given to the cell specified by * it. Additionally, if @start_editing is %TRUE, then editing should be * started in the specified cell. @@ -1904,8 +2061,8 @@ gtk_icon_view_set_cursor (GtkIconView *icon_view, /** * gtk_icon_view_get_cursor: * @icon_view: A #GtkIconView - * @path: Return location for the current cursor path, or %NULL - * @cell: Return location the current focus cell, or %NULL + * @path: (allow-none): Return location for the current cursor path, or %NULL + * @cell: (allow-none): Return location the current focus cell, or %NULL * * Fills in @path and @cell with the current cursor path and cell. * If the cursor isn't currently set, then *@path will be %NULL. @@ -1969,7 +2126,7 @@ gtk_icon_view_button_press (GtkWidget *widget, if (event->window != icon_view->priv->bin_window) return FALSE; - if (!GTK_WIDGET_HAS_FOCUS (widget)) + if (!gtk_widget_has_focus (widget)) gtk_widget_grab_focus (widget); if (event->button == 1 && event->type == GDK_BUTTON_PRESS) @@ -2027,14 +2184,11 @@ gtk_icon_view_button_press (GtkWidget *widget, } else { - if (!item->selected) - { - gtk_icon_view_unselect_all_internal (icon_view); - - item->selected = TRUE; - gtk_icon_view_queue_draw_item (icon_view, item); - dirty = TRUE; - } + gtk_icon_view_unselect_all_internal (icon_view); + + item->selected = TRUE; + gtk_icon_view_queue_draw_item (icon_view, item); + dirty = TRUE; } gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell); icon_view->priv->anchor_item = item; @@ -2073,9 +2227,11 @@ gtk_icon_view_button_press (GtkWidget *widget, } if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE) - gtk_icon_view_start_rubberbanding (icon_view, event->x, event->y); + gtk_icon_view_start_rubberbanding (icon_view, event->device, event->x, event->y); } + /* don't draw keyboard focus around an clicked-on item */ + icon_view->priv->draw_focus = FALSE; } if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) @@ -2130,7 +2286,7 @@ gtk_icon_view_key_press (GtkWidget *widget, if (icon_view->priv->doing_rubberband) { - if (event->keyval == GDK_Escape) + if (event->keyval == GDK_KEY_Escape) gtk_icon_view_stop_rubberbanding (icon_view); return TRUE; @@ -2159,11 +2315,13 @@ gtk_icon_view_update_rubberband (gpointer data) GdkRectangle old_area; GdkRectangle new_area; GdkRectangle common; - GdkRegion *invalid_region; + cairo_region_t *invalid_region; icon_view = GTK_ICON_VIEW (data); - gdk_window_get_pointer (icon_view->priv->bin_window, &x, &y, NULL); + gdk_window_get_device_position (icon_view->priv->bin_window, + icon_view->priv->rubberband_device, + &x, &y, NULL); x = MAX (x, 0); y = MAX (y, 0); @@ -2182,13 +2340,13 @@ gtk_icon_view_update_rubberband (gpointer data) new_area.width = ABS (x - icon_view->priv->rubberband_x1) + 1; new_area.height = ABS (y - icon_view->priv->rubberband_y1) + 1; - invalid_region = gdk_region_rectangle (&old_area); - gdk_region_union_with_rect (invalid_region, &new_area); + invalid_region = cairo_region_create_rectangle (&old_area); + cairo_region_union_rectangle (invalid_region, &new_area); gdk_rectangle_intersect (&old_area, &new_area, &common); if (common.width > 2 && common.height > 2) { - GdkRegion *common_region; + cairo_region_t *common_region; /* make sure the border is invalidated */ common.x += 1; @@ -2196,15 +2354,15 @@ gtk_icon_view_update_rubberband (gpointer data) common.width -= 2; common.height -= 2; - common_region = gdk_region_rectangle (&common); + common_region = cairo_region_create_rectangle (&common); - gdk_region_subtract (invalid_region, common_region); - gdk_region_destroy (common_region); + cairo_region_subtract (invalid_region, common_region); + cairo_region_destroy (common_region); } gdk_window_invalidate_region (icon_view->priv->bin_window, invalid_region, TRUE); - gdk_region_destroy (invalid_region); + cairo_region_destroy (invalid_region); icon_view->priv->rubberband_x2 = x; icon_view->priv->rubberband_y2 = y; @@ -2214,12 +2372,14 @@ gtk_icon_view_update_rubberband (gpointer data) static void gtk_icon_view_start_rubberbanding (GtkIconView *icon_view, + GdkDevice *device, gint x, gint y) { GList *items; - g_assert (!icon_view->priv->doing_rubberband); + if (icon_view->priv->rubberband_device) + return; for (items = icon_view->priv->items; items; items = items->next) { @@ -2234,8 +2394,9 @@ gtk_icon_view_start_rubberbanding (GtkIconView *icon_view, icon_view->priv->rubberband_y2 = y; icon_view->priv->doing_rubberband = TRUE; + icon_view->priv->rubberband_device = device; - gtk_grab_add (GTK_WIDGET (icon_view)); + gtk_device_grab_add (GTK_WIDGET (icon_view), device, TRUE); } static void @@ -2244,10 +2405,12 @@ gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view) if (!icon_view->priv->doing_rubberband) return; + gtk_device_grab_remove (GTK_WIDGET (icon_view), + icon_view->priv->rubberband_device); + icon_view->priv->doing_rubberband = FALSE; + icon_view->priv->rubberband_device = NULL; - gtk_grab_remove (GTK_WIDGET (icon_view)); - gtk_widget_queue_draw (GTK_WIDGET (icon_view)); } @@ -2309,7 +2472,7 @@ gtk_icon_view_item_hit_test (GtkIconView *icon_view, { GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; gtk_icon_view_get_cell_box (icon_view, item, info, &box); @@ -2359,11 +2522,11 @@ gtk_icon_view_set_adjustments (GtkIconView *icon_view, if (hadj) g_return_if_fail (GTK_IS_ADJUSTMENT (hadj)); else - hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + hadj = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); if (vadj) g_return_if_fail (GTK_IS_ADJUSTMENT (vadj)); else - vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + vadj = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); if (icon_view->priv->hadjustment && (icon_view->priv->hadjustment != hadj)) { @@ -2500,7 +2663,7 @@ static void gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment, GtkIconView *icon_view) { - if (GTK_WIDGET_REALIZED (icon_view)) + if (gtk_widget_get_realized (GTK_WIDGET (icon_view))) { gdk_window_move (icon_view->priv->bin_window, - icon_view->priv->hadjustment->value, @@ -2521,6 +2684,8 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, gint *y, gint *maximum_width) { + GtkAllocation allocation; + GtkWidget *widget = GTK_WIDGET (icon_view); gint focus_width; gint x, current_width; GList *items, *last_item; @@ -2530,7 +2695,7 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, gint i; gboolean rtl; - rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL; + rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL; max_height = g_new0 (gint, icon_view->priv->n_cells); x = 0; @@ -2538,7 +2703,7 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, items = first_item; current_width = 0; - gtk_widget_style_get (GTK_WIDGET (icon_view), + gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); @@ -2559,7 +2724,9 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, if (items != first_item) { - if ((icon_view->priv->columns <= 0 && current_width > GTK_WIDGET (icon_view)->allocation.width) || + gtk_widget_get_allocation (widget, &allocation); + + if ((icon_view->priv->columns <= 0 && current_width > allocation.width) || (icon_view->priv->columns > 0 && col >= icon_view->priv->columns)) break; } @@ -2567,7 +2734,7 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, current_width += icon_view->priv->column_spacing + 2 * focus_width; item->y = *y + focus_width; - item->x = rtl ? GTK_WIDGET (icon_view)->allocation.width - item->width - x : x; + item->x = x; x = current_width - (icon_view->priv->margin + focus_width); @@ -2591,14 +2758,17 @@ gtk_icon_view_layout_single_row (GtkIconView *icon_view, { GtkIconViewItem *item = items->data; + if (rtl) + { + item->x = *maximum_width - item->width - item->x; + item->col = col - 1 - item->col; + } + gtk_icon_view_calculate_item_size2 (icon_view, item, max_height); /* We may want to readjust the new y coordinate. */ if (item->y + item->height + focus_width + icon_view->priv->row_spacing > *y) *y = item->y + item->height + focus_width + icon_view->priv->row_spacing; - - if (rtl) - item->col = col - 1 - item->col; } g_free (max_height); @@ -2633,11 +2803,13 @@ gtk_icon_view_set_adjustment_upper (GtkAdjustment *adj, static void gtk_icon_view_layout (GtkIconView *icon_view) { - gint y = 0, maximum_width = 0; - GList *icons; + GtkAllocation allocation; GtkWidget *widget; + GList *icons; + gint y = 0, maximum_width = 0; gint row; gint item_width; + gboolean size_changed = FALSE; if (icon_view->priv->layout_idle_id != 0) { @@ -2683,26 +2855,32 @@ gtk_icon_view_layout (GtkIconView *icon_view) while (icons != NULL); if (maximum_width != icon_view->priv->width) - icon_view->priv->width = maximum_width; + { + icon_view->priv->width = maximum_width; + size_changed = TRUE; + } y += icon_view->priv->margin; if (y != icon_view->priv->height) - icon_view->priv->height = y; + { + icon_view->priv->height = y; + size_changed = TRUE; + } gtk_icon_view_set_adjustment_upper (icon_view->priv->hadjustment, icon_view->priv->width); gtk_icon_view_set_adjustment_upper (icon_view->priv->vadjustment, icon_view->priv->height); - if (icon_view->priv->width != widget->requisition.width || - icon_view->priv->height != widget->requisition.height) + if (size_changed) gtk_widget_queue_resize_no_redraw (widget); - if (GTK_WIDGET_REALIZED (icon_view)) + gtk_widget_get_allocation (widget, &allocation); + if (gtk_widget_get_realized (GTK_WIDGET (icon_view))) gdk_window_resize (icon_view->priv->bin_window, - MAX (icon_view->priv->width, widget->allocation.width), - MAX (icon_view->priv->height, widget->allocation.height)); + MAX (icon_view->priv->width, allocation.width), + MAX (icon_view->priv->height, allocation.height)); if (icon_view->priv->scroll_to_path) { @@ -2730,19 +2908,19 @@ gtk_icon_view_get_cell_area (GtkIconView *icon_view, { g_return_if_fail (info->position < item->n_cells); - if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) { cell_area->x = item->box[info->position].x - item->before[info->position]; - cell_area->y = item->y + ITEM_PADDING; + cell_area->y = item->y + icon_view->priv->item_padding; cell_area->width = item->box[info->position].width + item->before[info->position] + item->after[info->position]; - cell_area->height = item->height - ITEM_PADDING * 2; + cell_area->height = item->height - icon_view->priv->item_padding * 2; } else { - cell_area->x = item->x + ITEM_PADDING; + cell_area->x = item->x + icon_view->priv->item_padding; cell_area->y = item->box[info->position].y - item->before[info->position]; - cell_area->width = item->width - ITEM_PADDING * 2; + cell_area->width = item->width - icon_view->priv->item_padding * 2; cell_area->height = item->box[info->position].height + item->before[info->position] + item->after[info->position]; } @@ -2767,43 +2945,38 @@ adjust_wrap_width (GtkIconView *icon_view, { GtkIconViewCellInfo *text_info; GtkIconViewCellInfo *pixbuf_info; - gint pixbuf_width, wrap_width; - + gint wrap_width; + if (icon_view->priv->text_cell != -1 && icon_view->priv->pixbuf_cell != -1) { + GtkRequisition min_size; gint item_width; text_info = g_list_nth_data (icon_view->priv->cell_list, icon_view->priv->text_cell); pixbuf_info = g_list_nth_data (icon_view->priv->cell_list, icon_view->priv->pixbuf_cell); - - gtk_cell_renderer_get_size (pixbuf_info->cell, - GTK_WIDGET (icon_view), - NULL, NULL, NULL, - &pixbuf_width, - NULL); - + + gtk_cell_renderer_get_preferred_size (pixbuf_info->cell, + GTK_WIDGET (icon_view), + &min_size, NULL); if (icon_view->priv->item_width > 0) item_width = icon_view->priv->item_width; else item_width = item->width; - if (item->width == -1) - { - if (item_width > 0) - wrap_width = item_width - pixbuf_width - icon_view->priv->spacing; - else - wrap_width = MAX (2 * pixbuf_width, 50); - } - else if (icon_view->priv->orientation == GTK_ORIENTATION_VERTICAL) - wrap_width = item_width; - else - wrap_width = item_width - pixbuf_width - icon_view->priv->spacing; + if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL) + wrap_width = item_width; + else { + if (item->width == -1 && item_width <= 0) + wrap_width = MAX (2 * min_size.width, 50); + else + wrap_width = item_width - min_size.width - icon_view->priv->spacing; + } - wrap_width -= ITEM_PADDING * 2; + wrap_width -= icon_view->priv->item_padding * 2; g_object_set (text_info->cell, "wrap-width", wrap_width, NULL); g_object_set (text_info->cell, "width", wrap_width, NULL); @@ -2814,6 +2987,7 @@ static void gtk_icon_view_calculate_item_size (GtkIconView *icon_view, GtkIconViewItem *item) { + GtkRequisition min_size; gint spacing; GList *l; @@ -2843,15 +3017,16 @@ gtk_icon_view_calculate_item_size (GtkIconView *icon_view, { GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; - - gtk_cell_renderer_get_size (info->cell, GTK_WIDGET (icon_view), - NULL, NULL, NULL, - &item->box[info->position].width, - &item->box[info->position].height); - if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_cell_renderer_get_preferred_size (info->cell, + GTK_WIDGET (icon_view), + &min_size, NULL); + item->box[info->position].width = min_size.width; + item->box[info->position].height = min_size.height; + + if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) { item->width += item->box[info->position].width + (info->position > 0 ? spacing : 0); @@ -2864,8 +3039,8 @@ gtk_icon_view_calculate_item_size (GtkIconView *icon_view, } } - item->width += ITEM_PADDING * 2; - item->height += ITEM_PADDING * 2; + item->width += icon_view->priv->item_padding * 2; + item->height += icon_view->priv->item_padding * 2; } static void @@ -2873,6 +3048,7 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, GtkIconViewItem *item, gint *max_height) { + GtkRequisition min_size; GdkRectangle cell_area; gint spacing; GList *l; @@ -2888,29 +3064,29 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, item->height = 0; for (i = 0; i < icon_view->priv->n_cells; i++) { - if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) item->height = MAX (item->height, max_height[i]); else item->height += max_height[i] + (i > 0 ? spacing : 0); } - cell_area.x = item->x + ITEM_PADDING; - cell_area.y = item->y + ITEM_PADDING; + cell_area.x = item->x + icon_view->priv->item_padding; + cell_area.y = item->y + icon_view->priv->item_padding; for (k = 0; k < 2; k++) for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++) { GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - + if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END)) continue; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; - if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) { - /* We should not subtract ITEM_PADDING from item->height, + /* We should not subtract icon_view->priv->item_padding from item->height, * because item->height is recalculated above using * max_height which does not contain item padding. */ @@ -2922,18 +3098,24 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, /* item->width is not recalculated and thus needs to be * corrected for the padding. */ - cell_area.width = item->width - 2 * ITEM_PADDING; + cell_area.width = item->width - 2 * icon_view->priv->item_padding; cell_area.height = max_height[i]; } - - gtk_cell_renderer_get_size (info->cell, GTK_WIDGET (icon_view), - &cell_area, - &item->box[info->position].x, &item->box[info->position].y, - &item->box[info->position].width, &item->box[info->position].height); - + + gtk_cell_renderer_get_preferred_size (info->cell, + GTK_WIDGET (icon_view), + &min_size, NULL); + item->box[info->position].width = min_size.width; + item->box[info->position].height = min_size.height; + + _gtk_cell_renderer_calc_offset (info->cell, &cell_area, + gtk_widget_get_direction (GTK_WIDGET (icon_view)), + item->box[info->position].width, item->box[info->position].height, + &item->box[info->position].x, &item->box[info->position].y); item->box[info->position].x += cell_area.x; item->box[info->position].y += cell_area.y; - if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + + if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) { item->before[info->position] = item->box[info->position].x - cell_area.x; item->after[info->position] = cell_area.width - item->box[info->position].width - item->before[info->position]; @@ -2941,9 +3123,9 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, } else { - if (item->box[info->position].width > item->width - ITEM_PADDING * 2) + if (item->box[info->position].width > item->width - icon_view->priv->item_padding * 2) { - item->width = item->box[info->position].width + ITEM_PADDING * 2; + item->width = item->box[info->position].width + icon_view->priv->item_padding * 2; cell_area.width = item->width; } item->before[info->position] = item->box[info->position].y - cell_area.y; @@ -2952,7 +3134,7 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, } } - if (rtl && icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL) + if (rtl && icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL) { for (i = 0; i < icon_view->priv->n_cells; i++) { @@ -2961,7 +3143,7 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, } } - item->height += ITEM_PADDING * 2; + item->height += icon_view->priv->item_padding * 2; } static void @@ -2982,8 +3164,6 @@ static void gtk_icon_view_paint_item (GtkIconView *icon_view, cairo_t *cr, GtkIconViewItem *item, - GdkRectangle *area, - GdkDrawable *drawable, gint x, gint y, gboolean draw_focus) @@ -2995,13 +3175,16 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, gint i; GtkStateType state; GtkCellRendererState flags; - + GtkStyle *style; + GtkWidget *widget = GTK_WIDGET (icon_view); + if (icon_view->priv->model == NULL) return; gtk_icon_view_set_cell_data (icon_view, item); - gtk_widget_style_get (GTK_WIDGET (icon_view), + style = gtk_widget_get_style (widget); + gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); @@ -3010,7 +3193,7 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, if (item->selected) { flags = GTK_CELL_RENDERER_SELECTED; - if (GTK_WIDGET_HAS_FOCUS (icon_view)) + if (gtk_widget_has_focus (widget)) state = GTK_STATE_SELECTED; else state = GTK_STATE_ACTIVE; @@ -3020,89 +3203,63 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, flags = 0; state = GTK_STATE_NORMAL; } - -#ifdef DEBUG_ICON_VIEW - gdk_draw_rectangle (drawable, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - x, y, - item->width, item->height); -#endif if (item->selected) { - gtk_paint_flat_box (GTK_WIDGET (icon_view)->style, - (GdkWindow *) drawable, - GTK_STATE_SELECTED, - GTK_SHADOW_NONE, - area, - GTK_WIDGET (icon_view), - "icon_view_item", - x, y, - item->width, item->height); + gtk_paint_flat_box (style, + cr, + GTK_STATE_SELECTED, + GTK_SHADOW_NONE, + GTK_WIDGET (icon_view), + "icon_view_item", + x, y, + item->width, item->height); } for (l = icon_view->priv->cell_list; l; l = l->next) { GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area); - -#ifdef DEBUG_ICON_VIEW - gdk_draw_rectangle (drawable, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - x - item->x + cell_area.x, - y - item->y + cell_area.y, - cell_area.width, cell_area.height); - - gtk_icon_view_get_cell_box (icon_view, item, info, &box); - - gdk_draw_rectangle (drawable, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - x - item->x + box.x, - y - item->y + box.y, - box.width, box.height); -#endif cell_area.x = x - item->x + cell_area.x; cell_area.y = y - item->y + cell_area.y; gtk_cell_renderer_render (info->cell, - drawable, - GTK_WIDGET (icon_view), - &cell_area, &cell_area, area, flags); + cr, + widget, + &cell_area, &cell_area, flags); } if (draw_focus && - GTK_WIDGET_HAS_FOCUS (icon_view) && + gtk_widget_has_focus (widget) && item == icon_view->priv->cursor_item) { for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++) { + GtkCellRendererMode mode; GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; /* If found a editable/activatable cell, draw focus on it. */ + g_object_get (info->cell, "mode", &mode, NULL); if (icon_view->priv->cursor_cell < 0 && - info->cell->mode != GTK_CELL_RENDERER_MODE_INERT) + mode != GTK_CELL_RENDERER_MODE_INERT) icon_view->priv->cursor_cell = i; gtk_icon_view_get_cell_box (icon_view, item, info, &box); if (i == icon_view->priv->cursor_cell) { - gtk_paint_focus (GTK_WIDGET (icon_view)->style, - drawable, + gtk_paint_focus (style, + cr, GTK_STATE_NORMAL, - area, - GTK_WIDGET (icon_view), + widget, "icon_view", x - item->x + box.x - padding, y - item->y + box.y - padding, @@ -3116,11 +3273,10 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, * around the whole item. */ if (icon_view->priv->cursor_cell < 0) - gtk_paint_focus (GTK_WIDGET (icon_view)->style, - drawable, + gtk_paint_focus (style, + cr, GTK_STATE_NORMAL, - area, - GTK_WIDGET (icon_view), + widget, "icon_view", x - padding, y - padding, @@ -3131,21 +3287,18 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view, - cairo_t *cr, - GdkRectangle *area) + cairo_t *cr) { GdkRectangle rect; - GdkRectangle rubber_rect; GdkColor *fill_color_gdk; guchar fill_color_alpha; - rubber_rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2); - rubber_rect.y = MIN (icon_view->priv->rubberband_y1, icon_view->priv->rubberband_y2); - rubber_rect.width = ABS (icon_view->priv->rubberband_x1 - icon_view->priv->rubberband_x2) + 1; - rubber_rect.height = ABS (icon_view->priv->rubberband_y1 - icon_view->priv->rubberband_y2) + 1; + cairo_save (cr); - if (!gdk_rectangle_intersect (&rubber_rect, area, &rect)) - return; + rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2); + rect.y = MIN (icon_view->priv->rubberband_y1, icon_view->priv->rubberband_y2); + rect.width = ABS (icon_view->priv->rubberband_x1 - icon_view->priv->rubberband_x2) + 1; + rect.height = ABS (icon_view->priv->rubberband_y1 - icon_view->priv->rubberband_y2) + 1; gtk_widget_style_get (GTK_WIDGET (icon_view), "selection-box-color", &fill_color_gdk, @@ -3153,31 +3306,23 @@ gtk_icon_view_paint_rubberband (GtkIconView *icon_view, NULL); if (!fill_color_gdk) - fill_color_gdk = gdk_color_copy (>K_WIDGET (icon_view)->style->base[GTK_STATE_SELECTED]); + fill_color_gdk = gdk_color_copy (>k_widget_get_style (GTK_WIDGET (icon_view))->base[GTK_STATE_SELECTED]); - cairo_set_source_rgba (cr, - fill_color_gdk->red / 65535., - fill_color_gdk->green / 65535., - fill_color_gdk->blue / 65535., - fill_color_alpha / 255.); + gdk_cairo_set_source_color (cr, fill_color_gdk); - cairo_save (cr); gdk_cairo_rectangle (cr, &rect); cairo_clip (cr); - cairo_paint (cr); - /* Draw the border without alpha */ - cairo_set_source_rgb (cr, - fill_color_gdk->red / 65535., - fill_color_gdk->green / 65535., - fill_color_gdk->blue / 65535.); + cairo_paint_with_alpha (cr, fill_color_alpha / 255.); + cairo_rectangle (cr, - rubber_rect.x + 0.5, rubber_rect.y + 0.5, - rubber_rect.width - 1, rubber_rect.height - 1); + rect.x + 0.5, rect.y + 0.5, + rect.width - 1, rect.height - 1); cairo_stroke (cr); - cairo_restore (cr); gdk_color_free (fill_color_gdk); + + cairo_restore (cr); } static void @@ -3322,6 +3467,9 @@ gtk_icon_view_get_item_at_coords (GtkIconView *icon_view, GList *items, *l; GdkRectangle box; + if (cell_at_pos) + *cell_at_pos = NULL; + for (items = icon_view->priv->items; items; items = items->next) { GtkIconViewItem *item = items->data; @@ -3336,12 +3484,12 @@ gtk_icon_view_get_item_at_coords (GtkIconView *icon_view, for (l = icon_view->priv->cell_list; l; l = l->next) { GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; - - if (!info->cell->visible) + + if (!gtk_cell_renderer_get_visible (info->cell)) continue; - + gtk_icon_view_get_cell_box (icon_view, item, info, &box); - + if ((x >= box.x && x <= box.x + box.width && y >= box.y && y <= box.y + box.height) || (x >= box.x && @@ -3351,16 +3499,13 @@ gtk_icon_view_get_item_at_coords (GtkIconView *icon_view, { if (cell_at_pos) *cell_at_pos = info; - + return item; } } if (only_in_cell) return NULL; - - if (cell_at_pos) - *cell_at_pos = NULL; } return item; @@ -3674,7 +3819,7 @@ gtk_icon_view_real_move_cursor (GtkIconView *icon_view, step == GTK_MOVEMENT_PAGES || step == GTK_MOVEMENT_BUFFER_ENDS, FALSE); - if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (icon_view))) + if (!gtk_widget_has_focus (GTK_WIDGET (icon_view))) return FALSE; gtk_icon_view_stop_editing (icon_view, FALSE); @@ -3711,6 +3856,8 @@ gtk_icon_view_real_move_cursor (GtkIconView *icon_view, icon_view->priv->ctrl_pressed = FALSE; icon_view->priv->shift_pressed = FALSE; + icon_view->priv->draw_focus = TRUE; + return TRUE; } @@ -3753,7 +3900,7 @@ find_cell (GtkIconView *icon_view, gint i, k; GList *l; - if (icon_view->priv->orientation != orientation) + if (icon_view->priv->item_orientation != orientation) return cell; gtk_icon_view_set_cell_data (icon_view, item); @@ -3765,15 +3912,17 @@ find_cell (GtkIconView *icon_view, for (k = 0; k < 2; k++) for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++) { + GtkCellRendererMode mode; GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data; if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END)) continue; - if (!info->cell->visible) + if (!gtk_cell_renderer_get_visible (info->cell)) continue; - if (info->cell->mode != GTK_CELL_RENDERER_MODE_INERT) + g_object_get (info->cell, "mode", &mode, NULL); + if (mode != GTK_CELL_RENDERER_MODE_INERT) { if (cell == i) current = n_focusable; @@ -3926,10 +4075,13 @@ gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view, gint cell; gboolean dirty = FALSE; gint step; - - if (!GTK_WIDGET_HAS_FOCUS (icon_view)) + GtkDirectionType direction; + + if (!gtk_widget_has_focus (GTK_WIDGET (icon_view))) return; - + + direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN; + if (!icon_view->priv->cursor_item) { GList *list; @@ -3962,7 +4114,16 @@ gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view, if (!item) { - gtk_widget_error_bell (GTK_WIDGET (icon_view)); + if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction)) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view)); + if (toplevel) + gtk_widget_child_focus (toplevel, + direction == GTK_DIR_UP ? + GTK_DIR_TAB_BACKWARD : + GTK_DIR_TAB_FORWARD); + } + return; } @@ -3996,7 +4157,7 @@ gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view, GtkIconViewItem *item; gboolean dirty = FALSE; - if (!GTK_WIDGET_HAS_FOCUS (icon_view)) + if (!gtk_widget_has_focus (GTK_WIDGET (icon_view))) return; if (!icon_view->priv->cursor_item) @@ -4052,10 +4213,13 @@ gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view, gint cell = -1; gboolean dirty = FALSE; gint step; - - if (!GTK_WIDGET_HAS_FOCUS (icon_view)) + GtkDirectionType direction; + + if (!gtk_widget_has_focus (GTK_WIDGET (icon_view))) return; - + + direction = count < 0 ? GTK_DIR_LEFT : GTK_DIR_RIGHT; + if (!icon_view->priv->cursor_item) { GList *list; @@ -4087,7 +4251,16 @@ gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view, if (!item) { - gtk_widget_error_bell (GTK_WIDGET (icon_view)); + if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction)) + { + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view)); + if (toplevel) + gtk_widget_child_focus (toplevel, + direction == GTK_DIR_LEFT ? + GTK_DIR_TAB_BACKWARD : + GTK_DIR_TAB_FORWARD); + } + return; } @@ -4122,7 +4295,7 @@ gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view, GList *list; gboolean dirty = FALSE; - if (!GTK_WIDGET_HAS_FOCUS (icon_view)) + if (!gtk_widget_has_focus (GTK_WIDGET (icon_view))) return; if (count < 0) @@ -4194,17 +4367,21 @@ gtk_icon_view_scroll_to_path (GtkIconView *icon_view, gfloat col_align) { GtkIconViewItem *item = NULL; + GtkWidget *widget; g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); g_return_if_fail (path != NULL); g_return_if_fail (row_align >= 0.0 && row_align <= 1.0); g_return_if_fail (col_align >= 0.0 && col_align <= 1.0); + widget = GTK_WIDGET (icon_view); + 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 (!GTK_WIDGET_REALIZED (icon_view) || !item || item->width < 0) + if (!item || item->width < 0 || + !gtk_widget_get_realized (widget)) { if (icon_view->priv->scroll_to_path) gtk_tree_row_reference_free (icon_view->priv->scroll_to_path); @@ -4223,24 +4400,25 @@ gtk_icon_view_scroll_to_path (GtkIconView *icon_view, if (use_align) { + GtkAllocation allocation; gint x, y; gint focus_width; gfloat offset; - gtk_widget_style_get (GTK_WIDGET (icon_view), + gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); gdk_window_get_position (icon_view->priv->bin_window, &x, &y); - - offset = y + item->y - focus_width - - row_align * (GTK_WIDGET (icon_view)->allocation.height - item->height); + + gtk_widget_get_allocation (widget, &allocation); + + offset = y + item->y - focus_width - row_align * (allocation.height - item->height); gtk_adjustment_set_value (icon_view->priv->vadjustment, icon_view->priv->vadjustment->value + offset); - offset = x + item->x - focus_width - - col_align * (GTK_WIDGET (icon_view)->allocation.width - item->width); + offset = x + item->x - focus_width - col_align * (allocation.width - item->width); gtk_adjustment_set_value (icon_view->priv->hadjustment, icon_view->priv->hadjustment->value + offset); @@ -4257,32 +4435,36 @@ static void gtk_icon_view_scroll_to_item (GtkIconView *icon_view, GtkIconViewItem *item) { + GtkAllocation allocation; + GtkWidget *widget = GTK_WIDGET (icon_view); gint x, y, width, height; gint focus_width; - gtk_widget_style_get (GTK_WIDGET (icon_view), + gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL); - gdk_drawable_get_size (GDK_DRAWABLE (icon_view->priv->bin_window), - &width, &height); + width = gdk_window_get_width (icon_view->priv->bin_window); + height = gdk_window_get_height (icon_view->priv->bin_window); gdk_window_get_position (icon_view->priv->bin_window, &x, &y); - + + gtk_widget_get_allocation (widget, &allocation); + if (y + item->y - focus_width < 0) gtk_adjustment_set_value (icon_view->priv->vadjustment, icon_view->priv->vadjustment->value + y + item->y - focus_width); - else if (y + item->y + item->height + focus_width > GTK_WIDGET (icon_view)->allocation.height) + else if (y + item->y + item->height + focus_width > allocation.height) gtk_adjustment_set_value (icon_view->priv->vadjustment, icon_view->priv->vadjustment->value + y + item->y + item->height - + focus_width - GTK_WIDGET (icon_view)->allocation.height); + + focus_width - allocation.height); if (x + item->x - focus_width < 0) gtk_adjustment_set_value (icon_view->priv->hadjustment, - icon_view->priv->hadjustment->value + x + item->x - focus_width); - else if (x + item->x + item->width + focus_width > GTK_WIDGET (icon_view)->allocation.width) + icon_view->priv->hadjustment->value + x + item->x - focus_width); + else if (x + item->x + item->width + focus_width > allocation.width) gtk_adjustment_set_value (icon_view->priv->hadjustment, icon_view->priv->hadjustment->value + x + item->x + item->width - + focus_width - GTK_WIDGET (icon_view)->allocation.width); + + focus_width - allocation.width); gtk_adjustment_changed (icon_view->priv->hadjustment); gtk_adjustment_changed (icon_view->priv->vadjustment); @@ -4670,7 +4852,7 @@ gtk_icon_view_get_path_at_pos (GtkIconView *icon_view, * @icon_view: A #GtkIconView. * @x: The x position to be identified * @y: The y position to be identified - * @path: Return location for the path, or %NULL + * @path: (allow-none): Return location for the path, or %NULL * @cell: Return location for the renderer responsible for the cell * at (@x, @y), or %NULL * @@ -4725,6 +4907,7 @@ gtk_icon_view_get_item_at_pos (GtkIconView *icon_view, * @path: a #GtkTreePath * * Sets the tip area of @tooltip to be the area covered by the item at @path. + * See also gtk_icon_view_set_tooltip_column() for a simpler alternative. * See also gtk_tooltip_set_tip_area(). * * Since: 2.12 @@ -4745,11 +4928,13 @@ gtk_icon_view_set_tooltip_item (GtkIconView *icon_view, * @icon_view: a #GtkIconView * @tooltip: a #GtkTooltip * @path: a #GtkTreePath - * @cell: a #GtkCellRenderer or %NULL + * @cell: (allow-none): a #GtkCellRenderer or %NULL * * Sets the tip area of @tooltip to the area which @cell occupies in * the item pointed to by @path. See also gtk_tooltip_set_tip_area(). * + * See also gtk_icon_view_set_tooltip_column() for a simpler alternative. + * * Since: 2.12 */ void @@ -4804,9 +4989,9 @@ gtk_icon_view_set_tooltip_cell (GtkIconView *icon_view, * @x: the x coordinate (relative to widget coordinates) * @y: the y coordinate (relative to widget coordinates) * @keyboard_tip: whether this is a keyboard tooltip or not - * @model: a pointer to receive a #GtkTreeModel or %NULL - * @path: a pointer to receive a #GtkTreePath or %NULL - * @iter: a pointer to receive a #GtkTreeIter or %NULL + * @model: (out) (allow-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 * * This function is supposed to be used in a #GtkWidget::query-tooltip * signal handler for #GtkIconView. The @x, @y and @keyboard_tip values @@ -4976,8 +5161,8 @@ gtk_icon_view_get_tooltip_column (GtkIconView *icon_view) /** * gtk_icon_view_get_visible_range: * @icon_view: A #GtkIconView - * @start_path: Return location for start of region, or %NULL - * @end_path: Return location for end of region, or %NULL + * @start_path: (allow-none): Return location for start of region, or %NULL + * @end_path: (allow-none): Return location for end of region, or %NULL * * Sets @start_path and @end_path to be the first and last visible path. * Note that there may be invisible paths in between. @@ -5032,7 +5217,7 @@ gtk_icon_view_get_visible_range (GtkIconView *icon_view, /** * gtk_icon_view_selected_foreach: * @icon_view: A #GtkIconView. - * @func: The funcion to call for each selected icon. + * @func: (scope call): The function to call for each selected icon. * @data: User data to pass to the function. * * Calls a function for each selected icon. Note that the model or @@ -5107,10 +5292,10 @@ gtk_icon_view_get_selection_mode (GtkIconView *icon_view) /** * gtk_icon_view_set_model: * @icon_view: A #GtkIconView. - * @model: The model. + * @model: (allow-none): The model. * - * Sets the model for a #GtkIconView. - * If the @icon_view already has a model set, it will remove + * Sets the model for a #GtkIconView. + * If the @icon_view already has a model set, it will remove * it before setting the new model. If @model is %NULL, then * it will unset the old model. * @@ -5222,7 +5407,7 @@ gtk_icon_view_set_model (GtkIconView *icon_view, g_object_notify (G_OBJECT (icon_view), "model"); - if (GTK_WIDGET_REALIZED (icon_view)) + if (gtk_widget_get_realized (GTK_WIDGET (icon_view))) gtk_widget_queue_resize (GTK_WIDGET (icon_view)); } @@ -5233,7 +5418,8 @@ gtk_icon_view_set_model (GtkIconView *icon_view, * Returns the model the #GtkIconView is based on. Returns %NULL if the * model is unset. * - * Return value: A #GtkTreeModel, or %NULL if none is currently being used. + * Return value: (transfer none): A #GtkTreeModel, or %NULL if none is + * currently being used. * * Since: 2.6 **/ @@ -5302,7 +5488,7 @@ update_text_cell (GtkIconView *icon_view) "text", icon_view->priv->text_column, NULL); - if (icon_view->priv->orientation == GTK_ORIENTATION_VERTICAL) + if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL) g_object_set (info->cell, "alignment", PANGO_ALIGN_CENTER, "wrap-mode", PANGO_WRAP_WORD_CHAR, @@ -5370,7 +5556,7 @@ update_pixbuf_cell (GtkIconView *icon_view) "pixbuf", icon_view->priv->pixbuf_column, NULL); - if (icon_view->priv->orientation == GTK_ORIENTATION_VERTICAL) + if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL) g_object_set (info->cell, "xalign", 0.5, "yalign", 1.0, @@ -5635,11 +5821,11 @@ gtk_icon_view_unselect_path (GtkIconView *icon_view, * * To free the return value, use: * |[ - * g_list_foreach (list, gtk_tree_path_free, NULL); + * g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL); * g_list_free (list); * ]| * - * Return value: A #GList containing a #GtkTreePath for each selected row. + * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row. * * Since: 2.6 **/ @@ -5757,6 +5943,68 @@ gtk_icon_view_path_is_selected (GtkIconView *icon_view, return item->selected; } +/** + * gtk_icon_view_get_item_row: + * @icon_view: a #GtkIconView + * @path: the #GtkTreePath of the item + * + * Gets the row in which the item @path is currently + * displayed. Row numbers start at 0. + * + * Returns: The row in which the item is displayed + * + * Since: 2.22 + */ +gint +gtk_icon_view_get_item_row (GtkIconView *icon_view, + GtkTreePath *path) +{ + GtkIconViewItem *item; + + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1); + g_return_val_if_fail (icon_view->priv->model != NULL, -1); + g_return_val_if_fail (path != NULL, -1); + + item = g_list_nth_data (icon_view->priv->items, + gtk_tree_path_get_indices(path)[0]); + + if (!item) + return -1; + + return item->row; +} + +/** + * gtk_icon_view_get_item_column: + * @icon_view: a #GtkIconView + * @path: the #GtkTreePath of the item + * + * Gets the column in which the item @path is currently + * displayed. Column numbers start at 0. + * + * Returns: The column in which the item is displayed + * + * Since: 2.22 + */ +gint +gtk_icon_view_get_item_column (GtkIconView *icon_view, + GtkTreePath *path) +{ + GtkIconViewItem *item; + + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1); + g_return_val_if_fail (icon_view->priv->model != NULL, -1); + g_return_val_if_fail (path != NULL, -1); + + item = g_list_nth_data (icon_view->priv->items, + gtk_tree_path_get_indices(path)[0]); + + if (!item) + return -1; + + return item->col; +} + /** * gtk_icon_view_item_activated: * @icon_view: A #GtkIconView @@ -5777,24 +6025,24 @@ gtk_icon_view_item_activated (GtkIconView *icon_view, } /** - * gtk_icon_view_set_orientation: + * gtk_icon_view_set_item_orientation: * @icon_view: a #GtkIconView * @orientation: the relative position of texts and icons * - * Sets the ::orientation property which determines whether the labels + * Sets the ::item-orientation property which determines whether the labels * are drawn beside the icons instead of below. * * Since: 2.6 **/ void -gtk_icon_view_set_orientation (GtkIconView *icon_view, - GtkOrientation orientation) +gtk_icon_view_set_item_orientation (GtkIconView *icon_view, + GtkOrientation orientation) { g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); - if (icon_view->priv->orientation != orientation) + if (icon_view->priv->item_orientation != orientation) { - icon_view->priv->orientation = orientation; + icon_view->priv->item_orientation = orientation; gtk_icon_view_stop_editing (icon_view, TRUE); gtk_icon_view_invalidate_sizes (icon_view); @@ -5803,15 +6051,15 @@ gtk_icon_view_set_orientation (GtkIconView *icon_view, update_text_cell (icon_view); update_pixbuf_cell (icon_view); - g_object_notify (G_OBJECT (icon_view), "orientation"); + g_object_notify (G_OBJECT (icon_view), "item-orientation"); } } /** - * gtk_icon_view_get_orientation: + * gtk_icon_view_get_item_orientation: * @icon_view: a #GtkIconView * - * Returns the value of the ::orientation property which determines + * Returns the value of the ::item-orientation property which determines * whether the labels are drawn beside the icons instead of below. * * Return value: the relative position of texts and icons @@ -5819,12 +6067,12 @@ gtk_icon_view_set_orientation (GtkIconView *icon_view, * Since: 2.6 **/ GtkOrientation -gtk_icon_view_get_orientation (GtkIconView *icon_view) +gtk_icon_view_get_item_orientation (GtkIconView *icon_view) { g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), GTK_ORIENTATION_VERTICAL); - return icon_view->priv->orientation; + return icon_view->priv->item_orientation; } /** @@ -6110,6 +6358,51 @@ gtk_icon_view_get_margin (GtkIconView *icon_view) return icon_view->priv->margin; } +/** + * gtk_icon_view_set_item_padding: + * @icon_view: a #GtkIconView + * @item_padding: the item padding + * + * Sets the #GtkIconView:item-padding property which specifies the padding + * around each of the icon view's items. + * + * Since: 2.18 + */ +void +gtk_icon_view_set_item_padding (GtkIconView *icon_view, + gint item_padding) +{ + g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); + + if (icon_view->priv->item_padding != item_padding) + { + icon_view->priv->item_padding = item_padding; + + gtk_icon_view_stop_editing (icon_view, TRUE); + gtk_icon_view_invalidate_sizes (icon_view); + gtk_icon_view_queue_layout (icon_view); + + g_object_notify (G_OBJECT (icon_view), "item-padding"); + } +} + +/** + * gtk_icon_view_get_item_padding: + * @icon_view: a #GtkIconView + * + * Returns the value of the ::item-padding property. + * + * Return value: the padding around items + * + * Since: 2.18 + */ +gint +gtk_icon_view_get_item_padding (GtkIconView *icon_view) +{ + g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1); + + return icon_view->priv->item_padding; +} /* Get/set whether drag_motion requested the drag data and * drag_data_received should thus not actually insert the data, @@ -6141,26 +6434,6 @@ unset_reorderable (GtkIconView *icon_view) } } -static void -clear_source_info (GtkIconView *icon_view) -{ - if (icon_view->priv->source_targets) - gtk_target_list_unref (icon_view->priv->source_targets); - icon_view->priv->source_targets = NULL; - - icon_view->priv->source_set = FALSE; -} - -static void -clear_dest_info (GtkIconView *icon_view) -{ - if (icon_view->priv->dest_targets) - gtk_target_list_unref (icon_view->priv->dest_targets); - icon_view->priv->dest_targets = NULL; - - icon_view->priv->dest_set = FALSE; -} - static void set_source_row (GdkDragContext *context, GtkTreeModel *model, @@ -6298,11 +6571,14 @@ remove_scroll_timeout (GtkIconView *icon_view) static void gtk_icon_view_autoscroll (GtkIconView *icon_view) { + GdkWindow *window; gint px, py, x, y, width, height; gint hoffset, voffset; - gdk_window_get_pointer (GTK_WIDGET (icon_view)->window, &px, &py, NULL); - gdk_window_get_geometry (GTK_WIDGET (icon_view)->window, &x, &y, &width, &height, NULL); + window = gtk_widget_get_window (GTK_WIDGET (icon_view)); + + gdk_window_get_pointer (window, &px, &py, NULL); + gdk_window_get_geometry (window, &x, &y, &width, &height, NULL); /* see if we are near the edge. */ voffset = py - (y + 2 * SCROLL_EDGE_SIZE); @@ -6369,7 +6645,8 @@ set_destination (GtkIconView *icon_view, return FALSE; /* no longer a drop site */ } - *target = gtk_drag_dest_find_target (widget, context, icon_view->priv->dest_targets); + *target = gtk_drag_dest_find_target (widget, context, + gtk_drag_dest_get_target_list (widget)); if (*target == GDK_NONE) return FALSE; @@ -6489,6 +6766,7 @@ static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, GdkEventMotion *event) { + GtkWidget *widget = GTK_WIDGET (icon_view); GdkDragContext *context; GtkTreePath *path = NULL; gint button; @@ -6535,8 +6813,8 @@ gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view, retval = TRUE; - context = gtk_drag_begin (GTK_WIDGET (icon_view), - icon_view->priv->source_targets, + context = gtk_drag_begin (widget, + gtk_drag_source_get_target_list (widget), icon_view->priv->source_actions, button, (GdkEvent*)event); @@ -6557,7 +6835,7 @@ gtk_icon_view_drag_begin (GtkWidget *widget, { GtkIconView *icon_view; GtkIconViewItem *item; - GdkPixmap *icon; + cairo_surface_t *icon; gint x, y; GtkTreePath *path; @@ -6582,13 +6860,11 @@ gtk_icon_view_drag_begin (GtkWidget *widget, icon = gtk_icon_view_create_drag_icon (icon_view, path); gtk_tree_path_free (path); - gtk_drag_set_icon_pixmap (context, - gdk_drawable_get_colormap (icon), - icon, - NULL, - x, y); + cairo_surface_set_device_offset (icon, -x, -y); + + gtk_drag_set_icon_surface (context, icon); - g_object_unref (icon); + cairo_surface_destroy (icon); } static void @@ -6900,8 +7176,9 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, * @n_targets: the number of items in @targets * @actions: the bitmask of possible actions for a drag from this * widget - * - * Turns @icon_view into a drag source for automatic DND. + * + * Turns @icon_view into a drag source for automatic DND. Calling this + * method sets #GtkIconView:reorderable to %FALSE. * * Since: 2.8 **/ @@ -6914,11 +7191,9 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view, { g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); - gtk_drag_source_set (GTK_WIDGET (icon_view), 0, NULL, 0, actions); + gtk_drag_source_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions); - clear_source_info (icon_view); icon_view->priv->start_button_mask = start_button_mask; - icon_view->priv->source_targets = gtk_target_list_new (targets, n_targets); icon_view->priv->source_actions = actions; icon_view->priv->source_set = TRUE; @@ -6933,8 +7208,9 @@ gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view, * @n_targets: the number of items in @targets * @actions: the bitmask of possible actions for a drag to this * widget - * - * Turns @icon_view into a drop destination for automatic DND. + * + * Turns @icon_view into a drop destination for automatic DND. Calling this + * method sets #GtkIconView:reorderable to %FALSE. * * Since: 2.8 **/ @@ -6946,11 +7222,8 @@ gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view, { g_return_if_fail (GTK_IS_ICON_VIEW (icon_view)); - gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, NULL, 0, actions); + gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions); - clear_dest_info (icon_view); - - icon_view->priv->dest_targets = gtk_target_list_new (targets, n_targets); icon_view->priv->dest_actions = actions; icon_view->priv->dest_set = TRUE; @@ -6962,7 +7235,8 @@ gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view, * gtk_icon_view_unset_model_drag_source: * @icon_view: a #GtkIconView * - * Undoes the effect of gtk_icon_view_enable_model_drag_source(). + * Undoes the effect of gtk_icon_view_enable_model_drag_source(). Calling this + * method sets #GtkIconView:reorderable to %FALSE. * * Since: 2.8 **/ @@ -6974,7 +7248,7 @@ gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view) if (icon_view->priv->source_set) { gtk_drag_source_unset (GTK_WIDGET (icon_view)); - clear_source_info (icon_view); + icon_view->priv->source_set = FALSE; } unset_reorderable (icon_view); @@ -6984,7 +7258,8 @@ gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view) * gtk_icon_view_unset_model_drag_dest: * @icon_view: a #GtkIconView * - * Undoes the effect of gtk_icon_view_enable_model_drag_dest(). + * Undoes the effect of gtk_icon_view_enable_model_drag_dest(). Calling this + * method sets #GtkIconView:reorderable to %FALSE. * * Since: 2.8 **/ @@ -6996,7 +7271,7 @@ gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view) if (icon_view->priv->dest_set) { gtk_drag_dest_unset (GTK_WIDGET (icon_view)); - clear_dest_info (icon_view); + icon_view->priv->dest_set = FALSE; } unset_reorderable (icon_view); @@ -7006,9 +7281,9 @@ gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view) /** * gtk_icon_view_set_drag_dest_item: * @icon_view: a #GtkIconView - * @path: The path of the item to highlight, or %NULL. + * @path: (allow-none): The path of the item to highlight, or %NULL. * @pos: Specifies where to drop, relative to the item - * + * * Sets the item that is highlighted for feedback. * * Since: 2.8 @@ -7037,7 +7312,7 @@ gtk_icon_view_set_drag_dest_item (GtkIconView *icon_view, /* special case a drop on an empty model */ icon_view->priv->empty_view_drop = FALSE; - if (pos == GTK_TREE_VIEW_DROP_BEFORE && path + if (pos == GTK_ICON_VIEW_DROP_ABOVE && path && gtk_tree_path_get_depth (path) == 1 && gtk_tree_path_get_indices (path)[0] == 0) { @@ -7065,8 +7340,8 @@ gtk_icon_view_set_drag_dest_item (GtkIconView *icon_view, /** * gtk_icon_view_get_drag_dest_item: * @icon_view: a #GtkIconView - * @path: Return location for the path of the highlighted item, or %NULL. - * @pos: Return location for the drop position, or %NULL + * @path: (allow-none): Return location for the path of the highlighted item, or %NULL. + * @pos: (allow-none): Return location for the drop position, or %NULL * * Gets information about the item that is highlighted for feedback. * @@ -7096,8 +7371,8 @@ gtk_icon_view_get_drag_dest_item (GtkIconView *icon_view, * @icon_view: a #GtkIconView * @drag_x: the position to determine the destination item for * @drag_y: the position to determine the destination item for - * @path: Return location for the path of the item, or %NULL. - * @pos: Return location for the drop position, or %NULL + * @path: (allow-none): Return location for the path of the item, or %NULL. + * @pos: (allow-none): Return location for the drop position, or %NULL * * Determines the destination item for a given position. * @@ -7160,30 +7435,29 @@ gtk_icon_view_get_dest_item_at_pos (GtkIconView *icon_view, * @icon_view: a #GtkIconView * @path: a #GtkTreePath in @icon_view * - * Creates a #GdkPixmap representation of the item at @path. + * Creates a #cairo_surface_t representation of the item at @path. * This image is used for a drag icon. * - * Return value: a newly-allocated pixmap of the drag icon. + * Return value: (transfer full) a newly-allocated surface of the drag icon. * * Since: 2.8 **/ -GdkPixmap * +cairo_surface_t * gtk_icon_view_create_drag_icon (GtkIconView *icon_view, GtkTreePath *path) { GtkWidget *widget; cairo_t *cr; - GdkPixmap *drawable; + cairo_surface_t *surface; GList *l; gint index; - GdkRectangle area; g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL); g_return_val_if_fail (path != NULL, NULL); widget = GTK_WIDGET (icon_view); - if (!GTK_WIDGET_REALIZED (widget)) + if (!gtk_widget_get_realized (widget)) return NULL; index = gtk_tree_path_get_indices (path)[0]; @@ -7194,26 +7468,26 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, if (index == item->index) { - drawable = gdk_pixmap_new (icon_view->priv->bin_window, - item->width + 2, - item->height + 2, - -1); + surface = gdk_window_create_similar_surface (icon_view->priv->bin_window, + CAIRO_CONTENT_COLOR, + item->width + 2, + item->height + 2); - cr = gdk_cairo_create (drawable); + cr = cairo_create (surface); cairo_set_line_width (cr, 1.); - gdk_cairo_set_source_color - (cr, &widget->style->base[GTK_WIDGET_STATE (widget)]); + gdk_cairo_set_source_color (cr, >k_widget_get_style (widget)->base[gtk_widget_get_state (widget)]); cairo_rectangle (cr, 0, 0, item->width + 2, item->height + 2); cairo_fill (cr); - area.x = 0; - area.y = 0; - area.width = item->width; - area.height = item->height; + cairo_save (cr); - gtk_icon_view_paint_item (icon_view, cr, item, &area, - drawable, 1, 1, FALSE); + cairo_rectangle (cr, 0, 0, item->width, item->height); + cairo_clip (cr); + + gtk_icon_view_paint_item (icon_view, cr, item, 1, 1, FALSE); + + cairo_restore (cr); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ cairo_rectangle (cr, 0.5, 0.5, item->width + 1, item->height + 1); @@ -7221,7 +7495,7 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, cairo_destroy (cr); - return drawable; + return surface; } } @@ -7262,7 +7536,9 @@ static const GtkTargetEntry item_targets[] = { * #GtkTreeStore and #GtkListStore support these. If @reorderable is %TRUE, then * the user can reorder the model by dragging and dropping rows. The * developer can listen to these changes by connecting to the model's - * row_inserted and row_deleted signals. + * row_inserted and row_deleted signals. The reordering is implemented by setting up + * the icon view as a drag source and destination. Therefore, drag and + * drop can not be used in a reorderable view for any other purpose. * * This function does not give you any degree of control over the order -- any * reordering is allowed. If more control is needed, you should probably @@ -7493,7 +7769,7 @@ gtk_icon_view_item_accessible_image_set_image_description (AtkImage *image, item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image); g_free (item->image_description); - item->image_description = g_strdup (item->image_description); + item->image_description = g_strdup (description); return TRUE; } @@ -8292,7 +8568,7 @@ gtk_icon_view_item_accessible_grab_focus (AtkComponent *component) gtk_widget_grab_focus (item->widget); gtk_icon_view_set_cursor_item (GTK_ICON_VIEW (item->widget), item->item, -1); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->widget)); - if (GTK_WIDGET_TOPLEVEL (toplevel)) + if (gtk_widget_is_toplevel (toplevel)) gtk_window_present (GTK_WINDOW (toplevel)); return TRUE; @@ -8363,6 +8639,7 @@ gtk_icon_view_item_accessible_remove_state (GtkIconViewItemAccessible *item, static gboolean gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item) { + GtkAllocation allocation; GtkIconView *icon_view; GdkRectangle visible_rect; gboolean is_showing; @@ -8378,6 +8655,8 @@ gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item) if (item->item == NULL) return FALSE; + gtk_widget_get_allocation (item->widget, &allocation); + icon_view = GTK_ICON_VIEW (item->widget); visible_rect.x = 0; if (icon_view->priv->hadjustment) @@ -8385,8 +8664,8 @@ gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item) visible_rect.y = 0; if (icon_view->priv->hadjustment) visible_rect.y += icon_view->priv->vadjustment->value; - visible_rect.width = item->widget->allocation.width; - visible_rect.height = item->widget->allocation.height; + visible_rect.width = allocation.width; + visible_rect.height = allocation.height; if (((item->item->x + item->item->width) < visible_rect.x) || ((item->item->y + item->item->height) < (visible_rect.y)) || @@ -8573,25 +8852,25 @@ gtk_icon_view_item_accessible_get_type (void) NULL /* value table */ }; - static const GInterfaceInfo atk_component_info = + const GInterfaceInfo atk_component_info = { (GInterfaceInitFunc) atk_component_item_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; - static const GInterfaceInfo atk_action_info = + const GInterfaceInfo atk_action_info = { (GInterfaceInitFunc) atk_action_item_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; - static const GInterfaceInfo atk_image_info = + const GInterfaceInfo atk_image_info = { (GInterfaceInitFunc) atk_image_item_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; - static const GInterfaceInfo atk_text_info = + const GInterfaceInfo atk_text_info = { (GInterfaceInitFunc) atk_text_item_interface_init, (GInterfaceFinalizeFunc) NULL, @@ -8682,7 +8961,7 @@ gtk_icon_view_accessible_get_n_children (AtkObject *accessible) GtkIconView *icon_view; GtkWidget *widget; - widget = GTK_ACCESSIBLE (accessible)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) return 0; @@ -8722,7 +9001,7 @@ gtk_icon_view_accessible_ref_child (AtkObject *accessible, AtkObject *obj; GtkIconViewItemAccessible *a11y_item; - widget = GTK_ACCESSIBLE (accessible)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); if (!widget) return NULL; @@ -8780,7 +9059,7 @@ gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view, GtkWidget *widget; gboolean act_on_item; - widget = GTK_ACCESSIBLE (view)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (view)); if (widget == NULL) return; @@ -8882,11 +9161,44 @@ static void gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, - gpointer user_data) + gpointer user_data) { AtkObject *atk_obj; + gint index; + GtkWidget *widget; + GtkIconView *icon_view; + GtkIconViewItem *item; + GtkIconViewAccessible *a11y_view; + GtkIconViewItemAccessible *a11y_item; + const gchar *name; + gchar *text; atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data)); + a11y_view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj); + index = gtk_tree_path_get_indices(path)[0]; + a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE ( + gtk_icon_view_accessible_find_child (atk_obj, index)); + + if (a11y_item) + { + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj)); + icon_view = GTK_ICON_VIEW (widget); + item = a11y_item->item; + + name = gtk_icon_view_item_accessible_get_name (ATK_OBJECT (a11y_item)); + + if (!name || strcmp (name, "") == 0) + { + gtk_icon_view_set_cell_data (icon_view, item); + text = get_text (icon_view, item); + if (text) + { + gtk_text_buffer_set_text (a11y_item->text_buffer, text, -1); + g_free (text); + } + } + } + g_signal_emit_by_name (atk_obj, "visible-data-changed"); return; @@ -9013,20 +9325,29 @@ gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model, GtkIconViewItemAccessible *item; GList *items; AtkObject *atk_obj; + gint *order; + gint length, i; atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data)); icon_view = GTK_ICON_VIEW (user_data); priv = gtk_icon_view_accessible_get_priv (atk_obj); + length = gtk_tree_model_iter_n_children (tree_model, NULL); + + order = g_new (gint, length); + for (i = 0; i < length; i++) + order [new_order[i]] = i; + items = priv->items; while (items) { info = items->data; item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item); - info->index = new_order[info->index]; + info->index = order[info->index]; item->item = g_list_nth_data (icon_view->priv->items, info->index); items = items->next; } + g_free (order); priv->items = g_list_sort (priv->items, (GCompareFunc)gtk_icon_view_accessible_item_compare); @@ -9219,9 +9540,12 @@ gtk_icon_view_accessible_destroyed (GtkWidget *widget, static void gtk_icon_view_accessible_connect_widget_destroyed (GtkAccessible *accessible) { - if (accessible->widget) + GtkWidget *widget; + + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); + if (widget) { - g_signal_connect_after (accessible->widget, + g_signal_connect_after (widget, "destroy", G_CALLBACK (gtk_icon_view_accessible_destroyed), accessible); @@ -9262,7 +9586,7 @@ gtk_icon_view_accessible_ref_accessible_at_point (AtkComponent *component, GtkIconViewItem *item; gint x_pos, y_pos; - widget = GTK_ACCESSIBLE (component)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component)); if (widget == NULL) /* State is defunct */ return NULL; @@ -9290,7 +9614,7 @@ gtk_icon_view_accessible_add_selection (AtkSelection *selection, GtkIconView *icon_view; GtkIconViewItem *item; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return FALSE; @@ -9312,7 +9636,7 @@ gtk_icon_view_accessible_clear_selection (AtkSelection *selection) GtkWidget *widget; GtkIconView *icon_view; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return FALSE; @@ -9331,7 +9655,7 @@ gtk_icon_view_accessible_ref_selection (AtkSelection *selection, GtkIconView *icon_view; GtkIconViewItem *item; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return NULL; @@ -9363,7 +9687,7 @@ gtk_icon_view_accessible_get_selection_count (AtkSelection *selection) GList *l; gint count; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return 0; @@ -9392,7 +9716,7 @@ gtk_icon_view_accessible_is_child_selected (AtkSelection *selection, GtkIconView *icon_view; GtkIconViewItem *item; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return FALSE; @@ -9415,7 +9739,7 @@ gtk_icon_view_accessible_remove_selection (AtkSelection *selection, GList *l; gint count; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return FALSE; @@ -9446,7 +9770,7 @@ gtk_icon_view_accessible_select_all_selection (AtkSelection *selection) GtkWidget *widget; GtkIconView *icon_view; - widget = GTK_ACCESSIBLE (selection)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection)); if (widget == NULL) return FALSE; @@ -9474,7 +9798,7 @@ gtk_icon_view_accessible_get_type (void) if (!type) { - static GTypeInfo tinfo = + GTypeInfo tinfo = { 0, /* class size */ (GBaseInitFunc) NULL, /* base init */ @@ -9487,13 +9811,13 @@ gtk_icon_view_accessible_get_type (void) (GInstanceInitFunc) NULL, /* instance init */ NULL /* value table */ }; - static const GInterfaceInfo atk_component_info = + const GInterfaceInfo atk_component_info = { (GInterfaceInitFunc) atk_component_interface_init, (GInterfaceFinalizeFunc) NULL, NULL }; - static const GInterfaceInfo atk_selection_info = + const GInterfaceInfo atk_selection_info = { (GInterfaceInitFunc) gtk_icon_view_accessible_selection_interface_init, (GInterfaceFinalizeFunc) NULL, @@ -9650,8 +9974,3 @@ gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable, parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname, data); } - - - -#define __GTK_ICON_VIEW_C__ -#include "gtkaliasdef.c"