2 * Copyright (C) 2002, 2004 Anders Carlsson <andersca@gnu.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
25 #include <gdk/gdkkeysyms.h>
27 #include "gtkiconview.h"
28 #include "gtkmarshalers.h"
29 #include "gtkbindings.h"
32 #include "gtksignal.h"
34 #include "gtkaccessible.h"
35 #include "gtkwindow.h"
36 #include "gtktextbuffer.h"
37 #include "gtkprivate.h"
40 #undef DEBUG_ICON_VIEW
42 #define ICON_TEXT_PADDING 3
44 #define GTK_ICON_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ICON_VIEW, GtkIconViewPrivate))
45 #define VALID_MODEL_AND_COLUMNS(obj) ((obj)->priv->model != NULL && \
46 ((obj)->priv->pixbuf_column != -1 || \
47 (obj)->priv->text_column != -1 || \
48 (obj)->priv->markup_column != -1))
61 gint pixbuf_x, pixbuf_y;
62 gint pixbuf_height, pixbuf_width;
64 gint layout_x, layout_y;
65 gint layout_width, layout_height;
68 guint selected_before_rubberbanding : 1;
71 struct _GtkIconViewPrivate
79 GtkSelectionMode selection_mode;
81 GdkWindow *bin_window;
87 GtkAdjustment *hadjustment;
88 GtkAdjustment *vadjustment;
92 gboolean doing_rubberband;
93 gint rubberband_x1, rubberband_y1;
94 gint rubberband_x2, rubberband_y2;
96 guint scroll_timeout_id;
97 gint scroll_value_diff;
98 gint event_last_x, event_last_y;
100 GtkIconViewItem *anchor_item;
101 GtkIconViewItem *cursor_item;
103 guint ctrl_pressed : 1;
104 guint shift_pressed : 1;
106 GtkIconViewItem *last_single_clicked;
115 /* Layout used to draw icon text */
118 GtkOrientation orientation;
138 ACTIVATE_CURSOR_ITEM,
160 /* GObject signals */
161 static void gtk_icon_view_finalize (GObject *object);
162 static void gtk_icon_view_set_property (GObject *object,
166 static void gtk_icon_view_get_property (GObject *object,
172 /* GtkObject signals */
173 static void gtk_icon_view_destroy (GtkObject *object);
175 /* GtkWidget signals */
176 static void gtk_icon_view_realize (GtkWidget *widget);
177 static void gtk_icon_view_unrealize (GtkWidget *widget);
178 static void gtk_icon_view_map (GtkWidget *widget);
179 static void gtk_icon_view_size_request (GtkWidget *widget,
180 GtkRequisition *requisition);
181 static void gtk_icon_view_size_allocate (GtkWidget *widget,
182 GtkAllocation *allocation);
183 static gboolean gtk_icon_view_expose (GtkWidget *widget,
184 GdkEventExpose *expose);
185 static gboolean gtk_icon_view_motion (GtkWidget *widget,
186 GdkEventMotion *event);
187 static gboolean gtk_icon_view_button_press (GtkWidget *widget,
188 GdkEventButton *event);
189 static gboolean gtk_icon_view_button_release (GtkWidget *widget,
190 GdkEventButton *event);
191 /* GtkIconView signals */
192 static void gtk_icon_view_set_adjustments (GtkIconView *icon_view,
194 GtkAdjustment *vadj);
195 static void gtk_icon_view_real_select_all (GtkIconView *icon_view);
196 static void gtk_icon_view_real_unselect_all (GtkIconView *icon_view);
197 static void gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view);
198 static void gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view);
199 static gboolean gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view);
201 /* Internal functions */
202 static void gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment,
203 GtkIconView *icon_view);
204 static void gtk_icon_view_layout (GtkIconView *icon_view);
205 static void gtk_icon_view_paint_item (GtkIconView *icon_view,
207 GtkIconViewItem *item,
209 static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view,
212 static void gtk_icon_view_queue_draw_item (GtkIconView *icon_view,
213 GtkIconViewItem *item);
214 static void gtk_icon_view_queue_layout (GtkIconView *icon_view);
215 static void gtk_icon_view_set_cursor_item (GtkIconView *icon_view,
216 GtkIconViewItem *item);
217 static void gtk_icon_view_start_rubberbanding (GtkIconView *icon_view,
220 static void gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view);
221 static void gtk_icon_view_update_rubberband_selection (GtkIconView *icon_view);
222 static gboolean gtk_icon_view_item_hit_test (GtkIconViewItem *item,
228 static gboolean gtk_icon_view_maybe_begin_dragging_items (GtkIconView *icon_view,
229 GdkEventMotion *event);
231 static gboolean gtk_icon_view_unselect_all_internal (GtkIconView *icon_view);
232 static void gtk_icon_view_calculate_item_size (GtkIconView *icon_view,
233 GtkIconViewItem *item,
235 static void gtk_icon_view_update_rubberband (gpointer data);
236 static void gtk_icon_view_item_invalidate_size (GtkIconViewItem *item);
237 static void gtk_icon_view_invalidate_sizes (GtkIconView *icon_view);
238 static void gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
241 GtkMovementStep step,
243 static gboolean gtk_icon_view_real_move_cursor (GtkIconView *icon_view,
244 GtkMovementStep step,
246 static void gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
248 static void gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
250 static void gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
252 static void gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
254 static void gtk_icon_view_scroll_to_item (GtkIconView *icon_view,
255 GtkIconViewItem *item);
256 static GdkPixbuf *gtk_icon_view_get_item_icon (GtkIconView *icon_view,
257 GtkIconViewItem *item);
258 static void gtk_icon_view_update_item_text (GtkIconView *icon_view,
259 GtkIconViewItem *item);
260 static void gtk_icon_view_select_item (GtkIconView *icon_view,
261 GtkIconViewItem *item);
262 static void gtk_icon_view_unselect_item (GtkIconView *icon_view,
263 GtkIconViewItem *item);
264 static gboolean gtk_icon_view_select_all_between (GtkIconView *icon_view,
265 GtkIconViewItem *anchor,
266 GtkIconViewItem *cursor);
268 static GtkIconViewItem *gtk_icon_view_get_item_at_pos (GtkIconView *icon_view,
273 /* Accessibility Support */
274 static AtkObject *gtk_icon_view_get_accessible (GtkWidget *widget);
276 static GtkContainerClass *parent_class = NULL;
277 static guint icon_view_signals[LAST_SIGNAL] = { 0 };
279 G_DEFINE_TYPE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER);
282 gtk_icon_view_class_init (GtkIconViewClass *klass)
284 GObjectClass *gobject_class;
285 GtkObjectClass *object_class;
286 GtkWidgetClass *widget_class;
287 GtkBindingSet *binding_set;
289 parent_class = g_type_class_peek_parent (klass);
290 binding_set = gtk_binding_set_by_class (klass);
292 g_type_class_add_private (klass, sizeof (GtkIconViewPrivate));
294 gobject_class = (GObjectClass *) klass;
295 object_class = (GtkObjectClass *) klass;
296 widget_class = (GtkWidgetClass *) klass;
298 gobject_class->finalize = gtk_icon_view_finalize;
299 gobject_class->set_property = gtk_icon_view_set_property;
300 gobject_class->get_property = gtk_icon_view_get_property;
302 object_class->destroy = gtk_icon_view_destroy;
304 widget_class->realize = gtk_icon_view_realize;
305 widget_class->unrealize = gtk_icon_view_unrealize;
306 widget_class->map = gtk_icon_view_map;
307 widget_class->size_request = gtk_icon_view_size_request;
308 widget_class->size_allocate = gtk_icon_view_size_allocate;
309 widget_class->expose_event = gtk_icon_view_expose;
310 widget_class->motion_notify_event = gtk_icon_view_motion;
311 widget_class->button_press_event = gtk_icon_view_button_press;
312 widget_class->button_release_event = gtk_icon_view_button_release;
313 widget_class->get_accessible = gtk_icon_view_get_accessible;
315 klass->set_scroll_adjustments = gtk_icon_view_set_adjustments;
316 klass->select_all = gtk_icon_view_real_select_all;
317 klass->unselect_all = gtk_icon_view_real_unselect_all;
318 klass->select_cursor_item = gtk_icon_view_real_select_cursor_item;
319 klass->toggle_cursor_item = gtk_icon_view_real_toggle_cursor_item;
320 klass->activate_cursor_item = gtk_icon_view_real_activate_cursor_item;
321 klass->move_cursor = gtk_icon_view_real_move_cursor;
325 * GtkIconView:selection-mode:
327 * The ::selection-mode property specifies the selection mode of
328 * icon view. If the mode is #GTK_SELECTION_MULTIPLE, rubberband selection
329 * is enabled, for the other modes, only keyboard selection is possible.
333 g_object_class_install_property (gobject_class,
335 g_param_spec_enum ("selection-mode",
336 P_("Selection mode"),
337 P_("The selection mode"),
338 GTK_TYPE_SELECTION_MODE,
339 GTK_SELECTION_SINGLE,
340 GTK_PARAM_READWRITE));
343 * GtkIconView:pixbuf-column:
345 * The ::pixbuf-column property contains the number of the model column
346 * containing the pixbufs which are displayed. The pixbuf column must be
347 * of type #GDK_TYPE_PIXBUF. Setting this property to -1 turns off the
348 * display of pixbufs.
352 g_object_class_install_property (gobject_class,
354 g_param_spec_int ("pixbuf-column",
356 P_("Model column used to retrieve the icon pixbuf from"),
358 GTK_PARAM_READWRITE));
361 * GtkIconView:text-column:
363 * The ::text-column property contains the number of the model column
364 * containing the texts which are displayed. The text column must be
365 * of type #G_TYPE_STRING. If this property and the :markup-column
366 * property are both set to -1, no texts are displayed.
370 g_object_class_install_property (gobject_class,
372 g_param_spec_int ("text-column",
374 P_("Model column used to retrieve the text from"),
376 GTK_PARAM_READWRITE));
380 * GtkIconView:markup-column:
382 * The ::markup-column property contains the number of the model column
383 * containing markup information to be displayed. The markup column must be
384 * of type #G_TYPE_STRING. If this property and the :text-column property
385 * are both set to column numbers, it overrides the text column.
386 * If both are set to -1, no texts are displayed.
390 g_object_class_install_property (gobject_class,
392 g_param_spec_int ("markup-column",
394 P_("Model column used to retrieve the text if using Pango markup"),
396 GTK_PARAM_READWRITE));
398 g_object_class_install_property (gobject_class,
400 g_param_spec_object ("model",
401 P_("Icon View Model"),
402 P_("The model for the icon view"),
404 GTK_PARAM_READWRITE));
407 * GtkIconView:columns:
409 * The columns property contains the number of the columns in which the
410 * items should be displayed. If it is -1, the number of columns will
411 * be chosen automatically to fill the available area.
415 g_object_class_install_property (gobject_class,
417 g_param_spec_int ("columns",
418 P_("Number of columns"),
419 P_("Number of columns to display"),
421 GTK_PARAM_READWRITE));
425 * GtkIconView::item-width:
427 * The item-width property specifies the width to use for each item.
428 * If it is set to -1, the icon view will automatically determine a
429 * suitable item size.
433 g_object_class_install_property (gobject_class,
435 g_param_spec_int ("item-width",
436 P_("Width for each item"),
437 P_("The width used for each item"),
439 GTK_PARAM_READWRITE));
442 * GtkIconView::spacing:
444 * The spacing property specifies the space which is inserted between
445 * the cells (i.e. the icon and the text) of an item.
449 g_object_class_install_property (gobject_class,
451 g_param_spec_int ("spacing",
453 P_("Space which is inserted between cells of an item"),
455 GTK_PARAM_READWRITE));
458 * GtkIconView::row-spacing:
460 * The row-spacing property specifies the space which is inserted between
461 * the rows of the icon view.
465 g_object_class_install_property (gobject_class,
467 g_param_spec_int ("row-spacing",
469 P_("Space which is inserted between grid rows"),
471 GTK_PARAM_READWRITE));
474 * GtkIconView::column-spacing:
476 * The column-spacing property specifies the space which is inserted between
477 * the columns of the icon view.
481 g_object_class_install_property (gobject_class,
483 g_param_spec_int ("column-spacing",
484 P_("Column Spacing"),
485 P_("Space which is inserted between grid column"),
487 GTK_PARAM_READWRITE));
490 * GtkIconView::margin:
492 * The margin property specifies the space which is inserted
493 * at the edges of the icon view.
497 g_object_class_install_property (gobject_class,
499 g_param_spec_int ("margin",
501 P_("Space which is inserted at the edges of the icon view"),
503 GTK_PARAM_READWRITE));
507 * GtkIconView::orientation:
509 * The orientation property specifies how the cells (i.e. the icon and
510 * the text) of the item are positioned relative to each other.
514 g_object_class_install_property (gobject_class,
516 g_param_spec_enum ("orientation",
518 P_("How the text and icon of each item are positioned relative to each other"),
519 GTK_TYPE_ORIENTATION,
520 GTK_ORIENTATION_VERTICAL,
521 GTK_PARAM_READWRITE));
523 /* Style properties */
524 gtk_widget_class_install_style_property (widget_class,
525 g_param_spec_boxed ("selection-box-color",
526 P_("Selection Box Color"),
527 P_("Color of the selection box"),
529 GTK_PARAM_READABLE));
531 gtk_widget_class_install_style_property (widget_class,
532 g_param_spec_uchar ("selection-box-alpha",
533 P_("Selection Box Alpha"),
534 P_("Opacity of the selection box"),
537 GTK_PARAM_READABLE));
540 widget_class->set_scroll_adjustments_signal =
541 g_signal_new ("set_scroll_adjustments",
542 G_TYPE_FROM_CLASS (gobject_class),
544 G_STRUCT_OFFSET (GtkIconViewClass, set_scroll_adjustments),
546 _gtk_marshal_VOID__OBJECT_OBJECT,
548 GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
550 icon_view_signals[ITEM_ACTIVATED] =
551 g_signal_new ("item_activated",
552 G_TYPE_FROM_CLASS (gobject_class),
554 G_STRUCT_OFFSET (GtkIconViewClass, item_activated),
556 g_cclosure_marshal_VOID__BOXED,
560 icon_view_signals[SELECTION_CHANGED] =
561 g_signal_new ("selection_changed",
562 G_TYPE_FROM_CLASS (gobject_class),
564 G_STRUCT_OFFSET (GtkIconViewClass, selection_changed),
566 g_cclosure_marshal_VOID__VOID,
569 icon_view_signals[SELECT_ALL] =
570 g_signal_new ("select_all",
571 G_TYPE_FROM_CLASS (gobject_class),
572 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
573 G_STRUCT_OFFSET (GtkIconViewClass, select_all),
575 g_cclosure_marshal_VOID__VOID,
578 icon_view_signals[UNSELECT_ALL] =
579 g_signal_new ("unselect_all",
580 G_TYPE_FROM_CLASS (gobject_class),
581 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
582 G_STRUCT_OFFSET (GtkIconViewClass, unselect_all),
584 g_cclosure_marshal_VOID__VOID,
587 icon_view_signals[SELECT_CURSOR_ITEM] =
588 g_signal_new ("select_cursor_item",
589 G_TYPE_FROM_CLASS (gobject_class),
590 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
591 G_STRUCT_OFFSET (GtkIconViewClass, select_cursor_item),
593 g_cclosure_marshal_VOID__VOID,
596 icon_view_signals[TOGGLE_CURSOR_ITEM] =
597 g_signal_new ("toggle_cursor_item",
598 G_TYPE_FROM_CLASS (gobject_class),
599 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
600 G_STRUCT_OFFSET (GtkIconViewClass, toggle_cursor_item),
602 g_cclosure_marshal_VOID__VOID,
605 icon_view_signals[ACTIVATE_CURSOR_ITEM] =
606 g_signal_new ("activate_cursor_item",
607 G_TYPE_FROM_CLASS (gobject_class),
608 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
609 G_STRUCT_OFFSET (GtkIconViewClass, activate_cursor_item),
611 _gtk_marshal_BOOLEAN__VOID,
614 icon_view_signals[MOVE_CURSOR] =
615 g_signal_new ("move_cursor",
616 G_TYPE_FROM_CLASS (gobject_class),
617 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
618 G_STRUCT_OFFSET (GtkIconViewClass, move_cursor),
620 _gtk_marshal_BOOLEAN__ENUM_INT,
622 GTK_TYPE_MOVEMENT_STEP,
626 gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, "select_all", 0);
627 gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect_all", 0);
628 gtk_binding_entry_add_signal (binding_set, GDK_space, 0, "select_cursor_item", 0);
629 gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, "toggle_cursor_item", 0);
631 gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, "activate_cursor_item", 0);
632 gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, "activate_cursor_item", 0);
633 gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, "activate_cursor_item", 0);
635 gtk_icon_view_add_move_binding (binding_set, GDK_Up, 0,
636 GTK_MOVEMENT_DISPLAY_LINES, -1);
637 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Up, 0,
638 GTK_MOVEMENT_DISPLAY_LINES, -1);
640 gtk_icon_view_add_move_binding (binding_set, GDK_Down, 0,
641 GTK_MOVEMENT_DISPLAY_LINES, 1);
642 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Down, 0,
643 GTK_MOVEMENT_DISPLAY_LINES, 1);
645 gtk_icon_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
646 GTK_MOVEMENT_DISPLAY_LINES, -1);
648 gtk_icon_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
649 GTK_MOVEMENT_DISPLAY_LINES, 1);
651 gtk_icon_view_add_move_binding (binding_set, GDK_Home, 0,
652 GTK_MOVEMENT_BUFFER_ENDS, -1);
653 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Home, 0,
654 GTK_MOVEMENT_BUFFER_ENDS, -1);
656 gtk_icon_view_add_move_binding (binding_set, GDK_End, 0,
657 GTK_MOVEMENT_BUFFER_ENDS, 1);
658 gtk_icon_view_add_move_binding (binding_set, GDK_KP_End, 0,
659 GTK_MOVEMENT_BUFFER_ENDS, 1);
661 gtk_icon_view_add_move_binding (binding_set, GDK_Page_Up, 0,
662 GTK_MOVEMENT_PAGES, -1);
663 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
664 GTK_MOVEMENT_PAGES, -1);
666 gtk_icon_view_add_move_binding (binding_set, GDK_Page_Down, 0,
667 GTK_MOVEMENT_PAGES, 1);
668 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
669 GTK_MOVEMENT_PAGES, 1);
671 gtk_icon_view_add_move_binding (binding_set, GDK_Right, 0,
672 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
673 gtk_icon_view_add_move_binding (binding_set, GDK_Left, 0,
674 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
676 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Right, 0,
677 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
678 gtk_icon_view_add_move_binding (binding_set, GDK_KP_Left, 0,
679 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
683 gtk_icon_view_init (GtkIconView *icon_view)
685 icon_view->priv = GTK_ICON_VIEW_GET_PRIVATE (icon_view);
687 icon_view->priv->width = 0;
688 icon_view->priv->height = 0;
689 icon_view->priv->selection_mode = GTK_SELECTION_SINGLE;
691 icon_view->priv->pressed_button = -1;
692 icon_view->priv->press_start_x = -1;
693 icon_view->priv->press_start_y = -1;
695 icon_view->priv->text_column = -1;
696 icon_view->priv->markup_column = -1;
697 icon_view->priv->pixbuf_column = -1;
699 icon_view->priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (icon_view), NULL);
701 pango_layout_set_wrap (icon_view->priv->layout, PANGO_WRAP_WORD_CHAR);
703 GTK_WIDGET_SET_FLAGS (icon_view, GTK_CAN_FOCUS);
705 gtk_icon_view_set_adjustments (icon_view, NULL, NULL);
707 icon_view->priv->orientation = GTK_ORIENTATION_VERTICAL;
709 icon_view->priv->columns = -1;
710 icon_view->priv->item_width = -1;
711 icon_view->priv->spacing = 0;
712 icon_view->priv->row_spacing = 6;
713 icon_view->priv->column_spacing = 6;
714 icon_view->priv->margin = 6;
718 gtk_icon_view_destroy (GtkObject *object)
720 GtkIconView *icon_view;
722 icon_view = GTK_ICON_VIEW (object);
724 gtk_icon_view_set_model (icon_view, NULL);
726 if (icon_view->priv->layout_idle_id != 0)
727 g_source_remove (icon_view->priv->layout_idle_id);
729 if (icon_view->priv->scroll_timeout_id != 0)
730 g_source_remove (icon_view->priv->scroll_timeout_id);
732 (GTK_OBJECT_CLASS (parent_class)->destroy) (object);
735 /* GObject methods */
737 gtk_icon_view_finalize (GObject *object)
739 GtkIconView *icon_view;
741 icon_view = GTK_ICON_VIEW (object);
743 g_object_unref (icon_view->priv->layout);
745 (G_OBJECT_CLASS (parent_class)->finalize) (object);
750 gtk_icon_view_set_property (GObject *object,
755 GtkIconView *icon_view;
757 icon_view = GTK_ICON_VIEW (object);
761 case PROP_SELECTION_MODE:
762 gtk_icon_view_set_selection_mode (icon_view, g_value_get_enum (value));
764 case PROP_PIXBUF_COLUMN:
765 gtk_icon_view_set_pixbuf_column (icon_view, g_value_get_int (value));
767 case PROP_TEXT_COLUMN:
768 gtk_icon_view_set_text_column (icon_view, g_value_get_int (value));
770 case PROP_MARKUP_COLUMN:
771 gtk_icon_view_set_markup_column (icon_view, g_value_get_int (value));
774 gtk_icon_view_set_model (icon_view, g_value_get_object (value));
776 case PROP_ORIENTATION:
777 gtk_icon_view_set_orientation (icon_view, g_value_get_enum (value));
780 gtk_icon_view_set_columns (icon_view, g_value_get_int (value));
782 case PROP_ITEM_WIDTH:
783 gtk_icon_view_set_item_width (icon_view, g_value_get_int (value));
786 gtk_icon_view_set_spacing (icon_view, g_value_get_int (value));
788 case PROP_ROW_SPACING:
789 gtk_icon_view_set_row_spacing (icon_view, g_value_get_int (value));
791 case PROP_COLUMN_SPACING:
792 gtk_icon_view_set_column_spacing (icon_view, g_value_get_int (value));
795 gtk_icon_view_set_margin (icon_view, g_value_get_int (value));
799 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
805 gtk_icon_view_get_property (GObject *object,
810 GtkIconView *icon_view;
812 icon_view = GTK_ICON_VIEW (object);
816 case PROP_SELECTION_MODE:
817 g_value_set_enum (value, icon_view->priv->selection_mode);
819 case PROP_PIXBUF_COLUMN:
820 g_value_set_int (value, icon_view->priv->pixbuf_column);
822 case PROP_TEXT_COLUMN:
823 g_value_set_int (value, icon_view->priv->text_column);
825 case PROP_MARKUP_COLUMN:
826 g_value_set_int (value, icon_view->priv->markup_column);
829 g_value_set_object (value, icon_view->priv->model);
831 case PROP_ORIENTATION:
832 g_value_set_enum (value, icon_view->priv->orientation);
835 g_value_set_int (value, icon_view->priv->columns);
837 case PROP_ITEM_WIDTH:
838 g_value_set_int (value, icon_view->priv->item_width);
841 g_value_set_int (value, icon_view->priv->spacing);
843 case PROP_ROW_SPACING:
844 g_value_set_int (value, icon_view->priv->row_spacing);
846 case PROP_COLUMN_SPACING:
847 g_value_set_int (value, icon_view->priv->column_spacing);
850 g_value_set_int (value, icon_view->priv->margin);
854 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
859 /* GtkWidget signals */
861 gtk_icon_view_realize (GtkWidget *widget)
863 GtkIconView *icon_view;
864 GdkWindowAttr attributes;
865 gint attributes_mask;
867 icon_view = GTK_ICON_VIEW (widget);
869 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
871 /* Make the main, clipping window */
872 attributes.window_type = GDK_WINDOW_CHILD;
873 attributes.x = widget->allocation.x;
874 attributes.y = widget->allocation.y;
875 attributes.width = widget->allocation.width;
876 attributes.height = widget->allocation.height;
877 attributes.wclass = GDK_INPUT_OUTPUT;
878 attributes.visual = gtk_widget_get_visual (widget);
879 attributes.colormap = gtk_widget_get_colormap (widget);
880 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
882 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
884 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
885 &attributes, attributes_mask);
886 gdk_window_set_user_data (widget->window, widget);
888 /* Make the window for the icon view */
891 attributes.width = MAX (icon_view->priv->width, widget->allocation.width);
892 attributes.height = MAX (icon_view->priv->height, widget->allocation.height);
893 attributes.event_mask = (GDK_EXPOSURE_MASK |
895 GDK_POINTER_MOTION_MASK |
896 GDK_BUTTON_PRESS_MASK |
897 GDK_BUTTON_RELEASE_MASK |
899 GDK_KEY_RELEASE_MASK) |
900 gtk_widget_get_events (widget);
902 icon_view->priv->bin_window = gdk_window_new (widget->window,
903 &attributes, attributes_mask);
904 gdk_window_set_user_data (icon_view->priv->bin_window, widget);
906 widget->style = gtk_style_attach (widget->style, widget->window);
907 gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]);
908 gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
912 gtk_icon_view_unrealize (GtkWidget *widget)
914 GtkIconView *icon_view;
916 icon_view = GTK_ICON_VIEW (widget);
918 gdk_window_set_user_data (icon_view->priv->bin_window, NULL);
919 gdk_window_destroy (icon_view->priv->bin_window);
920 icon_view->priv->bin_window = NULL;
922 /* GtkWidget::unrealize destroys children and widget->window */
923 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
924 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
928 gtk_icon_view_map (GtkWidget *widget)
930 GtkIconView *icon_view;
932 icon_view = GTK_ICON_VIEW (widget);
934 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
936 gdk_window_show (icon_view->priv->bin_window);
937 gdk_window_show (widget->window);
941 gtk_icon_view_size_request (GtkWidget *widget,
942 GtkRequisition *requisition)
944 GtkIconView *icon_view;
946 icon_view = GTK_ICON_VIEW (widget);
948 requisition->width = icon_view->priv->width;
949 requisition->height = icon_view->priv->height;
953 gtk_icon_view_size_allocate (GtkWidget *widget,
954 GtkAllocation *allocation)
956 GtkIconView *icon_view;
957 GtkAdjustment *hadjustment, *vadjustment;
959 widget->allocation = *allocation;
961 icon_view = GTK_ICON_VIEW (widget);
963 if (GTK_WIDGET_REALIZED (widget))
965 gdk_window_move_resize (widget->window,
966 allocation->x, allocation->y,
967 allocation->width, allocation->height);
968 gdk_window_resize (icon_view->priv->bin_window,
969 MAX (icon_view->priv->width, allocation->width),
970 MAX (icon_view->priv->height, allocation->height));
973 hadjustment = icon_view->priv->hadjustment;
974 vadjustment = icon_view->priv->vadjustment;
976 hadjustment->page_size = allocation->width;
977 hadjustment->page_increment = allocation->width * 0.9;
978 hadjustment->step_increment = allocation->width * 0.1;
979 hadjustment->lower = 0;
980 hadjustment->upper = MAX (allocation->width, icon_view->priv->width);
982 if (hadjustment->value > hadjustment->upper - hadjustment->page_size)
983 gtk_adjustment_set_value (hadjustment, MAX (0, hadjustment->upper - hadjustment->page_size));
985 gtk_adjustment_changed (hadjustment);
987 vadjustment->page_size = allocation->height;
988 vadjustment->page_increment = allocation->height * 0.9;
989 vadjustment->step_increment = allocation->height * 0.1;
990 vadjustment->lower = 0;
991 vadjustment->upper = MAX (allocation->height, icon_view->priv->height);
993 if (vadjustment->value > vadjustment->upper - vadjustment->page_size)
994 gtk_adjustment_set_value (vadjustment, MAX (0, vadjustment->upper - vadjustment->page_size));
996 gtk_adjustment_changed (vadjustment);
998 gtk_icon_view_layout (icon_view);
1002 gtk_icon_view_expose (GtkWidget *widget,
1003 GdkEventExpose *expose)
1005 GtkIconView *icon_view;
1009 icon_view = GTK_ICON_VIEW (widget);
1011 if (expose->window != icon_view->priv->bin_window)
1014 cr = gdk_drawable_create_cairo_context (icon_view->priv->bin_window);
1015 cairo_set_line_width (cr, 1.);
1017 for (icons = icon_view->priv->items; icons; icons = icons->next) {
1018 GtkIconViewItem *item = icons->data;
1019 GdkRectangle item_rectangle;
1021 item_rectangle.x = item->x;
1022 item_rectangle.y = item->y;
1023 item_rectangle.width = item->width;
1024 item_rectangle.height = item->height;
1026 if (gdk_region_rect_in (expose->region, &item_rectangle) == GDK_OVERLAP_RECTANGLE_OUT)
1029 #ifdef DEBUG_ICON_VIEW
1030 cairo_rectangle (cr,
1031 item->x + 0.5, item->y + 0.5,
1032 item->width - 1, item->height - 1);
1033 cairo_rectangle (cr,
1034 item->x + 0.5, item->y + 0.5,
1035 item->width - 1, item->height- 1);
1036 cairo_rectangle (cr,
1037 item->pixbuf_x + 0.5, item->pixbuf_y + 0.5,
1038 item->pixbuf_width - 1, item->pixbuf_height- 1);
1039 cairo_rectangle (cr,
1040 item->layout_x + 0.5, item->layout_y + 0.5,
1041 item->layout_width - 1, item->layout_height - 1);
1044 gtk_icon_view_paint_item (icon_view, cr, item, &expose->area);
1048 if (icon_view->priv->doing_rubberband)
1050 GdkRectangle *rectangles;
1053 gdk_region_get_rectangles (expose->region,
1057 while (n_rectangles--)
1058 gtk_icon_view_paint_rubberband (icon_view, cr, &rectangles[n_rectangles]);
1060 g_free (rectangles);
1069 scroll_timeout (gpointer data)
1071 GtkIconView *icon_view;
1074 GDK_THREADS_ENTER ();
1078 value = MIN (icon_view->priv->vadjustment->value +
1079 icon_view->priv->scroll_value_diff,
1080 icon_view->priv->vadjustment->upper -
1081 icon_view->priv->vadjustment->page_size);
1083 gtk_adjustment_set_value (icon_view->priv->vadjustment,
1086 gtk_icon_view_update_rubberband (icon_view);
1088 GDK_THREADS_LEAVE ();
1094 gtk_icon_view_motion (GtkWidget *widget,
1095 GdkEventMotion *event)
1097 GtkIconView *icon_view;
1100 icon_view = GTK_ICON_VIEW (widget);
1102 gtk_icon_view_maybe_begin_dragging_items (icon_view, event);
1104 if (icon_view->priv->doing_rubberband)
1106 gtk_icon_view_update_rubberband (widget);
1108 abs_y = event->y - icon_view->priv->height *
1109 (icon_view->priv->vadjustment->value /
1110 (icon_view->priv->vadjustment->upper -
1111 icon_view->priv->vadjustment->lower));
1113 if (abs_y < 0 || abs_y > widget->allocation.height)
1115 if (icon_view->priv->scroll_timeout_id == 0)
1116 icon_view->priv->scroll_timeout_id = g_timeout_add (30, scroll_timeout, icon_view);
1119 icon_view->priv->scroll_value_diff = abs_y;
1121 icon_view->priv->scroll_value_diff = abs_y - widget->allocation.height;
1123 icon_view->priv->event_last_x = event->x;
1124 icon_view->priv->event_last_y = event->y;
1126 else if (icon_view->priv->scroll_timeout_id != 0)
1128 g_source_remove (icon_view->priv->scroll_timeout_id);
1130 icon_view->priv->scroll_timeout_id = 0;
1138 gtk_icon_view_button_press (GtkWidget *widget,
1139 GdkEventButton *event)
1141 GtkIconView *icon_view;
1142 GtkIconViewItem *item;
1143 gboolean dirty = FALSE;
1145 icon_view = GTK_ICON_VIEW (widget);
1147 if (event->window != icon_view->priv->bin_window)
1150 if (!GTK_WIDGET_HAS_FOCUS (widget))
1151 gtk_widget_grab_focus (widget);
1153 if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
1156 item = gtk_icon_view_get_item_at_pos (icon_view,
1157 event->x, event->y);
1161 gtk_icon_view_scroll_to_item (icon_view, item);
1163 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
1165 gtk_icon_view_set_cursor_item (icon_view, item);
1167 else if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE &&
1168 (event->state & GDK_SHIFT_MASK))
1170 gtk_icon_view_unselect_all_internal (icon_view);
1172 gtk_icon_view_set_cursor_item (icon_view, item);
1173 if (!icon_view->priv->anchor_item)
1174 icon_view->priv->anchor_item = item;
1176 gtk_icon_view_select_all_between (icon_view,
1177 icon_view->priv->anchor_item,
1183 if ((icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE ||
1184 ((icon_view->priv->selection_mode == GTK_SELECTION_SINGLE) && item->selected)) &&
1185 (event->state & GDK_CONTROL_MASK))
1187 item->selected = !item->selected;
1188 gtk_icon_view_queue_draw_item (icon_view, item);
1193 if (!item->selected)
1195 gtk_icon_view_unselect_all_internal (icon_view);
1197 item->selected = TRUE;
1198 gtk_icon_view_queue_draw_item (icon_view, item);
1202 gtk_icon_view_set_cursor_item (icon_view, item);
1203 icon_view->priv->anchor_item = item;
1206 /* Save press to possibly begin a drag */
1207 if (icon_view->priv->pressed_button < 0)
1209 icon_view->priv->pressed_button = event->button;
1210 icon_view->priv->press_start_x = event->x;
1211 icon_view->priv->press_start_y = event->y;
1214 if (!icon_view->priv->last_single_clicked)
1215 icon_view->priv->last_single_clicked = item;
1219 if (icon_view->priv->selection_mode != GTK_SELECTION_BROWSE &&
1220 !(event->state & GDK_CONTROL_MASK))
1222 dirty = gtk_icon_view_unselect_all_internal (icon_view);
1225 if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
1226 gtk_icon_view_start_rubberbanding (icon_view, event->x, event->y);
1231 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
1233 item = gtk_icon_view_get_item_at_pos (icon_view,
1234 event->x, event->y);
1236 if (item && item == icon_view->priv->last_single_clicked)
1240 path = gtk_tree_path_new_from_indices (item->index, -1);
1241 gtk_icon_view_item_activated (icon_view, path);
1242 gtk_tree_path_free (path);
1245 icon_view->priv->last_single_clicked = NULL;
1249 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
1251 return event->button == 1;
1255 gtk_icon_view_button_release (GtkWidget *widget,
1256 GdkEventButton *event)
1258 GtkIconView *icon_view;
1260 icon_view = GTK_ICON_VIEW (widget);
1263 if (icon_view->priv->pressed_button == event->button)
1264 icon_view->priv->pressed_button = -1;
1266 gtk_icon_view_stop_rubberbanding (icon_view);
1268 if (icon_view->priv->scroll_timeout_id != 0)
1270 g_source_remove (icon_view->priv->scroll_timeout_id);
1271 icon_view->priv->scroll_timeout_id = 0;
1278 gtk_icon_view_update_rubberband (gpointer data)
1280 GtkIconView *icon_view;
1282 GdkRectangle old_area;
1283 GdkRectangle new_area;
1284 GdkRectangle common;
1285 GdkRegion *invalid_region;
1287 icon_view = GTK_ICON_VIEW (data);
1289 gdk_window_get_pointer (icon_view->priv->bin_window, &x, &y, NULL);
1294 old_area.x = MIN (icon_view->priv->rubberband_x1,
1295 icon_view->priv->rubberband_x2);
1296 old_area.y = MIN (icon_view->priv->rubberband_y1,
1297 icon_view->priv->rubberband_y2);
1298 old_area.width = ABS (icon_view->priv->rubberband_x2 -
1299 icon_view->priv->rubberband_x1) + 1;
1300 old_area.height = ABS (icon_view->priv->rubberband_y2 -
1301 icon_view->priv->rubberband_y1) + 1;
1303 new_area.x = MIN (icon_view->priv->rubberband_x1, x);
1304 new_area.y = MIN (icon_view->priv->rubberband_y1, y);
1305 new_area.width = ABS (x - icon_view->priv->rubberband_x1) + 1;
1306 new_area.height = ABS (y - icon_view->priv->rubberband_y1) + 1;
1308 invalid_region = gdk_region_rectangle (&old_area);
1309 gdk_region_union_with_rect (invalid_region, &new_area);
1311 gdk_rectangle_intersect (&old_area, &new_area, &common);
1312 if (common.width > 2 && common.height > 2)
1314 GdkRegion *common_region;
1316 /* make sure the border is invalidated */
1322 common_region = gdk_region_rectangle (&common);
1324 gdk_region_subtract (invalid_region, common_region);
1325 gdk_region_destroy (common_region);
1328 gdk_window_invalidate_region (icon_view->priv->bin_window, invalid_region, TRUE);
1330 gdk_region_destroy (invalid_region);
1332 icon_view->priv->rubberband_x2 = x;
1333 icon_view->priv->rubberband_y2 = y;
1335 gtk_icon_view_update_rubberband_selection (icon_view);
1339 gtk_icon_view_start_rubberbanding (GtkIconView *icon_view,
1345 g_assert (!icon_view->priv->doing_rubberband);
1347 for (items = icon_view->priv->items; items; items = items->next)
1349 GtkIconViewItem *item = items->data;
1351 item->selected_before_rubberbanding = item->selected;
1354 icon_view->priv->rubberband_x1 = x;
1355 icon_view->priv->rubberband_y1 = y;
1356 icon_view->priv->rubberband_x2 = x;
1357 icon_view->priv->rubberband_y2 = y;
1359 icon_view->priv->doing_rubberband = TRUE;
1361 gtk_grab_add (GTK_WIDGET (icon_view));
1365 gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view)
1367 if (!icon_view->priv->doing_rubberband)
1370 icon_view->priv->doing_rubberband = FALSE;
1372 gtk_grab_remove (GTK_WIDGET (icon_view));
1374 gtk_widget_queue_draw (GTK_WIDGET (icon_view));
1378 gtk_icon_view_update_rubberband_selection (GtkIconView *icon_view)
1381 gint x, y, width, height;
1382 gboolean dirty = FALSE;
1384 x = MIN (icon_view->priv->rubberband_x1,
1385 icon_view->priv->rubberband_x2);
1386 y = MIN (icon_view->priv->rubberband_y1,
1387 icon_view->priv->rubberband_y2);
1388 width = ABS (icon_view->priv->rubberband_x1 -
1389 icon_view->priv->rubberband_x2);
1390 height = ABS (icon_view->priv->rubberband_y1 -
1391 icon_view->priv->rubberband_y2);
1393 for (items = icon_view->priv->items; items; items = items->next)
1395 GtkIconViewItem *item = items->data;
1399 is_in = gtk_icon_view_item_hit_test (item, x, y, width, height);
1401 selected = is_in ^ item->selected_before_rubberbanding;
1403 if (item->selected != selected)
1405 item->selected = selected;
1407 gtk_icon_view_queue_draw_item (icon_view, item);
1412 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
1416 gtk_icon_view_item_hit_test (GtkIconViewItem *item,
1422 /* First try the pixbuf */
1423 if (MIN (x + width, item->pixbuf_x + item->pixbuf_width) - MAX (x, item->pixbuf_x) > 0 &&
1424 MIN (y + height, item->pixbuf_y + item->pixbuf_height) - MAX (y, item->pixbuf_y) > 0)
1427 /* Then try the text */
1428 if (MIN (x + width, item->layout_x + item->layout_width) - MAX (x, item->layout_x) > 0 &&
1429 MIN (y + height, item->layout_y + item->layout_height) - MAX (y, item->layout_y) > 0)
1437 gtk_icon_view_maybe_begin_dragging_items (GtkIconView *icon_view,
1438 GdkEventMotion *event)
1440 gboolean retval = FALSE;
1442 if (icon_view->priv->pressed_button < 0)
1445 if (!gtk_drag_check_threshold (GTK_WIDGET (icon_view),
1446 icon_view->priv->press_start_x,
1447 icon_view->priv->press_start_y,
1448 event->x, event->y))
1451 button = icon_view->priv->pressed_button;
1452 icon_view->priv->pressed_button = -1;
1455 static GtkTargetEntry row_targets[] = {
1456 { "GTK_ICON_VIEW_ITEMS", GTK_TARGET_SAME_APP, 0 }
1458 GtkTargetList *target_list;
1459 GdkDragContext *context;
1460 GtkIconViewItem *item;
1464 target_list = gtk_target_list_new (row_targets, G_N_ELEMENTS (row_targets));
1466 context = gtk_drag_begin (GTK_WIDGET (icon_view),
1467 target_list, GDK_ACTION_MOVE,
1471 item = gtk_icon_view_get_item_at_pos (icon_view,
1472 icon_view->priv->press_start_x,
1473 icon_view->priv->press_start_y);
1474 g_assert (item != NULL);
1475 gtk_drag_set_icon_pixbuf (context, gtk_icon_view_get_item_icon (icon_view, item),
1477 event->y - item->y);
1485 gtk_icon_view_unselect_all_internal (GtkIconView *icon_view)
1487 gboolean dirty = FALSE;
1490 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
1493 for (items = icon_view->priv->items; items; items = items->next)
1495 GtkIconViewItem *item = items->data;
1499 item->selected = FALSE;
1501 gtk_icon_view_queue_draw_item (icon_view, item);
1509 /* GtkIconView signals */
1511 gtk_icon_view_set_adjustments (GtkIconView *icon_view,
1512 GtkAdjustment *hadj,
1513 GtkAdjustment *vadj)
1515 gboolean need_adjust = FALSE;
1518 g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
1520 hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1522 g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
1524 vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
1526 if (icon_view->priv->hadjustment && (icon_view->priv->hadjustment != hadj))
1528 g_signal_handlers_disconnect_matched (icon_view->priv->hadjustment, G_SIGNAL_MATCH_DATA,
1529 0, 0, NULL, NULL, icon_view);
1530 g_object_unref (icon_view->priv->hadjustment);
1533 if (icon_view->priv->vadjustment && (icon_view->priv->vadjustment != vadj))
1535 g_signal_handlers_disconnect_matched (icon_view->priv->vadjustment, G_SIGNAL_MATCH_DATA,
1536 0, 0, NULL, NULL, icon_view);
1537 g_object_unref (icon_view->priv->vadjustment);
1540 if (icon_view->priv->hadjustment != hadj)
1542 icon_view->priv->hadjustment = hadj;
1543 g_object_ref (icon_view->priv->hadjustment);
1544 gtk_object_sink (GTK_OBJECT (icon_view->priv->hadjustment));
1546 g_signal_connect (icon_view->priv->hadjustment, "value_changed",
1547 G_CALLBACK (gtk_icon_view_adjustment_changed),
1552 if (icon_view->priv->vadjustment != vadj)
1554 icon_view->priv->vadjustment = vadj;
1555 g_object_ref (icon_view->priv->vadjustment);
1556 gtk_object_sink (GTK_OBJECT (icon_view->priv->vadjustment));
1558 g_signal_connect (icon_view->priv->vadjustment, "value_changed",
1559 G_CALLBACK (gtk_icon_view_adjustment_changed),
1565 gtk_icon_view_adjustment_changed (NULL, icon_view);
1569 gtk_icon_view_real_select_all (GtkIconView *icon_view)
1571 gtk_icon_view_select_all (icon_view);
1575 gtk_icon_view_real_unselect_all (GtkIconView *icon_view)
1577 gtk_icon_view_unselect_all (icon_view);
1581 gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view)
1583 gtk_icon_view_unselect_all (icon_view);
1585 if (icon_view->priv->cursor_item != NULL)
1586 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
1590 gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view)
1594 if (!icon_view->priv->cursor_item)
1597 path = gtk_tree_path_new_from_indices (icon_view->priv->cursor_item->index, -1);
1599 gtk_icon_view_item_activated (icon_view, path);
1601 gtk_tree_path_free (path);
1607 gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view)
1609 if (!icon_view->priv->cursor_item)
1612 switch (icon_view->priv->selection_mode)
1614 case GTK_SELECTION_NONE:
1616 case GTK_SELECTION_BROWSE:
1617 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
1619 case GTK_SELECTION_SINGLE:
1620 if (icon_view->priv->cursor_item->selected)
1621 gtk_icon_view_unselect_item (icon_view, icon_view->priv->cursor_item);
1623 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
1625 case GTK_SELECTION_MULTIPLE:
1626 icon_view->priv->cursor_item->selected = !icon_view->priv->cursor_item->selected;
1627 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
1629 gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
1634 /* Internal functions */
1636 gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment,
1637 GtkIconView *icon_view)
1639 if (GTK_WIDGET_REALIZED (icon_view))
1641 gdk_window_move (icon_view->priv->bin_window,
1642 - icon_view->priv->hadjustment->value,
1643 - icon_view->priv->vadjustment->value);
1645 if (icon_view->priv->doing_rubberband)
1646 gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view));
1648 gdk_window_process_updates (icon_view->priv->bin_window, TRUE);
1653 gtk_icon_view_layout_single_row (GtkIconView *icon_view,
1658 gint *maximum_width)
1660 gint focus_width, focus_pad;
1661 gint x, current_width, max_height, max_pixbuf_height;
1662 GList *items, *last_item;
1665 gboolean rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL;
1670 max_pixbuf_height = 0;
1674 gtk_widget_style_get (GTK_WIDGET (icon_view),
1675 "focus-line-width", &focus_width,
1676 "focus-padding", &focus_pad,
1679 x += icon_view->priv->margin;
1680 current_width += 2 * icon_view->priv->margin;
1685 GtkIconViewItem *item = items->data;
1687 gtk_icon_view_calculate_item_size (icon_view, item, item_width);
1689 colspan = 1 + (item->width - 1) / (item_width + icon_view->priv->column_spacing);
1690 current_width += colspan * (item_width + icon_view->priv->column_spacing);
1692 if (items != first_item)
1694 if ((icon_view->priv->columns <= 0 && current_width > GTK_WIDGET (icon_view)->allocation.width) ||
1695 (icon_view->priv->columns > 0 && col >= icon_view->priv->columns))
1700 item->x = rtl ? GTK_WIDGET (icon_view)->allocation.width - MAX (item_width, item->width) - x : x;
1702 if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1706 item->layout_x = item->x + ICON_TEXT_PADDING + focus_width + focus_pad;
1707 if (icon_view->priv->text_column != -1 ||
1708 icon_view->priv->markup_column != -1)
1709 item->pixbuf_x = item->x + 2 * (ICON_TEXT_PADDING + focus_width + focus_pad) + icon_view->priv->spacing + item->layout_width;
1711 item->pixbuf_x = item->x;
1715 item->pixbuf_x = item->x;
1716 if (icon_view->priv->pixbuf_column != -1)
1717 item->layout_x = item->x + item->pixbuf_width + icon_view->priv->spacing + ICON_TEXT_PADDING + focus_width + focus_pad;
1719 item->layout_x = item->x + ICON_TEXT_PADDING + focus_width + focus_pad;
1724 if (item->width < colspan * item_width + (colspan - 1) * icon_view->priv->column_spacing)
1725 item->x += (colspan * item_width + (colspan - 1) * icon_view->priv->column_spacing - item->width) / 2;
1727 item->pixbuf_x = item->x + (item->width - item->pixbuf_width) / 2;
1728 item->layout_x = item->x + (item->width - item->layout_width) / 2;
1731 x = current_width - icon_view->priv->margin;
1733 max_height = MAX (max_height, item->height);
1734 max_pixbuf_height = MAX (max_pixbuf_height, item->pixbuf_height);
1736 if (current_width > *maximum_width)
1737 *maximum_width = current_width;
1743 items = items->next;
1748 *y += max_height + icon_view->priv->row_spacing;
1750 /* Now go through the row again and align the icons */
1751 for (items = first_item; items != last_item; items = items->next)
1753 GtkIconViewItem *item = items->data;
1755 if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1757 item->pixbuf_y = item->y;
1758 item->layout_y = item->y + ICON_TEXT_PADDING + focus_width + focus_pad;
1762 item->pixbuf_y = item->y + (max_pixbuf_height - item->pixbuf_height);
1763 if (icon_view->priv->pixbuf_column != -1)
1764 item->layout_y = item->pixbuf_y + item->pixbuf_height + icon_view->priv->spacing + ICON_TEXT_PADDING + focus_width + focus_pad;
1766 item->layout_y = item->y + ICON_TEXT_PADDING + focus_width + focus_pad;
1768 /* Update the bounding box */
1769 item->y = item->pixbuf_y;
1771 /* We may want to readjust the new y coordinate. */
1772 if (item->y + item->height > *y)
1773 *y = item->y + item->height;
1776 item->col = col - 1 - item->col;
1783 gtk_icon_view_set_adjustment_upper (GtkAdjustment *adj,
1786 if (upper != adj->upper)
1788 gdouble min = MAX (0.0, upper - adj->page_size);
1789 gboolean value_changed = FALSE;
1793 if (adj->value > min)
1796 value_changed = TRUE;
1799 gtk_adjustment_changed (adj);
1802 gtk_adjustment_value_changed (adj);
1807 gtk_icon_view_layout (GtkIconView *icon_view)
1809 gint y = 0, maximum_width = 0;
1815 if (!VALID_MODEL_AND_COLUMNS (icon_view))
1818 widget = GTK_WIDGET (icon_view);
1820 item_width = icon_view->priv->item_width;
1824 for (icons = icon_view->priv->items; icons; icons = icons->next)
1826 GtkIconViewItem *item = icons->data;
1827 gtk_icon_view_calculate_item_size (icon_view, item, -1);
1828 item_width = MAX (item_width, item->width);
1829 gtk_icon_view_item_invalidate_size (item);
1833 icons = icon_view->priv->items;
1834 y += icon_view->priv->margin;
1839 icons = gtk_icon_view_layout_single_row (icon_view, icons,
1841 &y, &maximum_width);
1844 while (icons != NULL);
1846 if (maximum_width != icon_view->priv->width)
1848 icon_view->priv->width = maximum_width;
1850 y += icon_view->priv->margin;
1852 if (y != icon_view->priv->height)
1854 icon_view->priv->height = y;
1857 gtk_icon_view_set_adjustment_upper (icon_view->priv->hadjustment, icon_view->priv->width);
1858 gtk_icon_view_set_adjustment_upper (icon_view->priv->vadjustment, icon_view->priv->height);
1860 if (GTK_WIDGET_REALIZED (icon_view))
1862 gdk_window_resize (icon_view->priv->bin_window,
1863 MAX (icon_view->priv->width, widget->allocation.width),
1864 MAX (icon_view->priv->height, widget->allocation.height));
1867 if (icon_view->priv->layout_idle_id != 0)
1869 g_source_remove (icon_view->priv->layout_idle_id);
1870 icon_view->priv->layout_idle_id = 0;
1873 gtk_widget_queue_draw (GTK_WIDGET (icon_view));
1876 /* Updates the pango layout and calculates the size */
1878 gtk_icon_view_calculate_item_size (GtkIconView *icon_view,
1879 GtkIconViewItem *item,
1882 gint focus_width, focus_pad;
1883 gint layout_width, layout_height;
1884 gint maximum_layout_width;
1885 gint spacing, padding;
1889 if (item->width != -1 && item->height != -1)
1892 gtk_widget_style_get (GTK_WIDGET (icon_view),
1893 "focus-line-width", &focus_width,
1894 "focus-padding", &focus_pad,
1897 spacing = icon_view->priv->spacing;
1899 if (icon_view->priv->pixbuf_column != -1)
1901 pixbuf = gtk_icon_view_get_item_icon (icon_view, item);
1902 item->pixbuf_width = gdk_pixbuf_get_width (pixbuf);
1903 item->pixbuf_height = gdk_pixbuf_get_height (pixbuf);
1904 g_object_unref (pixbuf);
1908 item->pixbuf_width = 0;
1909 item->pixbuf_height = 0;
1913 if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL &&
1916 colspan = item->pixbuf_width / item_width + 1;
1917 maximum_layout_width = MAX (colspan * item_width - item->pixbuf_width - icon_view->priv->spacing - 2 * (ICON_TEXT_PADDING + focus_width + focus_pad), 50);
1920 maximum_layout_width = MAX (item_width, item->pixbuf_width);
1922 if (icon_view->priv->markup_column != -1 ||
1923 icon_view->priv->text_column != -1)
1925 gtk_icon_view_update_item_text (icon_view, item);
1927 pango_layout_set_alignment (icon_view->priv->layout, PANGO_ALIGN_CENTER);
1928 pango_layout_set_width (icon_view->priv->layout, maximum_layout_width * PANGO_SCALE);
1930 pango_layout_get_pixel_size (icon_view->priv->layout, &layout_width, &layout_height);
1932 item->layout_width = layout_width;
1933 item->layout_height = layout_height;
1934 padding = 2 * (ICON_TEXT_PADDING + focus_width + focus_pad);
1938 item->layout_width = 0;
1939 item->layout_height = 0;
1944 if (icon_view->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
1946 item->width = item->layout_width + padding + spacing + item->pixbuf_width;
1947 item->height = MAX (item->layout_height + padding, item->pixbuf_height);
1951 item->width = MAX (item->layout_width + padding, item->pixbuf_width);
1952 item->height = item->layout_height + padding + spacing + item->pixbuf_height;
1957 gtk_icon_view_invalidate_sizes (GtkIconView *icon_view)
1959 g_list_foreach (icon_view->priv->items,
1960 (GFunc)gtk_icon_view_item_invalidate_size, NULL);
1964 gtk_icon_view_item_invalidate_size (GtkIconViewItem *item)
1971 create_colorized_pixbuf (GdkPixbuf *src, GdkColor *new_color)
1974 gint width, height, has_alpha, src_row_stride, dst_row_stride;
1975 gint red_value, green_value, blue_value;
1976 guchar *target_pixels;
1977 guchar *original_pixels;
1982 red_value = new_color->red / 255.0;
1983 green_value = new_color->green / 255.0;
1984 blue_value = new_color->blue / 255.0;
1986 dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
1987 gdk_pixbuf_get_has_alpha (src),
1988 gdk_pixbuf_get_bits_per_sample (src),
1989 gdk_pixbuf_get_width (src),
1990 gdk_pixbuf_get_height (src));
1992 has_alpha = gdk_pixbuf_get_has_alpha (src);
1993 width = gdk_pixbuf_get_width (src);
1994 height = gdk_pixbuf_get_height (src);
1995 src_row_stride = gdk_pixbuf_get_rowstride (src);
1996 dst_row_stride = gdk_pixbuf_get_rowstride (dest);
1997 target_pixels = gdk_pixbuf_get_pixels (dest);
1998 original_pixels = gdk_pixbuf_get_pixels (src);
2000 for (i = 0; i < height; i++) {
2001 pixdest = target_pixels + i*dst_row_stride;
2002 pixsrc = original_pixels + i*src_row_stride;
2003 for (j = 0; j < width; j++) {
2004 *pixdest++ = (*pixsrc++ * red_value) >> 8;
2005 *pixdest++ = (*pixsrc++ * green_value) >> 8;
2006 *pixdest++ = (*pixsrc++ * blue_value) >> 8;
2008 *pixdest++ = *pixsrc++;
2016 gtk_icon_view_paint_item (GtkIconView *icon_view,
2018 GtkIconViewItem *item,
2021 gint focus_width, focus_pad;
2022 GdkPixbuf *pixbuf, *tmp;
2024 gboolean rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL;
2026 if (!VALID_MODEL_AND_COLUMNS (icon_view))
2029 gtk_widget_style_get (GTK_WIDGET (icon_view),
2030 "focus-line-width", &focus_width,
2031 "focus-padding", &focus_pad,
2034 if (GTK_WIDGET_HAS_FOCUS (icon_view))
2035 state = GTK_STATE_SELECTED;
2037 state = GTK_STATE_ACTIVE;
2039 if (icon_view->priv->pixbuf_column != -1)
2041 tmp = gtk_icon_view_get_item_icon (icon_view, item);
2044 pixbuf = create_colorized_pixbuf (tmp,
2045 >K_WIDGET (icon_view)->style->base[state]);
2046 g_object_unref (tmp);
2051 cairo_move_to (cr, item->pixbuf_x, item->pixbuf_y);
2052 gdk_pixbuf_set_as_cairo_source (pixbuf, cr);
2053 g_object_unref (pixbuf);
2055 cairo_rectangle (cr,
2056 item->pixbuf_x, item->pixbuf_y,
2057 item->pixbuf_width, item->pixbuf_height);
2061 if (icon_view->priv->text_column != -1 ||
2062 icon_view->priv->markup_column != -1)
2066 gdk_cairo_set_source_color (cr, >K_WIDGET (icon_view)->style->base[state]);
2067 cairo_rectangle (cr,
2068 item->layout_x - ICON_TEXT_PADDING,
2069 item->layout_y - ICON_TEXT_PADDING,
2070 item->layout_width + 2 * ICON_TEXT_PADDING,
2071 item->layout_height + 2 * ICON_TEXT_PADDING);
2075 gtk_icon_view_update_item_text (icon_view, item);
2076 pango_layout_set_alignment (icon_view->priv->layout, rtl ? PANGO_ALIGN_RIGHT: PANGO_ALIGN_LEFT);
2077 pango_layout_set_width (icon_view->priv->layout, item->layout_width * PANGO_SCALE);
2078 gtk_paint_layout (GTK_WIDGET (icon_view)->style,
2079 icon_view->priv->bin_window,
2080 item->selected ? state : GTK_STATE_NORMAL,
2081 TRUE, area, GTK_WIDGET (icon_view), "icon_view",
2084 icon_view->priv->layout);
2086 if (GTK_WIDGET_HAS_FOCUS (icon_view) &&
2087 item == icon_view->priv->cursor_item)
2088 gtk_paint_focus (GTK_WIDGET (icon_view)->style,
2089 icon_view->priv->bin_window,
2092 GTK_WIDGET (icon_view),
2094 item->layout_x - ICON_TEXT_PADDING - focus_width - focus_pad,
2095 item->layout_y - ICON_TEXT_PADDING - focus_width - focus_pad,
2096 item->layout_width + 2 * (ICON_TEXT_PADDING + focus_width + focus_pad),
2097 item->layout_height + 2 * (ICON_TEXT_PADDING + focus_width + focus_pad));
2102 gtk_icon_view_paint_rubberband (GtkIconView *icon_view,
2107 GdkRectangle rubber_rect;
2108 GdkColor *fill_color_gdk;
2109 guchar fill_color_alpha;
2111 rubber_rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2);
2112 rubber_rect.y = MIN (icon_view->priv->rubberband_y1, icon_view->priv->rubberband_y2);
2113 rubber_rect.width = ABS (icon_view->priv->rubberband_x1 - icon_view->priv->rubberband_x2) + 1;
2114 rubber_rect.height = ABS (icon_view->priv->rubberband_y1 - icon_view->priv->rubberband_y2) + 1;
2116 if (!gdk_rectangle_intersect (&rubber_rect, area, &rect))
2119 gtk_widget_style_get (GTK_WIDGET (icon_view),
2120 "selection-box-color", &fill_color_gdk,
2121 "selection-box-alpha", &fill_color_alpha,
2124 if (!fill_color_gdk)
2125 fill_color_gdk = gdk_color_copy (>K_WIDGET (icon_view)->style->base[GTK_STATE_SELECTED]);
2127 cairo_set_source_rgba (cr,
2128 fill_color_gdk->red / 65535.,
2129 fill_color_gdk->green / 65535.,
2130 fill_color_gdk->blue / 65535.,
2131 fill_color_alpha / 255.);
2134 cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height);
2138 /* Draw the border without alpha */
2139 cairo_set_source_rgb (cr,
2140 fill_color_gdk->red / 65535.,
2141 fill_color_gdk->green / 65535.,
2142 fill_color_gdk->blue / 65535.);
2143 cairo_rectangle (cr,
2144 rubber_rect.x + 0.5, rubber_rect.y + 0.5,
2145 rubber_rect.width - 1, rubber_rect.height - 1);
2149 gdk_color_free (fill_color_gdk);
2153 gtk_icon_view_queue_draw_item (GtkIconView *icon_view,
2154 GtkIconViewItem *item)
2160 rect.width = item->width;
2161 rect.height = item->height;
2163 if (icon_view->priv->bin_window)
2164 gdk_window_invalidate_rect (icon_view->priv->bin_window, &rect, TRUE);
2168 layout_callback (gpointer user_data)
2170 GtkIconView *icon_view;
2172 GDK_THREADS_ENTER ();
2174 icon_view = GTK_ICON_VIEW (user_data);
2176 icon_view->priv->layout_idle_id = 0;
2178 gtk_icon_view_layout (icon_view);
2180 GDK_THREADS_LEAVE();
2186 gtk_icon_view_queue_layout (GtkIconView *icon_view)
2188 if (icon_view->priv->layout_idle_id != 0)
2191 icon_view->priv->layout_idle_id = g_idle_add (layout_callback, icon_view);
2195 gtk_icon_view_set_cursor_item (GtkIconView *icon_view,
2196 GtkIconViewItem *item)
2199 AtkObject *item_obj;
2201 if (icon_view->priv->cursor_item == item)
2204 if (icon_view->priv->cursor_item != NULL)
2205 gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
2207 icon_view->priv->cursor_item = item;
2208 gtk_icon_view_queue_draw_item (icon_view, item);
2210 /* Notify that accessible focus object has changed */
2211 obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
2212 item_obj = atk_object_ref_accessible_child (obj, item->index);
2214 if (item_obj != NULL)
2216 atk_focus_tracker_notify (item_obj);
2217 g_object_unref (item_obj);
2222 static GtkIconViewItem *
2223 gtk_icon_view_item_new (void)
2225 GtkIconViewItem *item;
2227 item = g_new0 (GtkIconViewItem, 1);
2236 gtk_icon_view_item_free (GtkIconViewItem *item)
2238 g_return_if_fail (item != NULL);
2244 gtk_icon_view_update_item_text (GtkIconView *icon_view,
2245 GtkIconViewItem *item)
2247 gboolean iters_persist;
2252 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
2256 path = gtk_tree_path_new_from_indices (item->index, -1);
2257 gtk_tree_model_get_iter (icon_view->priv->model, &iter, path);
2258 gtk_tree_path_free (path);
2263 if (icon_view->priv->markup_column != -1)
2265 gtk_tree_model_get (icon_view->priv->model, &iter,
2266 icon_view->priv->markup_column, &text,
2268 pango_layout_set_markup (icon_view->priv->layout, text, -1);
2271 else if (icon_view->priv->text_column != -1)
2273 gtk_tree_model_get (icon_view->priv->model, &iter,
2274 icon_view->priv->text_column, &text,
2276 pango_layout_set_text (icon_view->priv->layout, text, -1);
2280 pango_layout_set_text (icon_view->priv->layout, "", -1);
2284 gtk_icon_view_get_item_icon (GtkIconView *icon_view,
2285 GtkIconViewItem *item)
2287 gboolean iters_persist;
2292 g_return_val_if_fail (item != NULL, NULL);
2294 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
2298 path = gtk_tree_path_new_from_indices (item->index, -1);
2299 gtk_tree_model_get_iter (icon_view->priv->model, &iter, path);
2300 gtk_tree_path_free (path);
2305 gtk_tree_model_get (icon_view->priv->model, &iter,
2306 icon_view->priv->pixbuf_column, &pixbuf,
2313 static GtkIconViewItem *
2314 gtk_icon_view_get_item_at_pos (GtkIconView *icon_view,
2320 for (items = icon_view->priv->items; items; items = items->next)
2322 GtkIconViewItem *item = items->data;
2324 if (x > item->x && x < item->x + item->width &&
2325 y > item->y && y < item->y + item->height)
2327 /* Check if the mouse is inside the icon or the label */
2328 if ((x > item->pixbuf_x && x < item->pixbuf_x + item->pixbuf_width &&
2329 y > item->pixbuf_y && y < item->pixbuf_y + item->pixbuf_height) ||
2330 (x > item->layout_x - ICON_TEXT_PADDING &&
2331 x < item->layout_x + item->layout_width + ICON_TEXT_PADDING &&
2332 y > item->layout_y - ICON_TEXT_PADDING &&
2333 y < item->layout_y + item->layout_height + ICON_TEXT_PADDING))
2342 gtk_icon_view_select_item (GtkIconView *icon_view,
2343 GtkIconViewItem *item)
2345 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
2346 g_return_if_fail (item != NULL);
2351 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
2353 else if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
2354 gtk_icon_view_unselect_all_internal (icon_view);
2356 item->selected = TRUE;
2358 gtk_icon_view_queue_draw_item (icon_view, item);
2360 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2365 gtk_icon_view_unselect_item (GtkIconView *icon_view,
2366 GtkIconViewItem *item)
2368 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
2369 g_return_if_fail (item != NULL);
2371 if (!item->selected)
2374 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE ||
2375 icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
2378 item->selected = FALSE;
2380 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2382 gtk_icon_view_queue_draw_item (icon_view, item);
2386 verify_items (GtkIconView *icon_view)
2391 for (items = icon_view->priv->items; items; items = items->next)
2393 GtkIconViewItem *item = items->data;
2395 if (item->index != i)
2396 g_error ("List item does not match its index: item index %d and list index %d\n", item->index, i);
2403 gtk_icon_view_row_changed (GtkTreeModel *model,
2408 GtkIconViewItem *item;
2410 GtkIconView *icon_view;
2412 icon_view = GTK_ICON_VIEW (data);
2414 index = gtk_tree_path_get_indices(path)[0];
2415 item = g_list_nth (icon_view->priv->items, index)->data;
2417 gtk_icon_view_item_invalidate_size (item);
2418 gtk_icon_view_queue_layout (icon_view);
2420 verify_items (icon_view);
2424 gtk_icon_view_row_inserted (GtkTreeModel *model,
2430 GtkIconViewItem *item;
2431 gboolean iters_persist;
2432 GtkIconView *icon_view;
2435 icon_view = GTK_ICON_VIEW (data);
2436 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
2438 length = gtk_tree_model_iter_n_children (model, NULL);
2439 index = gtk_tree_path_get_indices(path)[0];
2441 item = gtk_icon_view_item_new ();
2446 item->index = index;
2448 /* FIXME: We can be more efficient here,
2449 we can store a tail pointer and use that when
2450 appending (which is a rather common operation)
2452 icon_view->priv->items = g_list_insert (icon_view->priv->items,
2455 list = g_list_nth (icon_view->priv->items, index + 1);
2456 for (; list; list = list->next)
2463 verify_items (icon_view);
2467 gtk_icon_view_row_deleted (GtkTreeModel *model,
2472 GtkIconView *icon_view;
2473 GtkIconViewItem *item;
2475 gboolean emit = FALSE;
2477 icon_view = GTK_ICON_VIEW (data);
2479 index = gtk_tree_path_get_indices(path)[0];
2481 list = g_list_nth (icon_view->priv->items, index);
2484 if (item == icon_view->priv->anchor_item)
2485 icon_view->priv->anchor_item = NULL;
2487 if (item == icon_view->priv->cursor_item)
2488 icon_view->priv->cursor_item = NULL;
2493 gtk_icon_view_item_free (item);
2495 for (next = list->next; next; next = next->next)
2502 icon_view->priv->items = g_list_delete_link (icon_view->priv->items, list);
2504 gtk_icon_view_queue_layout (icon_view);
2506 verify_items (icon_view);
2509 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2513 gtk_icon_view_rows_reordered (GtkTreeModel *model,
2514 GtkTreePath *parent,
2521 GtkIconView *icon_view;
2522 GList *items = NULL, *list;
2523 GtkIconViewItem **item_array;
2526 icon_view = GTK_ICON_VIEW (data);
2528 length = gtk_tree_model_iter_n_children (model, NULL);
2530 order = g_new (gint, length);
2531 for (i = 0; i < length; i++)
2532 order [new_order[i]] = i;
2534 item_array = g_new (GtkIconViewItem *, length);
2535 for (i = 0, list = icon_view->priv->items; list != NULL; list = list->next, i++)
2536 item_array[order[i]] = list->data;
2539 for (i = length - 1; i >= 0; i--)
2541 item_array[i]->index = i;
2542 items = g_list_prepend (items, item_array[i]);
2545 g_free (item_array);
2546 g_list_free (icon_view->priv->items);
2547 icon_view->priv->items = items;
2549 gtk_icon_view_queue_layout (icon_view);
2551 verify_items (icon_view);
2555 gtk_icon_view_build_items (GtkIconView *icon_view)
2559 gboolean iters_persist;
2560 GList *items = NULL;
2562 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
2564 if (!gtk_tree_model_get_iter_first (icon_view->priv->model,
2572 GtkIconViewItem *item = gtk_icon_view_item_new ();
2581 items = g_list_prepend (items, item);
2583 } while (gtk_tree_model_iter_next (icon_view->priv->model, &iter));
2585 icon_view->priv->items = g_list_reverse (items);
2589 gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
2592 GtkMovementStep step,
2596 gtk_binding_entry_add_signal (binding_set, keyval, modmask,
2601 gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
2606 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
2609 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
2614 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
2621 gtk_icon_view_real_move_cursor (GtkIconView *icon_view,
2622 GtkMovementStep step,
2625 GdkModifierType state;
2627 g_return_val_if_fail (GTK_ICON_VIEW (icon_view), FALSE);
2628 g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
2629 step == GTK_MOVEMENT_VISUAL_POSITIONS ||
2630 step == GTK_MOVEMENT_DISPLAY_LINES ||
2631 step == GTK_MOVEMENT_PAGES ||
2632 step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
2634 if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (icon_view)))
2637 gtk_widget_grab_focus (GTK_WIDGET (icon_view));
2639 if (gtk_get_current_event_state (&state))
2641 if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
2642 icon_view->priv->ctrl_pressed = TRUE;
2643 if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
2644 icon_view->priv->shift_pressed = TRUE;
2646 /* else we assume not pressed */
2650 case GTK_MOVEMENT_LOGICAL_POSITIONS:
2651 case GTK_MOVEMENT_VISUAL_POSITIONS:
2652 gtk_icon_view_move_cursor_left_right (icon_view, count);
2654 case GTK_MOVEMENT_DISPLAY_LINES:
2655 gtk_icon_view_move_cursor_up_down (icon_view, count);
2657 case GTK_MOVEMENT_PAGES:
2658 gtk_icon_view_move_cursor_page_up_down (icon_view, count);
2660 case GTK_MOVEMENT_BUFFER_ENDS:
2661 gtk_icon_view_move_cursor_start_end (icon_view, count);
2664 g_assert_not_reached ();
2667 icon_view->priv->ctrl_pressed = FALSE;
2668 icon_view->priv->shift_pressed = FALSE;
2673 static GtkIconViewItem *
2674 find_item (GtkIconView *icon_view,
2675 GtkIconViewItem *current,
2681 GtkIconViewItem *item;
2683 /* FIXME: this could be more efficient
2685 row = current->row + row_ofs;
2686 col = current->col + col_ofs;
2688 for (items = icon_view->priv->items; items; items = items->next)
2691 if (item->row == row && item->col == col)
2699 static GtkIconViewItem *
2700 find_item_page_up_down (GtkIconView *icon_view,
2701 GtkIconViewItem *current,
2708 y = current->y + count * icon_view->priv->vadjustment->page_size;
2710 item = g_list_find (icon_view->priv->items, current);
2715 for (next = item->next; next; next = next->next)
2717 if (((GtkIconViewItem *)next->data)->col == col)
2720 if (!next || ((GtkIconViewItem *)next->data)->y > y)
2730 for (next = item->prev; next; next = next->prev)
2732 if (((GtkIconViewItem *)next->data)->col == col)
2735 if (!next || ((GtkIconViewItem *)next->data)->y < y)
2749 gtk_icon_view_select_all_between (GtkIconView *icon_view,
2750 GtkIconViewItem *anchor,
2751 GtkIconViewItem *cursor)
2754 GtkIconViewItem *item;
2755 gint row1, row2, col1, col2;
2756 gboolean dirty = FALSE;
2758 if (anchor->row < cursor->row)
2769 if (anchor->col < cursor->col)
2780 for (items = icon_view->priv->items; items; items = items->next)
2784 if (row1 <= item->row && item->row <= row2 &&
2785 col1 <= item->col && item->col <= col2)
2787 if (!item->selected)
2790 item->selected = TRUE;
2792 gtk_icon_view_queue_draw_item (icon_view, item);
2800 gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
2803 GtkIconViewItem *item;
2804 gboolean dirty = FALSE;
2806 if (!GTK_WIDGET_HAS_FOCUS (icon_view))
2809 if (!icon_view->priv->cursor_item)
2814 list = icon_view->priv->items;
2816 list = g_list_last (icon_view->priv->items);
2818 item = list ? list->data : NULL;
2821 item = find_item (icon_view,
2822 icon_view->priv->cursor_item,
2828 if (icon_view->priv->ctrl_pressed ||
2829 !icon_view->priv->shift_pressed ||
2830 !icon_view->priv->anchor_item ||
2831 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
2832 icon_view->priv->anchor_item = item;
2834 gtk_icon_view_set_cursor_item (icon_view, item);
2836 if (!icon_view->priv->ctrl_pressed &&
2837 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
2839 gtk_icon_view_unselect_all_internal (icon_view);
2840 dirty = gtk_icon_view_select_all_between (icon_view,
2841 icon_view->priv->anchor_item,
2845 gtk_icon_view_scroll_to_item (icon_view, item);
2848 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2852 gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
2855 GtkIconViewItem *item;
2856 gboolean dirty = FALSE;
2858 if (!GTK_WIDGET_HAS_FOCUS (icon_view))
2861 if (!icon_view->priv->cursor_item)
2866 list = icon_view->priv->items;
2868 list = g_list_last (icon_view->priv->items);
2870 item = list ? list->data : NULL;
2873 item = find_item_page_up_down (icon_view,
2874 icon_view->priv->cursor_item,
2880 if (icon_view->priv->ctrl_pressed ||
2881 !icon_view->priv->shift_pressed ||
2882 !icon_view->priv->anchor_item ||
2883 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
2884 icon_view->priv->anchor_item = item;
2886 gtk_icon_view_set_cursor_item (icon_view, item);
2888 if (!icon_view->priv->ctrl_pressed &&
2889 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
2891 gtk_icon_view_unselect_all_internal (icon_view);
2892 dirty = gtk_icon_view_select_all_between (icon_view,
2893 icon_view->priv->anchor_item,
2897 gtk_icon_view_scroll_to_item (icon_view, item);
2900 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2904 gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
2907 GtkIconViewItem *item;
2908 gboolean dirty = FALSE;
2910 if (!GTK_WIDGET_HAS_FOCUS (icon_view))
2913 if (!icon_view->priv->cursor_item)
2918 list = icon_view->priv->items;
2920 list = g_list_last (icon_view->priv->items);
2922 item = list ? list->data : NULL;
2925 item = find_item (icon_view,
2926 icon_view->priv->cursor_item,
2932 if (icon_view->priv->ctrl_pressed ||
2933 !icon_view->priv->shift_pressed ||
2934 !icon_view->priv->anchor_item ||
2935 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
2936 icon_view->priv->anchor_item = item;
2938 gtk_icon_view_set_cursor_item (icon_view, item);
2940 if (!icon_view->priv->ctrl_pressed &&
2941 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
2943 gtk_icon_view_unselect_all_internal (icon_view);
2944 dirty = gtk_icon_view_select_all_between (icon_view,
2945 icon_view->priv->anchor_item,
2949 gtk_icon_view_scroll_to_item (icon_view, item);
2952 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2956 gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
2959 GtkIconViewItem *item;
2961 gboolean dirty = FALSE;
2963 if (!GTK_WIDGET_HAS_FOCUS (icon_view))
2967 list = icon_view->priv->items;
2969 list = g_list_last (icon_view->priv->items);
2971 item = list ? list->data : NULL;
2976 if (icon_view->priv->ctrl_pressed ||
2977 !icon_view->priv->shift_pressed ||
2978 !icon_view->priv->anchor_item ||
2979 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
2980 icon_view->priv->anchor_item = item;
2982 gtk_icon_view_set_cursor_item (icon_view, item);
2984 if (!icon_view->priv->ctrl_pressed &&
2985 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
2987 gtk_icon_view_unselect_all (icon_view);
2988 dirty = gtk_icon_view_select_all_between (icon_view,
2989 icon_view->priv->anchor_item,
2993 gtk_icon_view_scroll_to_item (icon_view, item);
2996 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3000 gtk_icon_view_scroll_to_item (GtkIconView *icon_view,
3001 GtkIconViewItem *item)
3003 gint x, y, width, height;
3006 gdk_drawable_get_size (GDK_DRAWABLE (icon_view->priv->bin_window), &width, &height);
3007 gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
3009 if (y + item->y < 0)
3011 value = icon_view->priv->vadjustment->value + y + item->y;
3012 gtk_adjustment_set_value (icon_view->priv->vadjustment, value);
3014 else if (y + item->y + item->height > GTK_WIDGET (icon_view)->allocation.height)
3016 value = icon_view->priv->vadjustment->value + y + item->y + item->height
3017 - GTK_WIDGET (icon_view)->allocation.height;
3018 value = MIN (value, icon_view->priv->vadjustment->value + y + item->y);
3019 gtk_adjustment_set_value (icon_view->priv->vadjustment, value);
3022 if (x + item->x < 0)
3024 value = icon_view->priv->hadjustment->value + x + item->x;
3025 gtk_adjustment_set_value (icon_view->priv->hadjustment, value);
3027 else if (x + item->x + item->width > GTK_WIDGET (icon_view)->allocation.width)
3029 value = icon_view->priv->hadjustment->value + x + item->x + item->width
3030 - GTK_WIDGET (icon_view)->allocation.width;
3031 value = MIN (value, icon_view->priv->hadjustment->value + x + item->x);
3032 gtk_adjustment_set_value (icon_view->priv->hadjustment, value);
3040 * gtk_icon_view_new:
3042 * Creates a new #GtkIconView widget
3044 * Return value: A newly created #GtkIconView widget
3049 gtk_icon_view_new (void)
3051 return g_object_new (GTK_TYPE_ICON_VIEW, NULL);
3055 * gtk_icon_view_new_with_model:
3056 * @model: The model.
3058 * Creates a new #GtkIconView widget with the model @model.
3060 * Return value: A newly created #GtkIconView widget.
3065 gtk_icon_view_new_with_model (GtkTreeModel *model)
3067 return g_object_new (GTK_TYPE_ICON_VIEW, "model", model, NULL);
3072 * gtk_icon_view_get_path_at_pos:
3073 * @icon_view: A #GtkIconView.
3074 * @x: The x position to be identified
3075 * @y: The y position to be identified
3077 * Finds the path at the point (@x, @y), relative to widget coordinates.
3079 * Return value: The #GtkTreePath corresponding to the icon or %NULL
3080 * if no icon exists at that position.
3085 gtk_icon_view_get_path_at_pos (GtkIconView *icon_view,
3089 GtkIconViewItem *item;
3092 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
3094 item = gtk_icon_view_get_item_at_pos (icon_view, x, y);
3099 path = gtk_tree_path_new_from_indices (item->index, -1);
3105 * gtk_icon_view_selected_foreach:
3106 * @icon_view: A #GtkIconView.
3107 * @func: The funcion to call for each selected icon.
3108 * @data: User data to pass to the function.
3110 * Calls a function for each selected icon. Note that the model or
3111 * selection cannot be modified from within this function.
3116 gtk_icon_view_selected_foreach (GtkIconView *icon_view,
3117 GtkIconViewForeachFunc func,
3122 for (list = icon_view->priv->items; list; list = list->next)
3124 GtkIconViewItem *item = list->data;
3125 GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
3128 (* func) (icon_view, path, data);
3130 gtk_tree_path_free (path);
3135 * gtk_icon_view_set_selection_mode:
3136 * @icon_view: A #GtkIconView.
3137 * @mode: The selection mode
3139 * Sets the selection mode of the @icon_view.
3144 gtk_icon_view_set_selection_mode (GtkIconView *icon_view,
3145 GtkSelectionMode mode)
3147 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3149 if (mode == icon_view->priv->selection_mode)
3152 if (mode == GTK_SELECTION_NONE ||
3153 icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
3154 gtk_icon_view_unselect_all (icon_view);
3156 icon_view->priv->selection_mode = mode;
3158 g_object_notify (G_OBJECT (icon_view), "selection-mode");
3162 * gtk_icon_view_get_selection_mode:
3163 * @icon_view: A #GtkIconView.
3165 * Gets the selection mode of the @icon_view.
3167 * Return value: the current selection mode
3172 gtk_icon_view_get_selection_mode (GtkIconView *icon_view)
3174 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), GTK_SELECTION_SINGLE);
3176 return icon_view->priv->selection_mode;
3180 * gtk_icon_view_set_model:
3181 * @icon_view: A #GtkIconView.
3182 * @model: The model.
3184 * Sets the model for a #GtkIconView.
3185 * If the @icon_view already has a model set, it will remove
3186 * it before setting the new model. If @model is %NULL, then
3187 * it will unset the old model.
3192 gtk_icon_view_set_model (GtkIconView *icon_view,
3193 GtkTreeModel *model)
3195 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3196 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
3198 if (icon_view->priv->model == model)
3205 g_return_if_fail (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY);
3207 if (icon_view->priv->pixbuf_column != -1)
3209 column_type = gtk_tree_model_get_column_type (model,
3210 icon_view->priv->pixbuf_column);
3212 g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
3215 if (icon_view->priv->text_column != -1)
3217 column_type = gtk_tree_model_get_column_type (model,
3218 icon_view->priv->text_column);
3220 g_return_if_fail (column_type == G_TYPE_STRING);
3223 if (icon_view->priv->markup_column != -1)
3225 column_type = gtk_tree_model_get_column_type (model,
3226 icon_view->priv->markup_column);
3228 g_return_if_fail (column_type == G_TYPE_STRING);
3233 if (icon_view->priv->model)
3235 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
3236 gtk_icon_view_row_changed,
3238 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
3239 gtk_icon_view_row_inserted,
3241 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
3242 gtk_icon_view_row_deleted,
3244 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
3245 gtk_icon_view_rows_reordered,
3248 g_object_unref (icon_view->priv->model);
3250 g_list_foreach (icon_view->priv->items, (GFunc)gtk_icon_view_item_free, NULL);
3251 g_list_free (icon_view->priv->items);
3252 icon_view->priv->items = NULL;
3253 icon_view->priv->anchor_item = NULL;
3254 icon_view->priv->cursor_item = NULL;
3255 icon_view->priv->last_single_clicked = NULL;
3256 icon_view->priv->width = 0;
3257 icon_view->priv->height = 0;
3260 icon_view->priv->model = model;
3262 if (icon_view->priv->model)
3264 g_object_ref (icon_view->priv->model);
3265 g_signal_connect (icon_view->priv->model,
3267 G_CALLBACK (gtk_icon_view_row_changed),
3269 g_signal_connect (icon_view->priv->model,
3271 G_CALLBACK (gtk_icon_view_row_inserted),
3273 g_signal_connect (icon_view->priv->model,
3275 G_CALLBACK (gtk_icon_view_row_deleted),
3277 g_signal_connect (icon_view->priv->model,
3279 G_CALLBACK (gtk_icon_view_rows_reordered),
3282 gtk_icon_view_build_items (icon_view);
3284 gtk_icon_view_queue_layout (icon_view);
3287 g_object_notify (G_OBJECT (icon_view), "model");
3289 if (GTK_WIDGET_REALIZED (icon_view))
3290 gtk_widget_queue_resize (GTK_WIDGET (icon_view));
3294 * gtk_icon_view_get_model:
3295 * @icon_view: a #GtkIconView
3297 * Returns the model the #GtkIconView is based on. Returns %NULL if the
3300 * Return value: A #GtkTreeModel, or %NULL if none is currently being used.
3305 gtk_icon_view_get_model (GtkIconView *icon_view)
3307 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
3309 return icon_view->priv->model;
3313 * gtk_icon_view_set_text_column:
3314 * @icon_view: A #GtkIconView.
3315 * @column: A column in the currently used model.
3317 * Sets the column with text for @icon_view to be @column. The text
3318 * column must be of type #G_TYPE_STRING.
3323 gtk_icon_view_set_text_column (GtkIconView *icon_view,
3326 if (column == icon_view->priv->text_column)
3330 icon_view->priv->text_column = -1;
3333 if (icon_view->priv->model != NULL)
3337 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
3339 g_return_if_fail (column_type == G_TYPE_STRING);
3342 icon_view->priv->text_column = column;
3345 gtk_icon_view_invalidate_sizes (icon_view);
3346 gtk_icon_view_queue_layout (icon_view);
3348 g_object_notify (G_OBJECT (icon_view), "text-column");
3352 * gtk_icon_view_get_text_column:
3353 * @icon_view: A #GtkIconView.
3355 * Returns the column with text for @icon_view.
3357 * Returns: the text column, or -1 if it's unset.
3362 gtk_icon_view_get_text_column (GtkIconView *icon_view)
3364 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3366 return icon_view->priv->text_column;
3370 * gtk_icon_view_set_markup_column:
3371 * @icon_view: A #GtkIconView.
3372 * @column: A column in the currently used model.
3374 * Sets the column with markup information for @icon_view to be
3375 * @column. The markup column must be of type #G_TYPE_STRING.
3376 * If the markup column is set to something, it overrides
3377 * the text column set by gtk_icon_view_set_text_column().
3382 gtk_icon_view_set_markup_column (GtkIconView *icon_view,
3385 if (column == icon_view->priv->markup_column)
3389 icon_view->priv->markup_column = -1;
3392 if (icon_view->priv->model != NULL)
3396 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
3398 g_return_if_fail (column_type == G_TYPE_STRING);
3401 icon_view->priv->markup_column = column;
3404 gtk_icon_view_invalidate_sizes (icon_view);
3405 gtk_icon_view_queue_layout (icon_view);
3407 g_object_notify (G_OBJECT (icon_view), "markup-column");
3411 * gtk_icon_view_get_markup_column:
3412 * @icon_view: A #GtkIconView.
3414 * Returns the column with markup text for @icon_view.
3416 * Returns: the markup column, or -1 if it's unset.
3421 gtk_icon_view_get_markup_column (GtkIconView *icon_view)
3423 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3425 return icon_view->priv->markup_column;
3429 * gtk_icon_view_set_pixbuf_column:
3430 * @icon_view: A #GtkIconView.
3431 * @column: A column in the currently used model.
3433 * Sets the column with pixbufs for @icon_view to be @column. The pixbuf
3434 * column must be of type #GDK_TYPE_PIXBUF
3439 gtk_icon_view_set_pixbuf_column (GtkIconView *icon_view,
3442 if (column == icon_view->priv->pixbuf_column)
3446 icon_view->priv->pixbuf_column = -1;
3449 if (icon_view->priv->model != NULL)
3453 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
3455 g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
3458 icon_view->priv->pixbuf_column = column;
3461 gtk_icon_view_invalidate_sizes (icon_view);
3462 gtk_icon_view_queue_layout (icon_view);
3464 g_object_notify (G_OBJECT (icon_view), "pixbuf-column");
3469 * gtk_icon_view_get_pixbuf_column:
3470 * @icon_view: A #GtkIconView.
3472 * Returns the column with pixbufs for @icon_view.
3474 * Returns: the pixbuf column, or -1 if it's unset.
3479 gtk_icon_view_get_pixbuf_column (GtkIconView *icon_view)
3481 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3483 return icon_view->priv->pixbuf_column;
3487 * gtk_icon_view_select_path:
3488 * @icon_view: A #GtkIconView.
3489 * @path: The #GtkTreePath to be selected.
3491 * Selects the row at @path.
3496 gtk_icon_view_select_path (GtkIconView *icon_view,
3501 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3502 g_return_if_fail (icon_view->priv->model != NULL);
3503 g_return_if_fail (path != NULL);
3505 l = g_list_nth (icon_view->priv->items,
3506 gtk_tree_path_get_indices(path)[0]);
3509 gtk_icon_view_select_item (icon_view, l->data);
3513 * gtk_icon_view_unselect_path:
3514 * @icon_view: A #GtkIconView.
3515 * @path: The #GtkTreePath to be unselected.
3517 * Unselects the row at @path.
3522 gtk_icon_view_unselect_path (GtkIconView *icon_view,
3525 GtkIconViewItem *item;
3527 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3528 g_return_if_fail (icon_view->priv->model != NULL);
3529 g_return_if_fail (path != NULL);
3531 item = g_list_nth (icon_view->priv->items,
3532 gtk_tree_path_get_indices(path)[0])->data;
3537 gtk_icon_view_unselect_item (icon_view, item);
3541 * gtk_icon_view_get_selected_items:
3542 * @icon_view: A #GtkIconView.
3544 * Creates a list of paths of all selected items. Additionally, if you are
3545 * planning on modifying the model after calling this function, you may
3546 * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
3547 * To do this, you can use gtk_tree_row_reference_new().
3549 * To free the return value, use:
3550 * <informalexample><programlisting>
3551 * g_list_foreach (list, gtk_tree_path_free, NULL);
3552 * g_list_free (list);
3553 * </programlisting></informalexample>
3555 * Return value: A #GList containing a #GtkTreePath for each selected row.
3560 gtk_icon_view_get_selected_items (GtkIconView *icon_view)
3563 GList *selected = NULL;
3565 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
3567 for (list = icon_view->priv->items; list != NULL; list = list->next)
3569 GtkIconViewItem *item = list->data;
3573 GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
3575 selected = g_list_prepend (selected, path);
3583 * gtk_icon_view_select_all:
3584 * @icon_view: A #GtkIconView.
3586 * Selects all the icons. @icon_view must has its selection mode set
3587 * to #GTK_SELECTION_MULTIPLE.
3592 gtk_icon_view_select_all (GtkIconView *icon_view)
3595 gboolean dirty = FALSE;
3597 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3599 if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
3602 for (items = icon_view->priv->items; items; items = items->next)
3604 GtkIconViewItem *item = items->data;
3606 if (!item->selected)
3609 item->selected = TRUE;
3610 gtk_icon_view_queue_draw_item (icon_view, item);
3615 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3619 * gtk_icon_view_unselect_all:
3620 * @icon_view: A #GtkIconView.
3622 * Unselects all the icons.
3627 gtk_icon_view_unselect_all (GtkIconView *icon_view)
3629 gboolean dirty = FALSE;
3631 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3633 if (icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
3636 dirty = gtk_icon_view_unselect_all_internal (icon_view);
3639 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3643 * gtk_icon_view_path_is_selected:
3644 * @icon_view: A #GtkIconView.
3645 * @path: A #GtkTreePath to check selection on.
3647 * Returns %TRUE if the icon pointed to by @path is currently
3648 * selected. If @icon does not point to a valid location, %FALSE is returned.
3650 * Return value: %TRUE if @path is selected.
3655 gtk_icon_view_path_is_selected (GtkIconView *icon_view,
3658 GtkIconViewItem *item;
3660 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
3661 g_return_val_if_fail (icon_view->priv->model != NULL, FALSE);
3662 g_return_val_if_fail (path != NULL, FALSE);
3664 item = g_list_nth (icon_view->priv->items,
3665 gtk_tree_path_get_indices(path)[0])->data;
3670 return item->selected;
3674 * gtk_icon_view_item_activated:
3675 * @icon_view: A #GtkIconView
3676 * @path: The #GtkTreePath to be activated
3678 * Activates the item determined by @path.
3683 gtk_icon_view_item_activated (GtkIconView *icon_view,
3686 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3687 g_return_if_fail (path != NULL);
3689 g_signal_emit (icon_view, icon_view_signals[ITEM_ACTIVATED], 0, path);
3693 * gtk_icon_view_set_orientation:
3694 * @icon_view: a #GtkIconView
3695 * @orientation: the relative position of texts and icons
3697 * Sets the ::orientation property which determines whether the labels
3698 * are drawn beside the icons instead of below.
3703 gtk_icon_view_set_orientation (GtkIconView *icon_view,
3704 GtkOrientation orientation)
3706 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3708 if (icon_view->priv->orientation != orientation)
3710 icon_view->priv->orientation = orientation;
3712 gtk_icon_view_invalidate_sizes (icon_view);
3713 gtk_icon_view_queue_layout (icon_view);
3715 g_object_notify (G_OBJECT (icon_view), "orientation");
3720 * gtk_icon_view_get_orientation:
3721 * @icon_view: a #GtkIconView
3723 * Returns the value of the ::orientation property which determines
3724 * whether the labels are drawn beside the icons instead of below.
3726 * Return value: the relative position of texts and icons
3731 gtk_icon_view_get_orientation (GtkIconView *icon_view)
3733 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view),
3734 GTK_ORIENTATION_VERTICAL);
3736 return icon_view->priv->orientation;
3740 * gtk_icon_view_set_columns:
3741 * @icon_view: a #GtkIconView
3742 * @columns: the number of columns
3744 * Sets the ::columns property which determines in how
3745 * many columns the icons are arranged. If @columns is
3746 * -1, the number of columns will be chosen automatically
3747 * to fill the available area.
3752 gtk_icon_view_set_columns (GtkIconView *icon_view,
3755 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3757 if (icon_view->priv->columns != columns)
3759 icon_view->priv->columns = columns;
3761 gtk_icon_view_queue_layout (icon_view);
3763 g_object_notify (G_OBJECT (icon_view), "columns");
3768 * gtk_icon_view_get_columns:
3769 * @icon_view: a #GtkIconView
3771 * Returns the value of the ::columns property.
3773 * Return value: the number of columns, or -1
3778 gtk_icon_view_get_columns (GtkIconView *icon_view)
3780 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3782 return icon_view->priv->columns;
3786 * gtk_icon_view_set_item_width:
3787 * @icon_view: a #GtkIconView
3788 * @item_width: the width for each item
3790 * Sets the ::item-width property which specifies the width
3791 * to use for each item. If it is set to -1, the icon view will
3792 * automatically determine a suitable item size.
3797 gtk_icon_view_set_item_width (GtkIconView *icon_view,
3800 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3802 if (icon_view->priv->item_width != item_width)
3804 icon_view->priv->item_width = item_width;
3806 gtk_icon_view_invalidate_sizes (icon_view);
3807 gtk_icon_view_queue_layout (icon_view);
3809 g_object_notify (G_OBJECT (icon_view), "item-width");
3814 * gtk_icon_view_get_item_width:
3815 * @icon_view: a #GtkIconView
3817 * Returns the value of the ::item-width property.
3819 * Return value: the width of a single item, or -1
3824 gtk_icon_view_get_item_width (GtkIconView *icon_view)
3826 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3828 return icon_view->priv->item_width;
3833 * gtk_icon_view_set_spacing:
3834 * @icon_view: a #GtkIconView
3835 * @spacing: the spacing
3837 * Sets the ::spacing property which specifies the space
3838 * which is inserted between the cells (i.e. the icon and
3839 * the text) of an item.
3844 gtk_icon_view_set_spacing (GtkIconView *icon_view,
3847 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3849 if (icon_view->priv->spacing != spacing)
3851 icon_view->priv->spacing = spacing;
3853 gtk_icon_view_invalidate_sizes (icon_view);
3854 gtk_icon_view_queue_layout (icon_view);
3856 g_object_notify (G_OBJECT (icon_view), "spacing");
3861 * gtk_icon_view_get_spacing:
3862 * @icon_view: a #GtkIconView
3864 * Returns the value of the ::spacing property.
3866 * Return value: the space between cells
3871 gtk_icon_view_get_spacing (GtkIconView *icon_view)
3873 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3875 return icon_view->priv->spacing;
3879 * gtk_icon_view_set_row_spacing:
3880 * @icon_view: a #GtkIconView
3881 * @row_spacing: the row spacing
3883 * Sets the ::row-spacing property which specifies the space
3884 * which is inserted between the rows of the icon view.
3889 gtk_icon_view_set_row_spacing (GtkIconView *icon_view,
3892 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3894 if (icon_view->priv->row_spacing != row_spacing)
3896 icon_view->priv->row_spacing = row_spacing;
3898 gtk_icon_view_invalidate_sizes (icon_view);
3899 gtk_icon_view_queue_layout (icon_view);
3901 g_object_notify (G_OBJECT (icon_view), "row-spacing");
3906 * gtk_icon_view_get_row_spacing:
3907 * @icon_view: a #GtkIconView
3909 * Returns the value of the ::row-spacing property.
3911 * Return value: the space between rows
3916 gtk_icon_view_get_row_spacing (GtkIconView *icon_view)
3918 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3920 return icon_view->priv->row_spacing;
3924 * gtk_icon_view_set_column_spacing:
3925 * @icon_view: a #GtkIconView
3926 * @column_spacing: the column spacing
3928 * Sets the ::column-spacing property which specifies the space
3929 * which is inserted between the columns of the icon view.
3934 gtk_icon_view_set_column_spacing (GtkIconView *icon_view,
3935 gint column_spacing)
3937 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3939 if (icon_view->priv->column_spacing != column_spacing)
3941 icon_view->priv->column_spacing = column_spacing;
3943 gtk_icon_view_invalidate_sizes (icon_view);
3944 gtk_icon_view_queue_layout (icon_view);
3946 g_object_notify (G_OBJECT (icon_view), "column-spacing");
3951 * gtk_icon_view_get_column_spacing:
3952 * @icon_view: a #GtkIconView
3954 * Returns the value of the ::column-spacing property.
3956 * Return value: the space between columns
3961 gtk_icon_view_get_column_spacing (GtkIconView *icon_view)
3963 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
3965 return icon_view->priv->column_spacing;
3969 * gtk_icon_view_set_marging:
3970 * @icon_view: a #GtkIconView
3971 * @spacing: the margin
3973 * Sets the ::margin property which specifies the space
3974 * which is inserted at the top, bottom, left and right
3980 gtk_icon_view_set_margin (GtkIconView *icon_view,
3983 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3985 if (icon_view->priv->margin != margin)
3987 icon_view->priv->margin = margin;
3989 gtk_icon_view_invalidate_sizes (icon_view);
3990 gtk_icon_view_queue_layout (icon_view);
3992 g_object_notify (G_OBJECT (icon_view), "margin");
3997 * gtk_icon_view_get_margin:
3998 * @icon_view: a #GtkIconView
4000 * Returns the value of the ::margin property.
4002 * Return value: the space at the borders
4007 gtk_icon_view_get_margin (GtkIconView *icon_view)
4009 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
4011 return icon_view->priv->margin;
4015 /* Accessibility Support */
4017 static gpointer accessible_parent_class;
4018 static gpointer accessible_item_parent_class;
4019 static GQuark accessible_private_data_quark = 0;
4021 #define GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE (gtk_icon_view_item_accessible_get_type ())
4022 #define GTK_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, GtkIconViewItemAccessible))
4023 #define GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE))
4025 static GType gtk_icon_view_item_accessible_get_type (void);
4036 GtkIconViewItem *item;
4040 AtkStateSet *state_set;
4044 GtkTextBuffer *text_buffer;
4046 gchar *action_descriptions[LAST_ACTION];
4047 gchar *image_description;
4048 guint action_idle_handler;
4049 } GtkIconViewItemAccessible;
4051 static const gchar *const gtk_icon_view_item_accessible_action_names[] =
4057 static const gchar *const gtk_icon_view_item_accessible_action_descriptions[] =
4062 typedef struct _GtkIconViewItemAccessibleClass
4064 AtkObjectClass parent_class;
4066 } GtkIconViewItemAccessibleClass;
4068 static gboolean gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item);
4071 gtk_icon_view_item_accessible_idle_do_action (gpointer data)
4073 GtkIconViewItemAccessible *item;
4074 GtkIconView *icon_view;
4077 GDK_THREADS_ENTER ();
4079 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (data);
4080 item->action_idle_handler = 0;
4082 if (item->widget != NULL)
4084 icon_view = GTK_ICON_VIEW (item->widget);
4085 path = gtk_tree_path_new_from_indices (item->item->index, -1);
4086 gtk_icon_view_item_activated (icon_view, path);
4087 gtk_tree_path_free (path);
4090 GDK_THREADS_LEAVE ();
4096 gtk_icon_view_item_accessible_action_do_action (AtkAction *action,
4099 GtkIconViewItemAccessible *item;
4100 GtkIconView *icon_view;
4102 if (i < 0 || i >= LAST_ACTION)
4105 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
4107 if (!GTK_IS_ICON_VIEW (item->widget))
4110 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4113 icon_view = GTK_ICON_VIEW (item->widget);
4117 case ACTION_ACTIVATE:
4118 if (!item->action_idle_handler)
4119 item->action_idle_handler = g_idle_add (gtk_icon_view_item_accessible_idle_do_action, item);
4122 g_assert_not_reached ();
4130 gtk_icon_view_item_accessible_action_get_n_actions (AtkAction *action)
4135 static const gchar *
4136 gtk_icon_view_item_accessible_action_get_description (AtkAction *action,
4139 GtkIconViewItemAccessible *item;
4141 if (i < 0 || i >= LAST_ACTION)
4144 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
4146 if (item->action_descriptions[i])
4147 return item->action_descriptions[i];
4149 return gtk_icon_view_item_accessible_action_descriptions[i];
4152 static const gchar *
4153 gtk_icon_view_item_accessible_action_get_name (AtkAction *action,
4156 if (i < 0 || i >= LAST_ACTION)
4159 return gtk_icon_view_item_accessible_action_names[i];
4163 gtk_icon_view_item_accessible_action_set_description (AtkAction *action,
4165 const gchar *description)
4167 GtkIconViewItemAccessible *item;
4169 if (i < 0 || i >= LAST_ACTION)
4172 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
4174 if (item->action_descriptions[i])
4175 g_free (item->action_descriptions[i]);
4177 item->action_descriptions[i] = g_strdup (description);
4183 atk_action_item_interface_init (AtkActionIface *iface)
4185 iface->do_action = gtk_icon_view_item_accessible_action_do_action;
4186 iface->get_n_actions = gtk_icon_view_item_accessible_action_get_n_actions;
4187 iface->get_description = gtk_icon_view_item_accessible_action_get_description;
4188 iface->get_name = gtk_icon_view_item_accessible_action_get_name;
4189 iface->set_description = gtk_icon_view_item_accessible_action_set_description;
4192 static const gchar *
4193 gtk_icon_view_item_accessible_image_get_image_description (AtkImage *image)
4195 GtkIconViewItemAccessible *item;
4197 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
4199 return item->image_description;
4203 gtk_icon_view_item_accessible_image_set_image_description (AtkImage *image,
4204 const gchar *description)
4206 GtkIconViewItemAccessible *item;
4208 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
4210 g_free (item->image_description);
4211 item->image_description = g_strdup (item->image_description);
4217 gtk_icon_view_item_accessible_image_get_image_size (AtkImage *image,
4221 GtkIconViewItemAccessible *item;
4223 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
4225 if (!GTK_IS_ICON_VIEW (item->widget))
4228 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4231 *width = item->item->pixbuf_width;
4232 *height = item->item->pixbuf_height;
4236 gtk_icon_view_item_accessible_image_get_image_position (AtkImage *image,
4239 AtkCoordType coord_type)
4241 GtkIconViewItemAccessible *item;
4243 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
4245 if (!GTK_IS_ICON_VIEW (item->widget))
4248 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4251 atk_component_get_position (ATK_COMPONENT (image), x, y, coord_type);
4252 *x+= item->item->pixbuf_x - item->item->x;
4253 *y+= item->item->pixbuf_y - item->item->y;
4257 atk_image_item_interface_init (AtkImageIface *iface)
4259 iface->get_image_description = gtk_icon_view_item_accessible_image_get_image_description;
4260 iface->set_image_description = gtk_icon_view_item_accessible_image_set_image_description;
4261 iface->get_image_size = gtk_icon_view_item_accessible_image_get_image_size;
4262 iface->get_image_position = gtk_icon_view_item_accessible_image_get_image_position;
4266 gtk_icon_view_item_accessible_text_get_text (AtkText *text,
4270 GtkIconViewItemAccessible *item;
4271 GtkTextIter start, end;
4272 GtkTextBuffer *buffer;
4274 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4276 if (!GTK_IS_ICON_VIEW (item->widget))
4279 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4282 buffer = item->text_buffer;
4283 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
4285 gtk_text_buffer_get_end_iter (buffer, &end);
4287 gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
4289 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
4293 gtk_icon_view_item_accessible_text_get_character_at_offset (AtkText *text,
4296 GtkIconViewItemAccessible *item;
4297 GtkTextIter start, end;
4298 GtkTextBuffer *buffer;
4302 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4304 if (!GTK_IS_ICON_VIEW (item->widget))
4307 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4310 buffer = item->text_buffer;
4311 if (offset >= gtk_text_buffer_get_char_count (buffer))
4314 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
4316 gtk_text_iter_forward_char (&end);
4317 string = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
4318 unichar = g_utf8_get_char (string);
4325 get_pango_text_offsets (PangoLayout *layout,
4326 GtkTextBuffer *buffer,
4328 AtkTextBoundary boundary_type,
4332 GtkTextIter *start_iter,
4333 GtkTextIter *end_iter)
4335 PangoLayoutIter *iter;
4336 PangoLayoutLine *line, *prev_line = NULL, *prev_prev_line = NULL;
4337 gint index, start_index, end_index;
4339 gboolean found = FALSE;
4341 text = pango_layout_get_text (layout);
4342 index = g_utf8_offset_to_pointer (text, offset) - text;
4343 iter = pango_layout_get_iter (layout);
4346 line = pango_layout_iter_get_line (iter);
4347 start_index = line->start_index;
4348 end_index = start_index + line->length;
4350 if (index >= start_index && index <= end_index)
4353 * Found line for offset
4359 * We want the previous line
4363 switch (boundary_type)
4365 case ATK_TEXT_BOUNDARY_LINE_START:
4366 end_index = start_index;
4367 start_index = prev_line->start_index;
4369 case ATK_TEXT_BOUNDARY_LINE_END:
4371 start_index = prev_prev_line->start_index +
4372 prev_prev_line->length;
4373 end_index = prev_line->start_index + prev_line->length;
4376 g_assert_not_reached();
4380 start_index = end_index = 0;
4383 switch (boundary_type)
4385 case ATK_TEXT_BOUNDARY_LINE_START:
4386 if (pango_layout_iter_next_line (iter))
4387 end_index = pango_layout_iter_get_line (iter)->start_index;
4389 case ATK_TEXT_BOUNDARY_LINE_END:
4391 start_index = prev_line->start_index +
4395 g_assert_not_reached();
4400 * We want the next line
4402 if (pango_layout_iter_next_line (iter))
4404 line = pango_layout_iter_get_line (iter);
4405 switch (boundary_type)
4407 case ATK_TEXT_BOUNDARY_LINE_START:
4408 start_index = line->start_index;
4409 if (pango_layout_iter_next_line (iter))
4410 end_index = pango_layout_iter_get_line (iter)->start_index;
4412 end_index = start_index + line->length;
4414 case ATK_TEXT_BOUNDARY_LINE_END:
4415 start_index = end_index;
4416 end_index = line->start_index + line->length;
4419 g_assert_not_reached();
4423 start_index = end_index;
4429 prev_prev_line = prev_line;
4432 while (pango_layout_iter_next_line (iter));
4436 start_index = prev_line->start_index + prev_line->length;
4437 end_index = start_index;
4439 pango_layout_iter_free (iter);
4440 *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
4441 *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
4443 gtk_text_buffer_get_iter_at_offset (buffer, start_iter, *start_offset);
4444 gtk_text_buffer_get_iter_at_offset (buffer, end_iter, *end_offset);
4448 gtk_icon_view_item_accessible_text_get_text_before_offset (AtkText *text,
4450 AtkTextBoundary boundary_type,
4454 GtkIconViewItemAccessible *item;
4455 GtkTextIter start, end;
4456 GtkTextBuffer *buffer;
4457 GtkIconView *icon_view;
4459 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4461 if (!GTK_IS_ICON_VIEW (item->widget))
4464 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4467 buffer = item->text_buffer;
4469 if (!gtk_text_buffer_get_char_count (buffer))
4473 return g_strdup ("");
4475 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
4479 switch (boundary_type)
4481 case ATK_TEXT_BOUNDARY_CHAR:
4482 gtk_text_iter_backward_char(&start);
4484 case ATK_TEXT_BOUNDARY_WORD_START:
4485 if (!gtk_text_iter_starts_word (&start))
4486 gtk_text_iter_backward_word_start (&start);
4488 gtk_text_iter_backward_word_start(&start);
4490 case ATK_TEXT_BOUNDARY_WORD_END:
4491 if (gtk_text_iter_inside_word (&start) &&
4492 !gtk_text_iter_starts_word (&start))
4493 gtk_text_iter_backward_word_start (&start);
4494 while (!gtk_text_iter_ends_word (&start))
4496 if (!gtk_text_iter_backward_char (&start))
4500 gtk_text_iter_backward_word_start(&start);
4501 while (!gtk_text_iter_ends_word (&start))
4503 if (!gtk_text_iter_backward_char (&start))
4507 case ATK_TEXT_BOUNDARY_SENTENCE_START:
4508 if (!gtk_text_iter_starts_sentence (&start))
4509 gtk_text_iter_backward_sentence_start (&start);
4511 gtk_text_iter_backward_sentence_start (&start);
4513 case ATK_TEXT_BOUNDARY_SENTENCE_END:
4514 if (gtk_text_iter_inside_sentence (&start) &&
4515 !gtk_text_iter_starts_sentence (&start))
4516 gtk_text_iter_backward_sentence_start (&start);
4517 while (!gtk_text_iter_ends_sentence (&start))
4519 if (!gtk_text_iter_backward_char (&start))
4523 gtk_text_iter_backward_sentence_start (&start);
4524 while (!gtk_text_iter_ends_sentence (&start))
4526 if (!gtk_text_iter_backward_char (&start))
4530 case ATK_TEXT_BOUNDARY_LINE_START:
4531 case ATK_TEXT_BOUNDARY_LINE_END:
4532 icon_view = GTK_ICON_VIEW (item->widget);
4533 gtk_icon_view_update_item_text (icon_view, item->item);
4534 get_pango_text_offsets (icon_view->priv->layout,
4546 *start_offset = gtk_text_iter_get_offset (&start);
4547 *end_offset = gtk_text_iter_get_offset (&end);
4549 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
4553 gtk_icon_view_item_accessible_text_get_text_at_offset (AtkText *text,
4555 AtkTextBoundary boundary_type,
4559 GtkIconViewItemAccessible *item;
4560 GtkTextIter start, end;
4561 GtkTextBuffer *buffer;
4562 GtkIconView *icon_view;
4564 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4566 if (!GTK_IS_ICON_VIEW (item->widget))
4569 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4572 buffer = item->text_buffer;
4574 if (!gtk_text_buffer_get_char_count (buffer))
4578 return g_strdup ("");
4580 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
4584 switch (boundary_type)
4586 case ATK_TEXT_BOUNDARY_CHAR:
4587 gtk_text_iter_forward_char (&end);
4589 case ATK_TEXT_BOUNDARY_WORD_START:
4590 if (!gtk_text_iter_starts_word (&start))
4591 gtk_text_iter_backward_word_start (&start);
4592 if (gtk_text_iter_inside_word (&end))
4593 gtk_text_iter_forward_word_end (&end);
4594 while (!gtk_text_iter_starts_word (&end))
4596 if (!gtk_text_iter_forward_char (&end))
4600 case ATK_TEXT_BOUNDARY_WORD_END:
4601 if (gtk_text_iter_inside_word (&start) &&
4602 !gtk_text_iter_starts_word (&start))
4603 gtk_text_iter_backward_word_start (&start);
4604 while (!gtk_text_iter_ends_word (&start))
4606 if (!gtk_text_iter_backward_char (&start))
4609 gtk_text_iter_forward_word_end (&end);
4611 case ATK_TEXT_BOUNDARY_SENTENCE_START:
4612 if (!gtk_text_iter_starts_sentence (&start))
4613 gtk_text_iter_backward_sentence_start (&start);
4614 if (gtk_text_iter_inside_sentence (&end))
4615 gtk_text_iter_forward_sentence_end (&end);
4616 while (!gtk_text_iter_starts_sentence (&end))
4618 if (!gtk_text_iter_forward_char (&end))
4622 case ATK_TEXT_BOUNDARY_SENTENCE_END:
4623 if (gtk_text_iter_inside_sentence (&start) &&
4624 !gtk_text_iter_starts_sentence (&start))
4625 gtk_text_iter_backward_sentence_start (&start);
4626 while (!gtk_text_iter_ends_sentence (&start))
4628 if (!gtk_text_iter_backward_char (&start))
4631 gtk_text_iter_forward_sentence_end (&end);
4633 case ATK_TEXT_BOUNDARY_LINE_START:
4634 case ATK_TEXT_BOUNDARY_LINE_END:
4635 icon_view = GTK_ICON_VIEW (item->widget);
4636 gtk_icon_view_update_item_text (icon_view, item->item);
4637 get_pango_text_offsets (icon_view->priv->layout,
4650 *start_offset = gtk_text_iter_get_offset (&start);
4651 *end_offset = gtk_text_iter_get_offset (&end);
4653 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
4657 gtk_icon_view_item_accessible_text_get_text_after_offset (AtkText *text,
4659 AtkTextBoundary boundary_type,
4663 GtkIconViewItemAccessible *item;
4664 GtkTextIter start, end;
4665 GtkTextBuffer *buffer;
4666 GtkIconView *icon_view;
4668 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4670 if (!GTK_IS_ICON_VIEW (item->widget))
4673 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4676 buffer = item->text_buffer;
4678 if (!gtk_text_buffer_get_char_count (buffer))
4682 return g_strdup ("");
4684 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
4688 switch (boundary_type)
4690 case ATK_TEXT_BOUNDARY_CHAR:
4691 gtk_text_iter_forward_char(&start);
4692 gtk_text_iter_forward_chars(&end, 2);
4694 case ATK_TEXT_BOUNDARY_WORD_START:
4695 if (gtk_text_iter_inside_word (&end))
4696 gtk_text_iter_forward_word_end (&end);
4697 while (!gtk_text_iter_starts_word (&end))
4699 if (!gtk_text_iter_forward_char (&end))
4703 if (!gtk_text_iter_is_end (&end))
4705 gtk_text_iter_forward_word_end (&end);
4706 while (!gtk_text_iter_starts_word (&end))
4708 if (!gtk_text_iter_forward_char (&end))
4713 case ATK_TEXT_BOUNDARY_WORD_END:
4714 gtk_text_iter_forward_word_end (&end);
4716 if (!gtk_text_iter_is_end (&end))
4717 gtk_text_iter_forward_word_end (&end);
4719 case ATK_TEXT_BOUNDARY_SENTENCE_START:
4720 if (gtk_text_iter_inside_sentence (&end))
4721 gtk_text_iter_forward_sentence_end (&end);
4722 while (!gtk_text_iter_starts_sentence (&end))
4724 if (!gtk_text_iter_forward_char (&end))
4728 if (!gtk_text_iter_is_end (&end))
4730 gtk_text_iter_forward_sentence_end (&end);
4731 while (!gtk_text_iter_starts_sentence (&end))
4733 if (!gtk_text_iter_forward_char (&end))
4738 case ATK_TEXT_BOUNDARY_SENTENCE_END:
4739 gtk_text_iter_forward_sentence_end (&end);
4741 if (!gtk_text_iter_is_end (&end))
4742 gtk_text_iter_forward_sentence_end (&end);
4744 case ATK_TEXT_BOUNDARY_LINE_START:
4745 case ATK_TEXT_BOUNDARY_LINE_END:
4746 icon_view = GTK_ICON_VIEW (item->widget);
4747 gtk_icon_view_update_item_text (icon_view, item->item);
4748 get_pango_text_offsets (icon_view->priv->layout,
4759 *start_offset = gtk_text_iter_get_offset (&start);
4760 *end_offset = gtk_text_iter_get_offset (&end);
4762 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
4766 gtk_icon_view_item_accessible_text_get_character_count (AtkText *text)
4768 GtkIconViewItemAccessible *item;
4770 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4772 if (!GTK_IS_ICON_VIEW (item->widget))
4775 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4778 return gtk_text_buffer_get_char_count (item->text_buffer);
4782 gtk_icon_view_item_accessible_text_get_character_extents (AtkText *text,
4788 AtkCoordType coord_type)
4790 GtkIconViewItemAccessible *item;
4791 GtkIconView *icon_view;
4792 PangoRectangle char_rect;
4793 const gchar *item_text;
4796 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4798 if (!GTK_IS_ICON_VIEW (item->widget))
4801 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4804 icon_view = GTK_ICON_VIEW (item->widget);
4805 gtk_icon_view_update_item_text (icon_view, item->item);
4806 item_text = pango_layout_get_text (icon_view->priv->layout);
4807 index = g_utf8_offset_to_pointer (item_text, offset) - item_text;
4808 pango_layout_index_to_pos (icon_view->priv->layout, index, &char_rect);
4810 atk_component_get_position (ATK_COMPONENT (text), x, y, coord_type);
4811 *x += item->item->layout_x - item->item->x + char_rect.x / PANGO_SCALE;
4812 /* Look at gtk_icon_view_paint_item() to see where the text is. */
4813 *x -= ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
4814 *y += item->item->layout_y - item->item->y + char_rect.y / PANGO_SCALE;
4815 *width = char_rect.width / PANGO_SCALE;
4816 *height = char_rect.height / PANGO_SCALE;
4820 gtk_icon_view_item_accessible_text_get_offset_at_point (AtkText *text,
4823 AtkCoordType coord_type)
4825 GtkIconViewItemAccessible *item;
4826 GtkIconView *icon_view;
4827 const gchar *item_text;
4832 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
4834 if (!GTK_IS_ICON_VIEW (item->widget))
4837 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4840 icon_view = GTK_ICON_VIEW (item->widget);
4841 gtk_icon_view_update_item_text (icon_view, item->item);
4842 atk_component_get_position (ATK_COMPONENT (text), &l_x, &l_y, coord_type);
4843 x -= l_x + item->item->layout_x - item->item->x;
4844 x += ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
4845 y -= l_y + item->item->layout_y - item->item->y;
4846 item_text = pango_layout_get_text (icon_view->priv->layout);
4847 if (!pango_layout_xy_to_index (icon_view->priv->layout,
4858 offset = g_utf8_strlen (item_text, -1);
4860 offset = g_utf8_pointer_to_offset (item_text, item_text + index);
4866 atk_text_item_interface_init (AtkTextIface *iface)
4868 iface->get_text = gtk_icon_view_item_accessible_text_get_text;
4869 iface->get_character_at_offset = gtk_icon_view_item_accessible_text_get_character_at_offset;
4870 iface->get_text_before_offset = gtk_icon_view_item_accessible_text_get_text_before_offset;
4871 iface->get_text_at_offset = gtk_icon_view_item_accessible_text_get_text_at_offset;
4872 iface->get_text_after_offset = gtk_icon_view_item_accessible_text_get_text_after_offset;
4873 iface->get_character_count = gtk_icon_view_item_accessible_text_get_character_count;
4874 iface->get_character_extents = gtk_icon_view_item_accessible_text_get_character_extents;
4875 iface->get_offset_at_point = gtk_icon_view_item_accessible_text_get_offset_at_point;
4879 gtk_icon_view_item_accessible_get_extents (AtkComponent *component,
4884 AtkCoordType coord_type)
4886 GtkIconViewItemAccessible *item;
4887 AtkObject *parent_obj;
4890 g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component));
4892 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
4893 if (!GTK_IS_WIDGET (item->widget))
4896 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
4899 *width = item->item->width;
4900 *height = item->item->height;
4901 if (gtk_icon_view_item_accessible_is_showing (item))
4903 parent_obj = gtk_widget_get_accessible (item->widget);
4904 atk_component_get_position (ATK_COMPONENT (parent_obj), &l_x, &l_y, coord_type);
4905 *x = l_x + item->item->x;
4906 *y = l_y + item->item->y;
4916 gtk_icon_view_item_accessible_grab_focus (AtkComponent *component)
4918 GtkIconViewItemAccessible *item;
4919 GtkWidget *toplevel;
4921 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component), FALSE);
4923 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
4924 if (!GTK_IS_WIDGET (item->widget))
4927 gtk_widget_grab_focus (item->widget);
4928 gtk_icon_view_set_cursor_item (GTK_ICON_VIEW (item->widget), item->item);
4929 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->widget));
4930 if (GTK_WIDGET_TOPLEVEL (toplevel))
4931 gtk_window_present (GTK_WINDOW (toplevel));
4937 atk_component_item_interface_init (AtkComponentIface *iface)
4939 iface->get_extents = gtk_icon_view_item_accessible_get_extents;
4940 iface->grab_focus = gtk_icon_view_item_accessible_grab_focus;
4944 gtk_icon_view_item_accessible_add_state (GtkIconViewItemAccessible *item,
4945 AtkStateType state_type,
4946 gboolean emit_signal)
4950 rc = atk_state_set_add_state (item->state_set, state_type);
4952 * The signal should only be generated if the value changed,
4953 * not when the item is set up. So states that are set
4954 * initially should pass FALSE as the emit_signal argument.
4959 atk_object_notify_state_change (ATK_OBJECT (item), state_type, TRUE);
4960 /* If state_type is ATK_STATE_VISIBLE, additional notification */
4961 if (state_type == ATK_STATE_VISIBLE)
4962 g_signal_emit_by_name (item, "visible_data_changed");
4969 gtk_icon_view_item_accessible_remove_state (GtkIconViewItemAccessible *item,
4970 AtkStateType state_type,
4971 gboolean emit_signal)
4973 if (atk_state_set_contains_state (item->state_set, state_type))
4977 rc = atk_state_set_remove_state (item->state_set, state_type);
4979 * The signal should only be generated if the value changed,
4980 * not when the item is set up. So states that are set
4981 * initially should pass FALSE as the emit_signal argument.
4986 atk_object_notify_state_change (ATK_OBJECT (item), state_type, FALSE);
4987 /* If state_type is ATK_STATE_VISIBLE, additional notification */
4988 if (state_type == ATK_STATE_VISIBLE)
4989 g_signal_emit_by_name (item, "visible_data_changed");
4999 gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item)
5001 GtkIconView *icon_view;
5002 GdkRectangle visible_rect;
5003 gboolean is_showing;
5006 * An item is considered "SHOWING" if any part of the item is in the
5007 * visible rectangle.
5010 if (!GTK_IS_ICON_VIEW (item->widget))
5013 if (item->item == NULL)
5016 icon_view = GTK_ICON_VIEW (item->widget);
5018 if (icon_view->priv->hadjustment)
5019 visible_rect.x += icon_view->priv->hadjustment->value;
5021 if (icon_view->priv->hadjustment)
5022 visible_rect.y += icon_view->priv->vadjustment->value;
5023 visible_rect.width = item->widget->allocation.width;
5024 visible_rect.height = item->widget->allocation.height;
5026 if (((item->item->x + item->item->width) < visible_rect.x) ||
5027 ((item->item->y + item->item->height) < (visible_rect.y)) ||
5028 (item->item->x > (visible_rect.x + visible_rect.width)) ||
5029 (item->item->y > (visible_rect.y + visible_rect.height)))
5038 gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
5039 gboolean emit_signal)
5041 if (gtk_icon_view_item_accessible_is_showing (item))
5042 return gtk_icon_view_item_accessible_add_state (item, ATK_STATE_SHOWING,
5045 return gtk_icon_view_item_accessible_remove_state (item, ATK_STATE_SHOWING,
5050 gtk_icon_view_item_accessible_object_init (GtkIconViewItemAccessible *item)
5054 item->state_set = atk_state_set_new ();
5056 atk_state_set_add_state (item->state_set, ATK_STATE_ENABLED);
5057 atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSABLE);
5058 atk_state_set_add_state (item->state_set, ATK_STATE_SENSITIVE);
5059 atk_state_set_add_state (item->state_set, ATK_STATE_SELECTABLE);
5060 atk_state_set_add_state (item->state_set, ATK_STATE_VISIBLE);
5062 for (i = 0; i < LAST_ACTION; i++)
5063 item->action_descriptions[i] = NULL;
5065 item->image_description = NULL;
5067 item->action_idle_handler = 0;
5071 gtk_icon_view_item_accessible_finalize (GObject *object)
5073 GtkIconViewItemAccessible *item;
5076 g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (object));
5078 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (object);
5081 g_object_remove_weak_pointer (G_OBJECT (item->widget), (gpointer) &item->widget);
5083 if (item->state_set)
5084 g_object_unref (item->state_set);
5086 if (item->text_buffer)
5087 g_object_unref (item->text_buffer);
5089 for (i = 0; i < LAST_ACTION; i++)
5090 g_free (item->action_descriptions[i]);
5092 g_free (item->image_description);
5094 if (item->action_idle_handler)
5096 g_source_remove (item->action_idle_handler);
5097 item->action_idle_handler = 0;
5100 G_OBJECT_CLASS (accessible_item_parent_class)->finalize (object);
5103 static G_CONST_RETURN gchar*
5104 gtk_icon_view_item_accessible_get_name (AtkObject *obj)
5110 GtkIconViewItemAccessible *item;
5111 GtkTextIter start_iter;
5112 GtkTextIter end_iter;
5114 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
5116 gtk_text_buffer_get_start_iter (item->text_buffer, &start_iter);
5117 gtk_text_buffer_get_end_iter (item->text_buffer, &end_iter);
5119 return gtk_text_buffer_get_text (item->text_buffer, &start_iter, &end_iter, FALSE);
5124 gtk_icon_view_item_accessible_get_parent (AtkObject *obj)
5126 GtkIconViewItemAccessible *item;
5128 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), NULL);
5129 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
5132 return gtk_widget_get_accessible (item->widget);
5138 gtk_icon_view_item_accessible_get_index_in_parent (AtkObject *obj)
5140 GtkIconViewItemAccessible *item;
5142 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), 0);
5143 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
5145 return item->item->index;
5148 static AtkStateSet *
5149 gtk_icon_view_item_accessible_ref_state_set (AtkObject *obj)
5151 GtkIconViewItemAccessible *item;
5152 GtkIconView *icon_view;
5154 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
5155 g_return_val_if_fail (item->state_set, NULL);
5160 icon_view = GTK_ICON_VIEW (item->widget);
5161 if (icon_view->priv->cursor_item == item->item)
5162 atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSED);
5164 atk_state_set_remove_state (item->state_set, ATK_STATE_FOCUSED);
5166 return g_object_ref (item->state_set);
5170 gtk_icon_view_item_accessible_class_init (AtkObjectClass *klass)
5172 GObjectClass *gobject_class;
5174 accessible_item_parent_class = g_type_class_peek_parent (klass);
5176 gobject_class = (GObjectClass *)klass;
5178 gobject_class->finalize = gtk_icon_view_item_accessible_finalize;
5180 klass->get_index_in_parent = gtk_icon_view_item_accessible_get_index_in_parent;
5181 klass->get_name = gtk_icon_view_item_accessible_get_name;
5182 klass->get_parent = gtk_icon_view_item_accessible_get_parent;
5183 klass->ref_state_set = gtk_icon_view_item_accessible_ref_state_set;
5187 gtk_icon_view_item_accessible_get_type (void)
5189 static GType type = 0;
5193 static const GTypeInfo tinfo =
5195 sizeof (GtkIconViewItemAccessibleClass),
5196 (GBaseInitFunc) NULL, /* base init */
5197 (GBaseFinalizeFunc) NULL, /* base finalize */
5198 (GClassInitFunc) gtk_icon_view_item_accessible_class_init, /* class init */
5199 (GClassFinalizeFunc) NULL, /* class finalize */
5200 NULL, /* class data */
5201 sizeof (GtkIconViewItemAccessible), /* instance size */
5202 0, /* nb preallocs */
5203 (GInstanceInitFunc) gtk_icon_view_item_accessible_object_init, /* instance init */
5204 NULL /* value table */
5207 static const GInterfaceInfo atk_component_info =
5209 (GInterfaceInitFunc) atk_component_item_interface_init,
5210 (GInterfaceFinalizeFunc) NULL,
5213 static const GInterfaceInfo atk_action_info =
5215 (GInterfaceInitFunc) atk_action_item_interface_init,
5216 (GInterfaceFinalizeFunc) NULL,
5219 static const GInterfaceInfo atk_image_info =
5221 (GInterfaceInitFunc) atk_image_item_interface_init,
5222 (GInterfaceFinalizeFunc) NULL,
5225 static const GInterfaceInfo atk_text_info =
5227 (GInterfaceInitFunc) atk_text_item_interface_init,
5228 (GInterfaceFinalizeFunc) NULL,
5232 type = g_type_register_static (ATK_TYPE_OBJECT,
5233 "GtkIconViewItemAccessible", &tinfo, 0);
5234 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
5235 &atk_component_info);
5236 g_type_add_interface_static (type, ATK_TYPE_ACTION,
5238 g_type_add_interface_static (type, ATK_TYPE_IMAGE,
5240 g_type_add_interface_static (type, ATK_TYPE_TEXT,
5247 #define GTK_TYPE_ICON_VIEW_ACCESSIBLE (gtk_icon_view_accessible_get_type ())
5248 #define GTK_ICON_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE, GtkIconViewAccessible))
5249 #define GTK_IS_ICON_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE))
5251 static GType gtk_icon_view_accessible_get_type (void);
5256 } GtkIconViewAccessible;
5262 } GtkIconViewItemAccessibleInfo;
5268 GtkAdjustment *old_hadj;
5269 GtkAdjustment *old_vadj;
5271 GtkTreeModel *model;
5273 } GtkIconViewAccessiblePrivate;
5275 static GtkIconViewAccessiblePrivate *
5276 gtk_icon_view_accessible_get_priv (AtkObject *accessible)
5278 return g_object_get_qdata (G_OBJECT (accessible),
5279 accessible_private_data_quark);
5283 gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
5287 GtkIconViewItemAccessibleInfo *info;
5288 GtkIconViewItemAccessibleInfo *tmp_info;
5289 GtkIconViewAccessiblePrivate *priv;
5292 info = g_new (GtkIconViewItemAccessibleInfo, 1);
5294 info->index = index;
5296 priv = gtk_icon_view_accessible_get_priv (accessible);
5297 items = priv->items;
5300 tmp_info = items->data;
5301 if (tmp_info->index > index)
5303 items = items->next;
5305 priv->items = g_list_insert_before (priv->items, items, info);
5306 priv->old_hadj = NULL;
5307 priv->old_vadj = NULL;
5311 gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
5313 GtkIconView *icon_view;
5316 widget = GTK_ACCESSIBLE (accessible)->widget;
5320 icon_view = GTK_ICON_VIEW (widget);
5322 return g_list_length (icon_view->priv->items);
5326 gtk_icon_view_accessible_find_child (AtkObject *accessible,
5329 GtkIconViewAccessiblePrivate *priv;
5330 GtkIconViewItemAccessibleInfo *info;
5333 priv = gtk_icon_view_accessible_get_priv (accessible);
5334 items = priv->items;
5339 if (info->index == index)
5341 items = items->next;
5347 gtk_icon_view_accessible_ref_child (AtkObject *accessible,
5350 GtkIconView *icon_view;
5354 GtkIconViewItemAccessible *a11y_item;
5356 widget = GTK_ACCESSIBLE (accessible)->widget;
5360 icon_view = GTK_ICON_VIEW (widget);
5361 icons = g_list_nth (icon_view->priv->items, index);
5365 GtkIconViewItem *item = icons->data;
5367 g_return_val_if_fail (item->index == index, NULL);
5368 obj = gtk_icon_view_accessible_find_child (accessible, index);
5371 obj = g_object_new (gtk_icon_view_item_accessible_get_type (), NULL);
5372 gtk_icon_view_item_accessible_info_new (accessible,
5375 obj->role = ATK_ROLE_ICON;
5376 a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
5377 a11y_item->item = item;
5378 a11y_item->widget = widget;
5379 a11y_item->text_buffer = gtk_text_buffer_new (NULL);
5380 gtk_icon_view_update_item_text (icon_view, item);
5381 gtk_text_buffer_set_text (a11y_item->text_buffer,
5382 pango_layout_get_text (icon_view->priv->layout),
5384 gtk_icon_view_item_accessible_set_visibility (a11y_item, FALSE);
5385 g_object_add_weak_pointer (G_OBJECT (widget), (gpointer) &(a11y_item->widget));
5393 gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
5396 GtkIconViewAccessiblePrivate *priv;
5397 GtkIconViewItemAccessibleInfo *info;
5398 GtkIconViewItemAccessible *item;
5401 priv = gtk_icon_view_accessible_get_priv (ATK_OBJECT (view));
5405 gboolean act_on_item;
5407 widget = GTK_ACCESSIBLE (view)->widget;
5411 items = priv->items;
5413 act_on_item = (list == NULL);
5418 info = (GtkIconViewItemAccessibleInfo *)items->data;
5419 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
5421 if (act_on_item == FALSE && list == items)
5425 gtk_icon_view_item_accessible_set_visibility (item, TRUE);
5427 items = items->next;
5433 gtk_icon_view_accessible_adjustment_changed (GtkAdjustment *adjustment,
5434 GtkIconView *icon_view)
5437 GtkIconViewAccessible *view;
5440 * The scrollbars have changed
5442 obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
5443 view = GTK_ICON_VIEW_ACCESSIBLE (obj);
5445 gtk_icon_view_accessible_traverse_items (view, NULL);
5449 gtk_icon_view_accessible_set_scroll_adjustments (GtkWidget *widget,
5450 GtkAdjustment *hadj,
5451 GtkAdjustment *vadj)
5454 GtkIconViewAccessiblePrivate *priv;
5456 atk_obj = gtk_widget_get_accessible (widget);
5457 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5459 if (priv->old_hadj != hadj)
5463 g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj),
5464 (gpointer *)&priv->old_hadj);
5466 g_signal_handlers_disconnect_by_func (priv->old_hadj,
5467 (gpointer) gtk_icon_view_accessible_adjustment_changed,
5470 priv->old_hadj = hadj;
5473 g_object_add_weak_pointer (G_OBJECT (priv->old_hadj),
5474 (gpointer *)&priv->old_hadj);
5475 g_signal_connect (hadj,
5477 G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
5481 if (priv->old_vadj != vadj)
5485 g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj),
5486 (gpointer *)&priv->old_vadj);
5488 g_signal_handlers_disconnect_by_func (priv->old_vadj,
5489 (gpointer) gtk_icon_view_accessible_adjustment_changed,
5492 priv->old_vadj = vadj;
5495 g_object_add_weak_pointer (G_OBJECT (priv->old_vadj),
5496 (gpointer *)&priv->old_vadj);
5497 g_signal_connect (vadj,
5499 G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
5506 gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
5513 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
5514 g_signal_emit_by_name (atk_obj, "visible-data-changed");
5520 gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
5525 GtkIconViewAccessiblePrivate *priv;
5526 GtkIconViewItemAccessibleInfo *info;
5527 GtkIconViewAccessible *view;
5528 GtkIconViewItemAccessible *item;
5534 index = gtk_tree_path_get_indices(path)[0];
5535 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
5536 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
5537 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5539 items = priv->items;
5544 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
5545 if (info->index != item->item->index)
5547 if (info->index < index)
5548 g_warning ("Unexpected index value on insertion %d %d", index, info->index);
5550 if (tmp_list == NULL)
5553 info->index = item->item->index;
5556 items = items->next;
5558 gtk_icon_view_accessible_traverse_items (view, tmp_list);
5559 g_signal_emit_by_name (atk_obj, "children_changed::add",
5565 gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
5569 GtkIconViewAccessiblePrivate *priv;
5570 GtkIconViewItemAccessibleInfo *info;
5571 GtkIconViewAccessible *view;
5572 GtkIconViewItemAccessible *item;
5575 GList *deleted_item;
5579 index = gtk_tree_path_get_indices(path)[0];
5580 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
5581 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
5582 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5584 items = priv->items;
5586 deleted_item = NULL;
5591 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
5592 if (info->index == index)
5594 deleted_item = items;
5596 if (info->index != item->item->index)
5598 if (tmp_list == NULL)
5601 info->index = item->item->index;
5604 items = items->next;
5606 gtk_icon_view_accessible_traverse_items (view, tmp_list);
5609 info = deleted_item->data;
5610 gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
5612 g_signal_emit_by_name (atk_obj, "children_changed::remove",
5616 priv->items = g_list_remove_link (priv->items, deleted_item);
5624 gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
5625 GtkIconViewItemAccessibleInfo *i2)
5627 return i1->index - i2->index;
5631 gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
5637 GtkIconViewAccessiblePrivate *priv;
5638 GtkIconViewItemAccessibleInfo *info;
5639 GtkIconViewAccessible *view;
5640 GtkIconView *icon_view;
5641 GtkIconViewItemAccessible *item;
5646 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
5647 icon_view = GTK_ICON_VIEW (user_data);
5648 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
5649 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5651 items = priv->items;
5656 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
5657 info->index = new_order[info->index];
5658 tmp_list = g_list_nth (icon_view->priv->items, info->index);
5659 item->item = tmp_list->data;
5660 items = items->next;
5662 priv->items = g_list_sort (priv->items,
5663 (GCompareFunc)gtk_icon_view_accessible_item_compare);
5669 gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
5674 obj = G_OBJECT (model);
5675 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_changed, widget);
5676 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_inserted, widget);
5677 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_deleted, widget);
5678 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_rows_reordered, widget);
5682 gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
5686 obj = G_OBJECT (icon_view->priv->model);
5687 g_signal_connect_data (obj, "row-changed",
5688 (GCallback) gtk_icon_view_accessible_model_row_changed,
5689 icon_view, NULL, 0);
5690 g_signal_connect_data (obj, "row-inserted",
5691 (GCallback) gtk_icon_view_accessible_model_row_inserted,
5692 icon_view, NULL, G_CONNECT_AFTER);
5693 g_signal_connect_data (obj, "row-deleted",
5694 (GCallback) gtk_icon_view_accessible_model_row_deleted,
5695 icon_view, NULL, G_CONNECT_AFTER);
5696 g_signal_connect_data (obj, "rows-reordered",
5697 (GCallback) gtk_icon_view_accessible_model_rows_reordered,
5698 icon_view, NULL, G_CONNECT_AFTER);
5702 gtk_icon_view_accessible_clear_cache (GtkIconViewAccessiblePrivate *priv)
5704 GtkIconViewItemAccessibleInfo *info;
5707 items = priv->items;
5710 info = (GtkIconViewItemAccessibleInfo *) items->data;
5711 g_object_unref (info->item);
5712 g_free (items->data);
5713 items = items->next;
5715 g_list_free (priv->items);
5720 gtk_icon_view_accessible_notify_gtk (GObject *obj,
5723 GtkIconView *icon_view;
5726 GtkIconViewAccessible *view;
5727 GtkIconViewAccessiblePrivate *priv;
5729 if (strcmp (pspec->name, "model") == 0)
5731 widget = GTK_WIDGET (obj);
5732 atk_obj = gtk_widget_get_accessible (widget);
5733 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
5734 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5737 g_object_remove_weak_pointer (G_OBJECT (priv->model),
5738 (gpointer *)&priv->model);
5739 gtk_icon_view_accessible_disconnect_model_signals (priv->model, widget);
5741 gtk_icon_view_accessible_clear_cache (priv);
5743 icon_view = GTK_ICON_VIEW (obj);
5744 priv->model = icon_view->priv->model;
5745 /* If there is no model the GtkIconView is probably being destroyed */
5748 g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
5749 gtk_icon_view_accessible_connect_model_signals (icon_view);
5757 gtk_icon_view_accessible_initialize (AtkObject *accessible,
5760 GtkIconViewAccessiblePrivate *priv;
5761 GtkIconView *icon_view;
5763 if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize)
5764 ATK_OBJECT_CLASS (accessible_parent_class)->initialize (accessible, data);
5766 priv = g_new0 (GtkIconViewAccessiblePrivate, 1);
5767 g_object_set_qdata (G_OBJECT (accessible),
5768 accessible_private_data_quark,
5771 icon_view = GTK_ICON_VIEW (data);
5772 if (icon_view->priv->hadjustment)
5774 priv->old_hadj = icon_view->priv->hadjustment;
5775 g_object_add_weak_pointer (G_OBJECT (priv->old_hadj), (gpointer *)&priv->old_hadj);
5776 g_signal_connect (icon_view->priv->hadjustment,
5778 G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
5781 if (icon_view->priv->vadjustment)
5783 priv->old_vadj = icon_view->priv->vadjustment;
5784 g_object_add_weak_pointer (G_OBJECT (priv->old_vadj), (gpointer *)&priv->old_vadj);
5785 g_signal_connect (icon_view->priv->vadjustment,
5787 G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
5790 g_signal_connect_after (data,
5791 "set_scroll_adjustments",
5792 G_CALLBACK (gtk_icon_view_accessible_set_scroll_adjustments),
5794 g_signal_connect (data,
5796 G_CALLBACK (gtk_icon_view_accessible_notify_gtk),
5799 priv->model = icon_view->priv->model;
5802 g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
5803 gtk_icon_view_accessible_connect_model_signals (icon_view);
5806 accessible->role = ATK_ROLE_LAYERED_PANE;
5810 gtk_icon_view_accessible_finalize (GObject *object)
5812 GtkIconViewAccessiblePrivate *priv;
5814 priv = gtk_icon_view_accessible_get_priv (ATK_OBJECT (object));
5815 gtk_icon_view_accessible_clear_cache (priv);
5819 G_OBJECT_CLASS (accessible_parent_class)->finalize (object);
5823 gtk_icon_view_accessible_destroyed (GtkWidget *widget,
5824 GtkAccessible *accessible)
5827 GtkIconViewAccessiblePrivate *priv;
5829 atk_obj = ATK_OBJECT (accessible);
5830 priv = gtk_icon_view_accessible_get_priv (atk_obj);
5833 g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj),
5834 (gpointer *)&priv->old_hadj);
5836 g_signal_handlers_disconnect_by_func (priv->old_hadj,
5837 (gpointer) gtk_icon_view_accessible_adjustment_changed,
5839 priv->old_hadj = NULL;
5843 g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj),
5844 (gpointer *)&priv->old_vadj);
5846 g_signal_handlers_disconnect_by_func (priv->old_vadj,
5847 (gpointer) gtk_icon_view_accessible_adjustment_changed,
5849 priv->old_vadj = NULL;
5854 gtk_icon_view_accessible_connect_widget_destroyed (GtkAccessible *accessible)
5856 if (accessible->widget)
5858 g_signal_connect_after (accessible->widget,
5860 G_CALLBACK (gtk_icon_view_accessible_destroyed),
5863 GTK_ACCESSIBLE_CLASS (accessible_parent_class)->connect_widget_destroyed (accessible);
5867 gtk_icon_view_accessible_class_init (AtkObjectClass *klass)
5869 GObjectClass *gobject_class;
5870 GtkAccessibleClass *accessible_class;
5872 accessible_parent_class = g_type_class_peek_parent (klass);
5874 gobject_class = (GObjectClass *)klass;
5875 accessible_class = (GtkAccessibleClass *)klass;
5877 gobject_class->finalize = gtk_icon_view_accessible_finalize;
5879 klass->get_n_children = gtk_icon_view_accessible_get_n_children;
5880 klass->ref_child = gtk_icon_view_accessible_ref_child;
5881 klass->initialize = gtk_icon_view_accessible_initialize;
5883 accessible_class->connect_widget_destroyed = gtk_icon_view_accessible_connect_widget_destroyed;
5885 accessible_private_data_quark = g_quark_from_static_string ("icon_view-accessible-private-data");
5889 gtk_icon_view_accessible_ref_accessible_at_point (AtkComponent *component,
5892 AtkCoordType coord_type)
5895 GtkIconView *icon_view;
5896 GtkIconViewItem *item;
5899 widget = GTK_ACCESSIBLE (component)->widget;
5901 /* State is defunct */
5904 icon_view = GTK_ICON_VIEW (widget);
5905 atk_component_get_extents (component, &x_pos, &y_pos, NULL, NULL, coord_type);
5906 item = gtk_icon_view_get_item_at_pos (icon_view, x - x_pos, y - y_pos);
5908 return gtk_icon_view_accessible_ref_child (ATK_OBJECT (component), item->index);
5914 atk_component_interface_init (AtkComponentIface *iface)
5916 iface->ref_accessible_at_point = gtk_icon_view_accessible_ref_accessible_at_point;
5920 gtk_icon_view_accessible_add_selection (AtkSelection *selection,
5924 GtkIconView *icon_view;
5925 GtkIconViewItem *item;
5928 widget = GTK_ACCESSIBLE (selection)->widget;
5932 icon_view = GTK_ICON_VIEW (widget);
5934 l = g_list_nth (icon_view->priv->items, i);
5939 gtk_icon_view_select_item (icon_view, item);
5945 gtk_icon_view_accessible_clear_selection (AtkSelection *selection)
5948 GtkIconView *icon_view;
5950 widget = GTK_ACCESSIBLE (selection)->widget;
5954 icon_view = GTK_ICON_VIEW (widget);
5955 gtk_icon_view_unselect_all (icon_view);
5961 gtk_icon_view_accessible_ref_selection (AtkSelection *selection,
5965 GtkIconView *icon_view;
5966 GtkIconViewItem *item;
5969 widget = GTK_ACCESSIBLE (selection)->widget;
5973 icon_view = GTK_ICON_VIEW (widget);
5975 l = icon_view->priv->items;
5982 return atk_object_ref_accessible_child (gtk_widget_get_accessible (widget), item->index);
5993 gtk_icon_view_accessible_get_selection_count (AtkSelection *selection)
5996 GtkIconView *icon_view;
5997 GtkIconViewItem *item;
6001 widget = GTK_ACCESSIBLE (selection)->widget;
6005 icon_view = GTK_ICON_VIEW (widget);
6007 l = icon_view->priv->items;
6023 gtk_icon_view_accessible_is_child_selected (AtkSelection *selection,
6027 GtkIconView *icon_view;
6028 GtkIconViewItem *item;
6031 widget = GTK_ACCESSIBLE (selection)->widget;
6035 icon_view = GTK_ICON_VIEW (widget);
6036 l = g_list_nth (icon_view->priv->items, i);
6042 return item->selected;
6046 gtk_icon_view_accessible_remove_selection (AtkSelection *selection,
6050 GtkIconView *icon_view;
6051 GtkIconViewItem *item;
6055 widget = GTK_ACCESSIBLE (selection)->widget;
6059 icon_view = GTK_ICON_VIEW (widget);
6060 l = icon_view->priv->items;
6069 gtk_icon_view_unselect_item (icon_view, item);
6081 gtk_icon_view_accessible_select_all_selection (AtkSelection *selection)
6084 GtkIconView *icon_view;
6086 widget = GTK_ACCESSIBLE (selection)->widget;
6090 icon_view = GTK_ICON_VIEW (widget);
6091 gtk_icon_view_select_all (icon_view);
6096 gtk_icon_view_accessible_selection_interface_init (AtkSelectionIface *iface)
6098 iface->add_selection = gtk_icon_view_accessible_add_selection;
6099 iface->clear_selection = gtk_icon_view_accessible_clear_selection;
6100 iface->ref_selection = gtk_icon_view_accessible_ref_selection;
6101 iface->get_selection_count = gtk_icon_view_accessible_get_selection_count;
6102 iface->is_child_selected = gtk_icon_view_accessible_is_child_selected;
6103 iface->remove_selection = gtk_icon_view_accessible_remove_selection;
6104 iface->select_all_selection = gtk_icon_view_accessible_select_all_selection;
6108 gtk_icon_view_accessible_get_type (void)
6110 static GType type = 0;
6114 static GTypeInfo tinfo =
6117 (GBaseInitFunc) NULL, /* base init */
6118 (GBaseFinalizeFunc) NULL, /* base finalize */
6119 (GClassInitFunc) gtk_icon_view_accessible_class_init,
6120 (GClassFinalizeFunc) NULL, /* class finalize */
6121 NULL, /* class data */
6122 0, /* instance size */
6123 0, /* nb preallocs */
6124 (GInstanceInitFunc) NULL, /* instance init */
6125 NULL /* value table */
6127 static const GInterfaceInfo atk_component_info =
6129 (GInterfaceInitFunc) atk_component_interface_init,
6130 (GInterfaceFinalizeFunc) NULL,
6133 static const GInterfaceInfo atk_selection_info =
6135 (GInterfaceInitFunc) gtk_icon_view_accessible_selection_interface_init,
6136 (GInterfaceFinalizeFunc) NULL,
6141 * Figure out the size of the class and instance
6142 * we are deriving from
6144 AtkObjectFactory *factory;
6147 GType derived_atk_type;
6149 derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
6150 factory = atk_registry_get_factory (atk_get_default_registry (),
6152 derived_atk_type = atk_object_factory_get_accessible_type (factory);
6153 g_type_query (derived_atk_type, &query);
6154 tinfo.class_size = query.class_size;
6155 tinfo.instance_size = query.instance_size;
6157 type = g_type_register_static (derived_atk_type,
6158 "GtkIconViewAccessible",
6160 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
6161 &atk_component_info);
6162 g_type_add_interface_static (type, ATK_TYPE_SELECTION,
6163 &atk_selection_info);
6169 gtk_icon_view_accessible_new (GObject *obj)
6171 AtkObject *accessible;
6173 g_return_val_if_fail (GTK_IS_WIDGET (obj), NULL);
6175 accessible = g_object_new (gtk_icon_view_accessible_get_type (), NULL);
6176 atk_object_initialize (accessible, obj);
6182 gtk_icon_view_accessible_factory_get_accessible_type (void)
6184 return gtk_icon_view_accessible_get_type ();
6188 gtk_icon_view_accessible_factory_create_accessible (GObject *obj)
6190 return gtk_icon_view_accessible_new (obj);
6194 gtk_icon_view_accessible_factory_class_init (AtkObjectFactoryClass *klass)
6196 klass->create_accessible = gtk_icon_view_accessible_factory_create_accessible;
6197 klass->get_accessible_type = gtk_icon_view_accessible_factory_get_accessible_type;
6201 gtk_icon_view_accessible_factory_get_type (void)
6203 static GType type = 0;
6207 static const GTypeInfo tinfo =
6209 sizeof (AtkObjectFactoryClass),
6210 NULL, /* base_init */
6211 NULL, /* base_finalize */
6212 (GClassInitFunc) gtk_icon_view_accessible_factory_class_init,
6213 NULL, /* class_finalize */
6214 NULL, /* class_data */
6215 sizeof (AtkObjectFactory),
6216 0, /* n_preallocs */
6220 type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY,
6221 "GtkIconViewAccessibleFactory",
6228 gtk_icon_view_get_accessible (GtkWidget *widget)
6230 static gboolean first_time = TRUE;
6234 AtkObjectFactory *factory;
6235 AtkRegistry *registry;
6237 GType derived_atk_type;
6240 * Figure out whether accessibility is enabled by looking at the
6241 * type of the accessible object which would be created for
6242 * the parent type of GtkIconView.
6244 derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
6246 registry = atk_get_default_registry ();
6247 factory = atk_registry_get_factory (registry,
6249 derived_atk_type = atk_object_factory_get_accessible_type (factory);
6250 if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
6251 atk_registry_set_factory_type (registry,
6253 gtk_icon_view_accessible_factory_get_type ());
6256 return GTK_WIDGET_CLASS (parent_class)->get_accessible (widget);
6259 #define __GTK_ICON_VIEW_C__
6260 #include "gtkaliasdef.c"