X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkiconview.c;h=e4da1a0939f41cf2930cc63b27689e7c499729ac;hb=23ce44c9fecefb9c243c09709c8c1decfd1eb530;hp=24718bdb59b4b30ae3b0750ae2f78764bbb1c4a0;hpb=e082783fbbe61ae2592dfb24f52569a05bc05c4d;p=~andy%2Fgtk diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 24718bdb5..e4da1a093 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -39,15 +39,32 @@ #include "gtkentry.h" #include "gtkcombobox.h" #include "gtktextbuffer.h" +#include "gtkscrollable.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 #GtkTreeModel. + * 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. + * + * Note that if the tree model is backed by an actual tree store (as + * opposed to a flat list where the mapping to icons is obvious), + * #GtkIconView will only display the first level of the tree and + * ignore the tree's branches. + */ #define SCROLL_EDGE_SIZE 15 -#define GTK_ICON_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ICON_VIEW, GtkIconViewPrivate)) +#define GTK_ICON_VIEW_PRIORITY_LAYOUT (GDK_PRIORITY_REDRAW + 5) typedef struct _GtkIconViewItem GtkIconViewItem; struct _GtkIconViewItem @@ -124,6 +141,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; @@ -141,7 +159,7 @@ struct _GtkIconViewPrivate gint cursor_cell; - GtkOrientation orientation; + GtkOrientation item_orientation; gint columns; gint item_width; @@ -187,6 +205,11 @@ struct _GtkIconViewPrivate guint shift_pressed : 1; guint draw_focus : 1; + + /* GtkScrollablePolicy needs to be checked when + * driving the scrollable adjustment values */ + guint hscroll_policy : 1; + guint vscroll_policy : 1; }; /* Signals */ @@ -209,9 +232,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 +244,13 @@ enum PROP_MARGIN, PROP_REORDERABLE, PROP_TOOLTIP_COLUMN, - PROP_ITEM_PADDING + PROP_ITEM_PADDING, + + /* For scrollable interface */ + PROP_HADJUSTMENT, + PROP_VADJUSTMENT, + PROP_HSCROLL_POLICY, + PROP_VSCROLL_POLICY }; /* GObject vfuncs */ @@ -235,23 +264,24 @@ 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, GtkStyle *previous_style); static void gtk_icon_view_state_changed (GtkWidget *widget, GtkStateType previous_state); -static void gtk_icon_view_size_request (GtkWidget *widget, - GtkRequisition *requisition); +static void gtk_icon_view_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void gtk_icon_view_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); 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, @@ -274,9 +304,6 @@ static void gtk_icon_view_forall (GtkContainer gpointer callback_data); /* GtkIconView vfuncs */ -static void gtk_icon_view_set_adjustments (GtkIconView *icon_view, - GtkAdjustment *hadj, - GtkAdjustment *vadj); static void gtk_icon_view_real_select_all (GtkIconView *icon_view); static void gtk_icon_view_real_unselect_all (GtkIconView *icon_view); static void gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view); @@ -284,21 +311,26 @@ static void gtk_icon_view_real_toggle_cursor_item (GtkIconView static gboolean gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view); /* Internal functions */ +static void gtk_icon_view_set_hadjustment_values (GtkIconView *icon_view); +static void gtk_icon_view_set_vadjustment_values (GtkIconView *icon_view); +static void gtk_icon_view_set_hadjustment (GtkIconView *icon_view, + GtkAdjustment *adjustment); +static void gtk_icon_view_set_vadjustment (GtkIconView *icon_view, + GtkAdjustment *adjustment); +static void gtk_icon_view_accessible_set_adjustment (AtkObject *accessible, + GtkOrientation orientation, + GtkAdjustment *adjustment); static void gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment, 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 +340,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); @@ -474,13 +507,13 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT, gtk_icon_view_cell_layout_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, - gtk_icon_view_buildable_init)) + gtk_icon_view_buildable_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL)) static void gtk_icon_view_class_init (GtkIconViewClass *klass) { GObjectClass *gobject_class; - GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; GtkBindingSet *binding_set; @@ -490,7 +523,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; @@ -498,15 +530,15 @@ 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->get_preferred_width = gtk_icon_view_get_preferred_width; + widget_class->get_preferred_height = gtk_icon_view_get_preferred_height; 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; @@ -525,7 +557,6 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) container_class->remove = gtk_icon_view_remove; container_class->forall = gtk_icon_view_forall; - klass->set_scroll_adjustments = gtk_icon_view_set_adjustments; klass->select_all = gtk_icon_view_real_select_all; klass->unselect_all = gtk_icon_view_real_unselect_all; klass->select_cursor_item = gtk_icon_view_real_select_cursor_item; @@ -716,17 +747,17 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) 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, @@ -774,7 +805,11 @@ gtk_icon_view_class_init (GtkIconViewClass *klass) 0, G_MAXINT, 6, GTK_PARAM_READWRITE)); - + /* Scrollable interface properties */ + g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment"); + g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment"); + g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy"); + g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy"); /* Style properties */ gtk_widget_class_install_style_property (widget_class, @@ -793,25 +828,6 @@ 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), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GtkIconViewClass, set_scroll_adjustments), - NULL, NULL, - _gtk_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT); - /** * GtkIconView::item-activated: * @iconview: the object on which the signal is emitted @@ -999,70 +1015,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); } @@ -1091,8 +1107,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; @@ -1108,13 +1126,11 @@ gtk_icon_view_init (GtkIconView *icon_view) gtk_widget_set_can_focus (GTK_WIDGET (icon_view), TRUE); - gtk_icon_view_set_adjustments (icon_view, NULL, NULL); - icon_view->priv->cell_list = NULL; 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; @@ -1127,46 +1143,6 @@ gtk_icon_view_init (GtkIconView *icon_view) icon_view->priv->draw_focus = TRUE; } -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; - } - - GTK_OBJECT_CLASS (gtk_icon_view_parent_class)->destroy (object); -} - /* GObject methods */ static void gtk_icon_view_finalize (GObject *object) @@ -1204,8 +1180,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)); @@ -1237,6 +1213,21 @@ gtk_icon_view_set_property (GObject *object, gtk_icon_view_set_item_padding (icon_view, g_value_get_int (value)); break; + case PROP_HADJUSTMENT: + gtk_icon_view_set_hadjustment (icon_view, g_value_get_object (value)); + break; + case PROP_VADJUSTMENT: + gtk_icon_view_set_vadjustment (icon_view, g_value_get_object (value)); + break; + case PROP_HSCROLL_POLICY: + icon_view->priv->hscroll_policy = g_value_get_enum (value); + gtk_widget_queue_resize (GTK_WIDGET (icon_view)); + break; + case PROP_VSCROLL_POLICY: + icon_view->priv->vscroll_policy = g_value_get_enum (value); + gtk_widget_queue_resize (GTK_WIDGET (icon_view)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1270,8 +1261,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); @@ -1302,47 +1293,101 @@ gtk_icon_view_get_property (GObject *object, g_value_set_int (value, icon_view->priv->item_padding); break; + case PROP_HADJUSTMENT: + g_value_set_object (value, icon_view->priv->hadjustment); + break; + case PROP_VADJUSTMENT: + g_value_set_object (value, icon_view->priv->vadjustment); + break; + case PROP_HSCROLL_POLICY: + g_value_set_enum (value, icon_view->priv->hscroll_policy); + break; + case PROP_VSCROLL_POLICY: + g_value_set_enum (value, icon_view->priv->vscroll_policy); + 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_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; - 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); + window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gtk_widget_set_window (widget, window); + gdk_window_set_user_data (window, widget); + + gtk_widget_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 | @@ -1352,12 +1397,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); } @@ -1381,11 +1427,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_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); @@ -1396,38 +1447,35 @@ gtk_icon_view_style_set (GtkWidget *widget, GtkStyle *previous_style) { GtkIconView *icon_view = GTK_ICON_VIEW (widget); + GtkStateType state; + GtkStyle *style; 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); } static void -gtk_icon_view_size_request (GtkWidget *widget, - GtkRequisition *requisition) +gtk_icon_view_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) { - GtkIconView *icon_view = GTK_ICON_VIEW (widget); - GList *tmp_list; - - requisition->width = icon_view->priv->width; - requisition->height = icon_view->priv->height; - - tmp_list = icon_view->priv->children; - - while (tmp_list) - { - GtkIconViewChild *child = tmp_list->data; - GtkRequisition child_requisition; - - tmp_list = tmp_list->next; + *minimum = *natural = GTK_ICON_VIEW (widget)->priv->width; +} - if (gtk_widget_get_visible (child->widget)) - gtk_widget_size_request (child->widget, &child_requisition); - } +static void +gtk_icon_view_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + *minimum = *natural = GTK_ICON_VIEW (widget)->priv->height; } static void @@ -1468,13 +1516,11 @@ gtk_icon_view_size_allocate (GtkWidget *widget, { GtkIconView *icon_view = GTK_ICON_VIEW (widget); - GtkAdjustment *hadjustment, *vadjustment; + gtk_widget_set_allocation (widget, allocation); - widget->allocation = *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, @@ -1486,26 +1532,12 @@ gtk_icon_view_size_allocate (GtkWidget *widget, gtk_icon_view_allocate_children (icon_view); - hadjustment = icon_view->priv->hadjustment; - vadjustment = icon_view->priv->vadjustment; - - hadjustment->page_size = allocation->width; - hadjustment->page_increment = allocation->width * 0.9; - hadjustment->step_increment = allocation->width * 0.1; - hadjustment->lower = 0; - hadjustment->upper = MAX (allocation->width, icon_view->priv->width); - - if (hadjustment->value > hadjustment->upper - hadjustment->page_size) - gtk_adjustment_set_value (hadjustment, MAX (0, hadjustment->upper - hadjustment->page_size)); - - vadjustment->page_size = allocation->height; - vadjustment->page_increment = allocation->height * 0.9; - vadjustment->step_increment = allocation->height * 0.1; - vadjustment->lower = 0; - vadjustment->upper = MAX (allocation->height, icon_view->priv->height); + /* Delay signal emission */ + g_object_freeze_notify (G_OBJECT (icon_view->priv->hadjustment)); + g_object_freeze_notify (G_OBJECT (icon_view->priv->vadjustment)); - if (vadjustment->value > vadjustment->upper - vadjustment->page_size) - gtk_adjustment_set_value (vadjustment, MAX (0, vadjustment->upper - vadjustment->page_size)); + gtk_icon_view_set_hadjustment_values (icon_view); + gtk_icon_view_set_vadjustment_values (icon_view); if (gtk_widget_get_realized (widget) && icon_view->priv->scroll_to_path) @@ -1521,20 +1553,18 @@ gtk_icon_view_size_allocate (GtkWidget *widget, icon_view->priv->scroll_to_col_align); gtk_tree_path_free (path); } - else - { - gtk_adjustment_changed (hadjustment); - gtk_adjustment_changed (vadjustment); - } + + /* Emit any pending signals now */ + g_object_thaw_notify (G_OBJECT (icon_view->priv->hadjustment)); + g_object_thaw_notify (G_OBJECT (icon_view->priv->vadjustment)); } 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; @@ -1542,15 +1572,13 @@ 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; - /* 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_save (cr); - cr = gdk_cairo_create (icon_view->priv->bin_window); + gtk_cairo_transform_to_window (cr, widget, icon_view->priv->bin_window); + cairo_set_line_width (cr, 1.); gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos); @@ -1566,101 +1594,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, - icon_view->priv->draw_focus); - - 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]); + gtk_icon_view_paint_rubberband (icon_view, cr); - g_free (rectangles); - } - - 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; } @@ -1668,17 +1685,11 @@ gtk_icon_view_expose (GtkWidget *widget, static gboolean rubberband_scroll_timeout (gpointer data) { - GtkIconView *icon_view; - gdouble value; - - icon_view = data; - - value = MIN (icon_view->priv->vadjustment->value + - icon_view->priv->scroll_value_diff, - icon_view->priv->vadjustment->upper - - icon_view->priv->vadjustment->page_size); + GtkIconView *icon_view = data; - gtk_adjustment_set_value (icon_view->priv->vadjustment, value); + gtk_adjustment_set_value (icon_view->priv->vadjustment, + icon_view->priv->vadjustment->value + + icon_view->priv->scroll_value_diff); gtk_icon_view_update_rubberband (icon_view); @@ -1689,6 +1700,7 @@ static gboolean gtk_icon_view_motion (GtkWidget *widget, GdkEventMotion *event) { + GtkAllocation allocation; GtkIconView *icon_view; gint abs_y; @@ -1705,12 +1717,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; @@ -2223,7 +2237,7 @@ 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 */ @@ -2282,7 +2296,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; @@ -2311,11 +2325,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); @@ -2334,13 +2350,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; @@ -2348,15 +2364,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; @@ -2366,12 +2382,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) { @@ -2386,8 +2404,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 @@ -2396,10 +2415,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)); } @@ -2461,7 +2482,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); @@ -2501,62 +2522,6 @@ gtk_icon_view_unselect_all_internal (GtkIconView *icon_view) /* GtkIconView signals */ -static void -gtk_icon_view_set_adjustments (GtkIconView *icon_view, - GtkAdjustment *hadj, - GtkAdjustment *vadj) -{ - gboolean need_adjust = FALSE; - - 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)); - 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)); - - if (icon_view->priv->hadjustment && (icon_view->priv->hadjustment != hadj)) - { - g_signal_handlers_disconnect_matched (icon_view->priv->hadjustment, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, icon_view); - g_object_unref (icon_view->priv->hadjustment); - } - - if (icon_view->priv->vadjustment && (icon_view->priv->vadjustment != vadj)) - { - g_signal_handlers_disconnect_matched (icon_view->priv->vadjustment, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, icon_view); - g_object_unref (icon_view->priv->vadjustment); - } - - if (icon_view->priv->hadjustment != hadj) - { - icon_view->priv->hadjustment = hadj; - g_object_ref_sink (icon_view->priv->hadjustment); - - g_signal_connect (icon_view->priv->hadjustment, "value-changed", - G_CALLBACK (gtk_icon_view_adjustment_changed), - icon_view); - need_adjust = TRUE; - } - - if (icon_view->priv->vadjustment != vadj) - { - icon_view->priv->vadjustment = vadj; - g_object_ref_sink (icon_view->priv->vadjustment); - - g_signal_connect (icon_view->priv->vadjustment, "value-changed", - G_CALLBACK (gtk_icon_view_adjustment_changed), - icon_view); - need_adjust = TRUE; - } - - if (need_adjust) - gtk_icon_view_adjustment_changed (NULL, icon_view); -} - static void gtk_icon_view_real_select_all (GtkIconView *icon_view) { @@ -2648,20 +2613,181 @@ gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view) } /* Internal functions */ +static void +gtk_icon_view_process_updates (GtkIconView *icon_view) +{ + /* Prior to drawing, we check if a layout has been scheduled. If so, + * do it now that all cell view items have valid sizes before we proceeed + * (and resize the bin_window if required). + */ + if (icon_view->priv->layout_idle_id != 0) + gtk_icon_view_layout (icon_view); + + gdk_window_process_updates (icon_view->priv->bin_window, TRUE); +} + +static void +gtk_icon_view_set_hadjustment_values (GtkIconView *icon_view) +{ + GtkAllocation allocation; + GtkAdjustment *adj = icon_view->priv->hadjustment; + gdouble old_page_size; + gdouble old_upper; + gdouble old_value; + gdouble new_value; + gdouble new_upper; + + gtk_widget_get_allocation (GTK_WIDGET (icon_view), &allocation); + + old_value = gtk_adjustment_get_value (adj); + old_upper = gtk_adjustment_get_upper (adj); + old_page_size = gtk_adjustment_get_page_size (adj); + new_upper = MAX (allocation.width, icon_view->priv->width); + + g_object_set (adj, + "lower", 0.0, + "upper", new_upper, + "page-size", (gdouble)allocation.width, + "step-increment", allocation.width * 0.1, + "page-increment", allocation.width * 0.9, + NULL); + + if (gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL) + { + /* Make sure no scrolling occurs for RTL locales also (if possible) */ + /* Quick explanation: + * In LTR locales, leftmost portion of visible rectangle should stay + * fixed, which means left edge of scrollbar thumb should remain fixed + * and thus adjustment's value should stay the same. + * + * In RTL locales, we want to keep rightmost portion of visible + * rectangle fixed. This means right edge of thumb should remain fixed. + * In this case, upper - value - page_size should remain constant. + */ + new_value = (new_upper - allocation.width) - + (old_upper - old_value - old_page_size); + new_value = CLAMP (new_value, 0, new_upper - allocation.width); + } + else + new_value = CLAMP (old_value, 0, new_upper - allocation.width); + + if (new_value != old_value) + gtk_adjustment_set_value (adj, new_value); +} + +static void +gtk_icon_view_set_vadjustment_values (GtkIconView *icon_view) +{ + GtkAllocation allocation; + GtkAdjustment *adj = icon_view->priv->vadjustment; + gdouble old_value; + gdouble new_value; + gdouble new_upper; + + gtk_widget_get_allocation (GTK_WIDGET (icon_view), &allocation); + + old_value = gtk_adjustment_get_value (adj); + new_upper = MAX (allocation.height, icon_view->priv->height); + + g_object_set (adj, + "lower", 0.0, + "upper", new_upper, + "page-size", (gdouble)allocation.height, + "step-increment", allocation.height * 0.1, + "page-increment", allocation.height * 0.9, + NULL); + + new_value = CLAMP (old_value, 0, new_upper - allocation.height); + if (new_value != old_value) + gtk_adjustment_set_value (adj, new_value); +} + +static void +gtk_icon_view_set_hadjustment (GtkIconView *icon_view, + GtkAdjustment *adjustment) +{ + GtkIconViewPrivate *priv = icon_view->priv; + AtkObject *atk_obj; + + if (adjustment && priv->hadjustment == adjustment) + return; + + if (priv->hadjustment != NULL) + { + g_signal_handlers_disconnect_matched (priv->hadjustment, + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, icon_view); + g_object_unref (priv->hadjustment); + } + + if (!adjustment) + adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, + 0.0, 0.0, 0.0); + + g_signal_connect (adjustment, "value-changed", + G_CALLBACK (gtk_icon_view_adjustment_changed), icon_view); + priv->hadjustment = g_object_ref_sink (adjustment); + gtk_icon_view_set_hadjustment_values (icon_view); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view)); + gtk_icon_view_accessible_set_adjustment (atk_obj, + GTK_ORIENTATION_HORIZONTAL, + adjustment); + + g_object_notify (G_OBJECT (icon_view), "hadjustment"); +} + +static void +gtk_icon_view_set_vadjustment (GtkIconView *icon_view, + GtkAdjustment *adjustment) +{ + GtkIconViewPrivate *priv = icon_view->priv; + AtkObject *atk_obj; + + if (adjustment && priv->vadjustment == adjustment) + return; + + if (priv->vadjustment != NULL) + { + g_signal_handlers_disconnect_matched (priv->vadjustment, + G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, icon_view); + g_object_unref (priv->vadjustment); + } + + if (!adjustment) + adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, + 0.0, 0.0, 0.0); + + g_signal_connect (adjustment, "value-changed", + G_CALLBACK (gtk_icon_view_adjustment_changed), icon_view); + priv->vadjustment = g_object_ref_sink (adjustment); + gtk_icon_view_set_vadjustment_values (icon_view); + + atk_obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view)); + gtk_icon_view_accessible_set_adjustment (atk_obj, + GTK_ORIENTATION_VERTICAL, + adjustment); + + g_object_notify (G_OBJECT (icon_view), "vadjustment"); +} + static void gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment, - GtkIconView *icon_view) + GtkIconView *icon_view) { + GtkIconViewPrivate *priv = icon_view->priv; + if (gtk_widget_get_realized (GTK_WIDGET (icon_view))) { - gdk_window_move (icon_view->priv->bin_window, - - icon_view->priv->hadjustment->value, - - icon_view->priv->vadjustment->value); + gdk_window_move (priv->bin_window, + - priv->hadjustment->value, + - priv->vadjustment->value); if (icon_view->priv->doing_rubberband) - gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view)); + gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view)); - gdk_window_process_updates (icon_view->priv->bin_window, TRUE); + gtk_icon_view_process_updates (icon_view); } } @@ -2673,6 +2799,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; @@ -2682,7 +2810,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; @@ -2690,7 +2818,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); @@ -2711,7 +2839,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; } @@ -2788,11 +2918,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) { @@ -2838,26 +2970,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); + 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) { @@ -2885,7 +3023,7 @@ 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 + icon_view->priv->item_padding; @@ -2922,37 +3060,35 @@ 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 (icon_view->priv->orientation == GTK_ORIENTATION_VERTICAL) + 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 * pixbuf_width, 50); + wrap_width = MAX (2 * min_size.width, 50); else - wrap_width = item_width - pixbuf_width - icon_view->priv->spacing; + wrap_width = item_width - min_size.width - icon_view->priv->spacing; } wrap_width -= icon_view->priv->item_padding * 2; @@ -2966,6 +3102,7 @@ static void gtk_icon_view_calculate_item_size (GtkIconView *icon_view, GtkIconViewItem *item) { + GtkRequisition min_size; gint spacing; GList *l; @@ -2995,15 +3132,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); @@ -3025,6 +3163,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; @@ -3040,7 +3179,7 @@ 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); @@ -3053,14 +3192,14 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, 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 icon_view->priv->item_padding from item->height, * because item->height is recalculated above using @@ -3077,15 +3216,21 @@ gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view, 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]; @@ -3104,7 +3249,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++) { @@ -3134,8 +3279,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) @@ -3147,13 +3290,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); @@ -3162,7 +3308,7 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, if (item->selected) { flags = GTK_CELL_RENDERER_SELECTED; - if (gtk_widget_has_focus (GTK_WIDGET (icon_view))) + if (gtk_widget_has_focus (widget)) state = GTK_STATE_SELECTED; else state = GTK_STATE_ACTIVE; @@ -3172,89 +3318,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 (GTK_WIDGET (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, @@ -3268,11 +3388,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, @@ -3283,21 +3402,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, @@ -3305,31 +3421,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 @@ -3393,7 +3501,9 @@ gtk_icon_view_queue_layout (GtkIconView *icon_view) if (icon_view->priv->layout_idle_id != 0) return; - icon_view->priv->layout_idle_id = gdk_threads_add_idle (layout_callback, icon_view); + icon_view->priv->layout_idle_id = + gdk_threads_add_idle_full (GTK_ICON_VIEW_PRIORITY_LAYOUT, + layout_callback, icon_view, NULL); } static void @@ -3492,7 +3602,7 @@ gtk_icon_view_get_item_at_coords (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); @@ -3592,11 +3702,13 @@ gtk_icon_view_row_changed (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { + GtkIconView *icon_view = GTK_ICON_VIEW (data); GtkIconViewItem *item; gint index; - GtkIconView *icon_view; - icon_view = GTK_ICON_VIEW (data); + /* ignore changes in branches */ + if (gtk_tree_path_get_depth (path) > 1) + return; gtk_icon_view_stop_editing (icon_view, TRUE); @@ -3615,13 +3727,15 @@ gtk_icon_view_row_inserted (GtkTreeModel *model, GtkTreeIter *iter, gpointer data) { + GtkIconView *icon_view = GTK_ICON_VIEW (data); gint index; GtkIconViewItem *item; gboolean iters_persist; - GtkIconView *icon_view; GList *list; - - icon_view = GTK_ICON_VIEW (data); + + /* ignore changes in branches */ + if (gtk_tree_path_get_depth (path) > 1) + return; iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST; @@ -3659,13 +3773,15 @@ gtk_icon_view_row_deleted (GtkTreeModel *model, GtkTreePath *path, gpointer data) { + GtkIconView *icon_view = GTK_ICON_VIEW (data); gint index; - GtkIconView *icon_view; GtkIconViewItem *item; GList *list, *next; gboolean emit = FALSE; - - icon_view = GTK_ICON_VIEW (data); + + /* ignore changes in branches */ + if (gtk_tree_path_get_depth (path) > 1) + return; index = gtk_tree_path_get_indices(path)[0]; @@ -3709,14 +3825,16 @@ gtk_icon_view_rows_reordered (GtkTreeModel *model, gint *new_order, gpointer data) { + GtkIconView *icon_view = GTK_ICON_VIEW (data); int i; int length; - GtkIconView *icon_view; GList *items = NULL, *list; GtkIconViewItem **item_array; gint *order; - - icon_view = GTK_ICON_VIEW (data); + + /* ignore changes in branches */ + if (iter != NULL) + return; gtk_icon_view_stop_editing (icon_view, TRUE); @@ -3907,7 +4025,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); @@ -3919,15 +4037,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; @@ -4080,10 +4200,13 @@ gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view, gint cell; gboolean dirty = FALSE; gint step; - + 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; @@ -4116,7 +4239,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; } @@ -4206,10 +4338,13 @@ gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view, gint cell = -1; gboolean dirty = FALSE; gint step; - + 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; @@ -4241,7 +4376,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; } @@ -4348,18 +4492,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 (!item || item->width < 0 || - !gtk_widget_get_realized (GTK_WIDGET (icon_view))) + !gtk_widget_get_realized (widget)) { if (icon_view->priv->scroll_to_path) gtk_tree_row_reference_free (icon_view->priv->scroll_to_path); @@ -4378,29 +4525,28 @@ gtk_icon_view_scroll_to_path (GtkIconView *icon_view, if (use_align) { + GtkAllocation allocation; gint x, y; gint focus_width; - gfloat offset, value; + 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); - value = CLAMP (icon_view->priv->vadjustment->value + offset, - icon_view->priv->vadjustment->lower, - icon_view->priv->vadjustment->upper - icon_view->priv->vadjustment->page_size); - gtk_adjustment_set_value (icon_view->priv->vadjustment, value); - - offset = x + item->x - focus_width - - col_align * (GTK_WIDGET (icon_view)->allocation.width - item->width); - value = CLAMP (icon_view->priv->hadjustment->value + offset, - icon_view->priv->hadjustment->lower, - icon_view->priv->hadjustment->upper - icon_view->priv->hadjustment->page_size); - gtk_adjustment_set_value (icon_view->priv->hadjustment, value); + + 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 * (allocation.width - item->width); + + gtk_adjustment_set_value (icon_view->priv->hadjustment, + icon_view->priv->hadjustment->value + offset); gtk_adjustment_changed (icon_view->priv->hadjustment); gtk_adjustment_changed (icon_view->priv->vadjustment); @@ -4414,32 +4560,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); @@ -4964,9 +5114,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: (allow-none): a pointer to receive a #GtkTreeModel or %NULL - * @path: (allow-none): a pointer to receive a #GtkTreePath or %NULL - * @iter: (allow-none): 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 @@ -5081,6 +5231,9 @@ gtk_icon_view_set_tooltip_query_cb (GtkWidget *widget, * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and * @icon_view will connect a #GtkWidget::query-tooltip signal handler. * + * Note that the signal handler sets the text with gtk_tooltip_set_markup(), + * so &, <, etc have to be escaped in the text. + * * Since: 2.12 */ void @@ -5192,7 +5345,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 @@ -5297,8 +5450,6 @@ gtk_icon_view_set_model (GtkIconView *icon_view, if (model) { GType column_type; - - g_return_if_fail (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY); if (icon_view->priv->pixbuf_column != -1) { @@ -5393,7 +5544,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 **/ @@ -5462,11 +5614,11 @@ 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, - "xalign", 0.0, + "xalign", 0.5, "yalign", 0.0, NULL); else @@ -5474,7 +5626,7 @@ update_text_cell (GtkIconView *icon_view) "alignment", PANGO_ALIGN_LEFT, "wrap-mode", PANGO_WRAP_WORD_CHAR, "xalign", 0.0, - "yalign", 0.0, + "yalign", 0.5, NULL); } } @@ -5530,7 +5682,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, @@ -5917,6 +6069,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 @@ -5937,24 +6151,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); @@ -5963,15 +6177,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 @@ -5979,12 +6193,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; } /** @@ -6483,12 +6697,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; - gfloat value; - 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); /* see if we are near the edge. */ voffset = py - (y + 2 * SCROLL_EDGE_SIZE); @@ -6500,19 +6716,12 @@ gtk_icon_view_autoscroll (GtkIconView *icon_view) hoffset = MAX (px - (x + width - 2 * SCROLL_EDGE_SIZE), 0); if (voffset != 0) - { - value = CLAMP (icon_view->priv->vadjustment->value + voffset, - icon_view->priv->vadjustment->lower, - icon_view->priv->vadjustment->upper - icon_view->priv->vadjustment->page_size); - gtk_adjustment_set_value (icon_view->priv->vadjustment, value); - } + gtk_adjustment_set_value (icon_view->priv->vadjustment, + icon_view->priv->vadjustment->value + voffset); + if (hoffset != 0) - { - value = CLAMP (icon_view->priv->hadjustment->value + hoffset, - icon_view->priv->hadjustment->lower, - icon_view->priv->hadjustment->upper - icon_view->priv->hadjustment->page_size); - gtk_adjustment_set_value (icon_view->priv->hadjustment, value); - } + gtk_adjustment_set_value (icon_view->priv->hadjustment, + icon_view->priv->hadjustment->value + hoffset); } @@ -6616,7 +6825,7 @@ out: { GtkWidget *source_widget; - *suggested_action = context->suggested_action; + *suggested_action = gdk_drag_context_get_suggested_action (context); source_widget = gtk_drag_get_source_widget (context); if (source_widget == widget) @@ -6624,7 +6833,7 @@ out: /* Default to MOVE, unless the user has * pressed ctrl or shift to affect available actions */ - if ((context->actions & GDK_ACTION_MOVE) != 0) + if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0) *suggested_action = GDK_ACTION_MOVE; } @@ -6752,7 +6961,7 @@ gtk_icon_view_drag_begin (GtkWidget *widget, { GtkIconView *icon_view; GtkIconViewItem *item; - GdkPixmap *icon; + cairo_surface_t *icon; gint x, y; GtkTreePath *path; @@ -6777,13 +6986,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 @@ -6830,7 +7037,7 @@ gtk_icon_view_drag_data_get (GtkWidget *widget, goto done; /* If drag_data_get does nothing, try providing row data. */ - if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW")) + if (gtk_selection_data_get_target (selection_data) == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW")) gtk_tree_set_row_drag_data (selection_data, model, source_row); @@ -7067,7 +7274,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, if (dest_row == NULL) return; - if (selection_data->length >= 0) + if (gtk_selection_data_get_length (selection_data) >= 0) { if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model), dest_row, @@ -7077,7 +7284,7 @@ gtk_icon_view_drag_data_received (GtkWidget *widget, gtk_drag_finish (context, accepted, - (context->action == GDK_ACTION_MOVE), + (gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE), time); gtk_tree_path_free (dest_row); @@ -7354,23 +7561,22 @@ 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); @@ -7388,26 +7594,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); @@ -7415,7 +7621,7 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view, cairo_destroy (cr); - return drawable; + return surface; } } @@ -8559,6 +8765,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; @@ -8574,6 +8781,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) @@ -8581,8 +8790,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)) || @@ -8878,7 +9087,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; @@ -8918,7 +9127,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; @@ -8976,7 +9185,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; @@ -9002,76 +9211,58 @@ gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view, } static void -gtk_icon_view_accessible_adjustment_changed (GtkAdjustment *adjustment, - GtkIconView *icon_view) +gtk_icon_view_accessible_adjustment_changed (GtkAdjustment *adjustment, + GtkIconViewAccessible *view) { - AtkObject *obj; - GtkIconViewAccessible *view; - - /* - * The scrollbars have changed - */ - obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view)); - view = GTK_ICON_VIEW_ACCESSIBLE (obj); - gtk_icon_view_accessible_traverse_items (view, NULL); } static void -gtk_icon_view_accessible_set_scroll_adjustments (GtkWidget *widget, - GtkAdjustment *hadj, - GtkAdjustment *vadj) +gtk_icon_view_accessible_set_adjustment (AtkObject *accessible, + GtkOrientation orientation, + GtkAdjustment *adjustment) { - AtkObject *atk_obj; GtkIconViewAccessiblePrivate *priv; + GtkAdjustment **old_adj_ptr; - atk_obj = gtk_widget_get_accessible (widget); - priv = gtk_icon_view_accessible_get_priv (atk_obj); + priv = gtk_icon_view_accessible_get_priv (accessible); - if (priv->old_hadj != hadj) + /* Adjustments are set for the first time in constructor and priv is not + * initialized at that time, so skip this first setting. */ + if (!priv) + return; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { - if (priv->old_hadj) - { - g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj), - (gpointer *)&priv->old_hadj); - - g_signal_handlers_disconnect_by_func (priv->old_hadj, - (gpointer) gtk_icon_view_accessible_adjustment_changed, - widget); - } - priv->old_hadj = hadj; - if (priv->old_hadj) - { - g_object_add_weak_pointer (G_OBJECT (priv->old_hadj), - (gpointer *)&priv->old_hadj); - g_signal_connect (hadj, - "value-changed", - G_CALLBACK (gtk_icon_view_accessible_adjustment_changed), - widget); - } + if (priv->old_hadj == adjustment) + return; + + old_adj_ptr = &priv->old_hadj; } - if (priv->old_vadj != vadj) + else { - if (priv->old_vadj) - { - g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj), - (gpointer *)&priv->old_vadj); - - g_signal_handlers_disconnect_by_func (priv->old_vadj, - (gpointer) gtk_icon_view_accessible_adjustment_changed, - widget); - } - priv->old_vadj = vadj; - if (priv->old_vadj) - { - g_object_add_weak_pointer (G_OBJECT (priv->old_vadj), - (gpointer *)&priv->old_vadj); - g_signal_connect (vadj, - "value-changed", - G_CALLBACK (gtk_icon_view_accessible_adjustment_changed), - widget); - } + if (priv->old_vadj == adjustment) + return; + + old_adj_ptr = &priv->old_vadj; } + + /* Disconnect signal handlers */ + if (*old_adj_ptr) + { + g_object_remove_weak_pointer (G_OBJECT (*old_adj_ptr), + (gpointer *)&priv->old_hadj); + g_signal_handlers_disconnect_by_func (*old_adj_ptr, + gtk_icon_view_accessible_adjustment_changed, + accessible); + } + + /* Connect signal */ + *old_adj_ptr = adjustment; + g_object_add_weak_pointer (G_OBJECT (adjustment), (gpointer *)old_adj_ptr); + g_signal_connect (adjustment, "value-changed", + G_CALLBACK (gtk_icon_view_accessible_adjustment_changed), + accessible); } static void @@ -9098,7 +9289,7 @@ gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model, if (a11y_item) { - widget = GTK_ACCESSIBLE (atk_obj)->widget; + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj)); icon_view = GTK_ICON_VIEW (widget); item = a11y_item->item; @@ -9374,27 +9565,13 @@ gtk_icon_view_accessible_initialize (AtkObject *accessible, icon_view = GTK_ICON_VIEW (data); if (icon_view->priv->hadjustment) - { - priv->old_hadj = icon_view->priv->hadjustment; - g_object_add_weak_pointer (G_OBJECT (priv->old_hadj), (gpointer *)&priv->old_hadj); - g_signal_connect (icon_view->priv->hadjustment, - "value-changed", - G_CALLBACK (gtk_icon_view_accessible_adjustment_changed), - icon_view); - } + gtk_icon_view_accessible_set_adjustment (accessible, + GTK_ORIENTATION_HORIZONTAL, + icon_view->priv->hadjustment); if (icon_view->priv->vadjustment) - { - priv->old_vadj = icon_view->priv->vadjustment; - g_object_add_weak_pointer (G_OBJECT (priv->old_vadj), (gpointer *)&priv->old_vadj); - g_signal_connect (icon_view->priv->vadjustment, - "value-changed", - G_CALLBACK (gtk_icon_view_accessible_adjustment_changed), - icon_view); - } - g_signal_connect_after (data, - "set-scroll-adjustments", - G_CALLBACK (gtk_icon_view_accessible_set_scroll_adjustments), - NULL); + gtk_icon_view_accessible_set_adjustment (accessible, + GTK_ORIENTATION_VERTICAL, + icon_view->priv->vadjustment); g_signal_connect (data, "notify", G_CALLBACK (gtk_icon_view_accessible_notify_gtk), @@ -9439,7 +9616,7 @@ gtk_icon_view_accessible_destroyed (GtkWidget *widget, g_signal_handlers_disconnect_by_func (priv->old_hadj, (gpointer) gtk_icon_view_accessible_adjustment_changed, - widget); + accessible); priv->old_hadj = NULL; } if (priv->old_vadj) @@ -9449,7 +9626,7 @@ gtk_icon_view_accessible_destroyed (GtkWidget *widget, g_signal_handlers_disconnect_by_func (priv->old_vadj, (gpointer) gtk_icon_view_accessible_adjustment_changed, - widget); + accessible); priv->old_vadj = NULL; } } @@ -9457,9 +9634,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); @@ -9500,7 +9680,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; @@ -9528,7 +9708,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; @@ -9550,7 +9730,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; @@ -9569,7 +9749,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; @@ -9601,7 +9781,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; @@ -9630,7 +9810,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; @@ -9653,7 +9833,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; @@ -9684,7 +9864,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; @@ -9888,8 +10068,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"