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 "gtkcelllayout.h"
29 #include "gtkcellrenderer.h"
30 #include "gtkcellrenderertext.h"
31 #include "gtkcellrendererpixbuf.h"
32 #include "gtkmarshalers.h"
33 #include "gtkbindings.h"
37 #include "gtkaccessible.h"
38 #include "gtkwindow.h"
40 #include "gtkcombobox.h"
41 #include "gtktextbuffer.h"
42 #include "gtkscrollable.h"
43 #include "gtksizerequest.h"
44 #include "gtktreednd.h"
45 #include "gtkprivate.h"
50 * @short_description: A widget which displays a list of icons in a grid
52 * #GtkIconView provides an alternative view on a #GtkTreeModel.
53 * It displays the model as a grid of icons with labels. Like
54 * #GtkTreeView, it allows to select one or multiple items
55 * (depending on the selection mode, see gtk_icon_view_set_selection_mode()).
56 * In addition to selection with the arrow keys, #GtkIconView supports
57 * rubberband selection, which is controlled by dragging the pointer.
59 * Note that if the tree model is backed by an actual tree store (as
60 * opposed to a flat list where the mapping to icons is obvious),
61 * #GtkIconView will only display the first level of the tree and
62 * ignore the tree's branches.
65 #define SCROLL_EDGE_SIZE 15
67 #define GTK_ICON_VIEW_PRIORITY_LAYOUT (GDK_PRIORITY_REDRAW + 5)
69 typedef struct _GtkIconViewItem GtkIconViewItem;
70 struct _GtkIconViewItem
78 gint x, y, width, height;
81 * box[i] is the actual area occupied by cell i,
82 * before, after are used to calculate the cell
83 * area relative to the box.
84 * See gtk_icon_view_get_cell_area().
92 guint selected_before_rubberbanding : 1;
96 typedef struct _GtkIconViewCellInfo GtkIconViewCellInfo;
97 struct _GtkIconViewCellInfo
99 GtkCellRenderer *cell;
109 GtkCellLayoutDataFunc func;
111 GDestroyNotify destroy;
114 typedef struct _GtkIconViewChild GtkIconViewChild;
115 struct _GtkIconViewChild
118 GtkIconViewItem *item;
122 struct _GtkIconViewPrivate
126 GtkSelectionMode selection_mode;
128 GdkWindow *bin_window;
136 GtkAdjustment *hadjustment;
137 GtkAdjustment *vadjustment;
139 guint layout_idle_id;
141 gboolean doing_rubberband;
142 gint rubberband_x1, rubberband_y1;
143 gint rubberband_x2, rubberband_y2;
144 GdkDevice *rubberband_device;
146 guint scroll_timeout_id;
147 gint scroll_value_diff;
148 gint event_last_x, event_last_y;
150 GtkIconViewItem *anchor_item;
151 GtkIconViewItem *cursor_item;
152 GtkIconViewItem *edited_item;
153 GtkCellEditable *editable;
155 GtkIconViewItem *last_single_clicked;
162 GtkOrientation item_orientation;
182 GdkModifierType start_button_mask;
187 GdkDragAction source_actions;
188 GdkDragAction dest_actions;
190 GtkTreeRowReference *dest_item;
191 GtkIconViewDropPosition dest_pos;
194 GtkTreeRowReference *scroll_to_path;
195 gfloat scroll_to_row_align;
196 gfloat scroll_to_col_align;
197 guint scroll_to_use_align : 1;
199 guint source_set : 1;
201 guint reorderable : 1;
202 guint empty_view_drop :1;
204 guint ctrl_pressed : 1;
205 guint shift_pressed : 1;
207 guint draw_focus : 1;
209 /* GtkScrollablePolicy needs to be checked when
210 * driving the scrollable adjustment values */
211 guint hscroll_policy : 1;
212 guint vscroll_policy : 1;
225 ACTIVATE_CURSOR_ITEM,
237 PROP_ITEM_ORIENTATION,
249 /* For scrollable interface */
257 static void gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface);
258 static void gtk_icon_view_finalize (GObject *object);
259 static void gtk_icon_view_set_property (GObject *object,
263 static void gtk_icon_view_get_property (GObject *object,
267 /* GtkWidget vfuncs */
268 static void gtk_icon_view_destroy (GtkWidget *widget);
269 static void gtk_icon_view_realize (GtkWidget *widget);
270 static void gtk_icon_view_unrealize (GtkWidget *widget);
271 static void gtk_icon_view_style_set (GtkWidget *widget,
272 GtkStyle *previous_style);
273 static void gtk_icon_view_state_changed (GtkWidget *widget,
274 GtkStateType previous_state);
275 static void gtk_icon_view_get_preferred_width (GtkWidget *widget,
278 static void gtk_icon_view_get_preferred_height (GtkWidget *widget,
281 static void gtk_icon_view_size_allocate (GtkWidget *widget,
282 GtkAllocation *allocation);
283 static gboolean gtk_icon_view_draw (GtkWidget *widget,
285 static gboolean gtk_icon_view_motion (GtkWidget *widget,
286 GdkEventMotion *event);
287 static gboolean gtk_icon_view_button_press (GtkWidget *widget,
288 GdkEventButton *event);
289 static gboolean gtk_icon_view_button_release (GtkWidget *widget,
290 GdkEventButton *event);
291 static gboolean gtk_icon_view_key_press (GtkWidget *widget,
293 static gboolean gtk_icon_view_key_release (GtkWidget *widget,
295 static AtkObject *gtk_icon_view_get_accessible (GtkWidget *widget);
298 /* GtkContainer vfuncs */
299 static void gtk_icon_view_remove (GtkContainer *container,
301 static void gtk_icon_view_forall (GtkContainer *container,
302 gboolean include_internals,
303 GtkCallback callback,
304 gpointer callback_data);
306 /* GtkIconView vfuncs */
307 static void gtk_icon_view_real_select_all (GtkIconView *icon_view);
308 static void gtk_icon_view_real_unselect_all (GtkIconView *icon_view);
309 static void gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view);
310 static void gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view);
311 static gboolean gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view);
313 /* Internal functions */
314 static void gtk_icon_view_set_hadjustment_values (GtkIconView *icon_view);
315 static void gtk_icon_view_set_vadjustment_values (GtkIconView *icon_view);
316 static void gtk_icon_view_set_hadjustment (GtkIconView *icon_view,
317 GtkAdjustment *adjustment);
318 static void gtk_icon_view_set_vadjustment (GtkIconView *icon_view,
319 GtkAdjustment *adjustment);
320 static void gtk_icon_view_accessible_set_adjustment (GtkIconView *icon_view,
321 GtkOrientation orientation,
322 GtkAdjustment *adjustment);
323 static void gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment,
324 GtkIconView *icon_view);
325 static void gtk_icon_view_layout (GtkIconView *icon_view);
326 static void gtk_icon_view_paint_item (GtkIconView *icon_view,
328 GtkIconViewItem *item,
331 gboolean draw_focus);
332 static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view,
334 static void gtk_icon_view_queue_draw_path (GtkIconView *icon_view,
336 static void gtk_icon_view_queue_draw_item (GtkIconView *icon_view,
337 GtkIconViewItem *item);
338 static void gtk_icon_view_queue_layout (GtkIconView *icon_view);
339 static void gtk_icon_view_set_cursor_item (GtkIconView *icon_view,
340 GtkIconViewItem *item,
342 static void gtk_icon_view_start_rubberbanding (GtkIconView *icon_view,
346 static void gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view);
347 static void gtk_icon_view_update_rubberband_selection (GtkIconView *icon_view);
348 static gboolean gtk_icon_view_item_hit_test (GtkIconView *icon_view,
349 GtkIconViewItem *item,
354 static gboolean gtk_icon_view_unselect_all_internal (GtkIconView *icon_view);
355 static void gtk_icon_view_calculate_item_size (GtkIconView *icon_view,
356 GtkIconViewItem *item);
357 static void gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view,
358 GtkIconViewItem *item,
360 static void gtk_icon_view_update_rubberband (gpointer data);
361 static void gtk_icon_view_item_invalidate_size (GtkIconViewItem *item);
362 static void gtk_icon_view_invalidate_sizes (GtkIconView *icon_view);
363 static void gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
366 GtkMovementStep step,
368 static gboolean gtk_icon_view_real_move_cursor (GtkIconView *icon_view,
369 GtkMovementStep step,
371 static void gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
373 static void gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
375 static void gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
377 static void gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
379 static void gtk_icon_view_scroll_to_item (GtkIconView *icon_view,
380 GtkIconViewItem *item);
381 static void gtk_icon_view_select_item (GtkIconView *icon_view,
382 GtkIconViewItem *item);
383 static void gtk_icon_view_unselect_item (GtkIconView *icon_view,
384 GtkIconViewItem *item);
385 static gboolean gtk_icon_view_select_all_between (GtkIconView *icon_view,
386 GtkIconViewItem *anchor,
387 GtkIconViewItem *cursor);
388 static GtkIconViewItem * gtk_icon_view_get_item_at_coords (GtkIconView *icon_view,
391 gboolean only_in_cell,
392 GtkIconViewCellInfo **cell_at_pos);
393 static void gtk_icon_view_get_cell_area (GtkIconView *icon_view,
394 GtkIconViewItem *item,
395 GtkIconViewCellInfo *cell_info,
396 GdkRectangle *cell_area);
397 static void gtk_icon_view_get_cell_box (GtkIconView *icon_view,
398 GtkIconViewItem *item,
399 GtkIconViewCellInfo *info,
401 static GtkIconViewCellInfo *gtk_icon_view_get_cell_info (GtkIconView *icon_view,
402 GtkCellRenderer *renderer);
403 static void gtk_icon_view_set_cell_data (GtkIconView *icon_view,
404 GtkIconViewItem *item);
405 static void gtk_icon_view_cell_layout_pack_start (GtkCellLayout *layout,
406 GtkCellRenderer *renderer,
408 static void gtk_icon_view_cell_layout_pack_end (GtkCellLayout *layout,
409 GtkCellRenderer *renderer,
411 static void gtk_icon_view_cell_layout_add_attribute (GtkCellLayout *layout,
412 GtkCellRenderer *renderer,
413 const gchar *attribute,
415 static void gtk_icon_view_cell_layout_clear (GtkCellLayout *layout);
416 static void gtk_icon_view_cell_layout_clear_attributes (GtkCellLayout *layout,
417 GtkCellRenderer *renderer);
418 static void gtk_icon_view_cell_layout_set_cell_data_func (GtkCellLayout *layout,
419 GtkCellRenderer *cell,
420 GtkCellLayoutDataFunc func,
422 GDestroyNotify destroy);
423 static void gtk_icon_view_cell_layout_reorder (GtkCellLayout *layout,
424 GtkCellRenderer *cell,
426 static GList * gtk_icon_view_cell_layout_get_cells (GtkCellLayout *layout);
428 static void gtk_icon_view_item_activate_cell (GtkIconView *icon_view,
429 GtkIconViewItem *item,
430 GtkIconViewCellInfo *cell_info,
432 static void gtk_icon_view_item_selected_changed (GtkIconView *icon_view,
433 GtkIconViewItem *item);
434 static void gtk_icon_view_put (GtkIconView *icon_view,
436 GtkIconViewItem *item,
438 static void gtk_icon_view_remove_widget (GtkCellEditable *editable,
439 GtkIconView *icon_view);
440 static void gtk_icon_view_start_editing (GtkIconView *icon_view,
441 GtkIconViewItem *item,
442 GtkIconViewCellInfo *cell_info,
444 static void gtk_icon_view_stop_editing (GtkIconView *icon_view,
445 gboolean cancel_editing);
447 /* Source side drag signals */
448 static void gtk_icon_view_drag_begin (GtkWidget *widget,
449 GdkDragContext *context);
450 static void gtk_icon_view_drag_end (GtkWidget *widget,
451 GdkDragContext *context);
452 static void gtk_icon_view_drag_data_get (GtkWidget *widget,
453 GdkDragContext *context,
454 GtkSelectionData *selection_data,
457 static void gtk_icon_view_drag_data_delete (GtkWidget *widget,
458 GdkDragContext *context);
460 /* Target side drag signals */
461 static void gtk_icon_view_drag_leave (GtkWidget *widget,
462 GdkDragContext *context,
464 static gboolean gtk_icon_view_drag_motion (GtkWidget *widget,
465 GdkDragContext *context,
469 static gboolean gtk_icon_view_drag_drop (GtkWidget *widget,
470 GdkDragContext *context,
474 static void gtk_icon_view_drag_data_received (GtkWidget *widget,
475 GdkDragContext *context,
478 GtkSelectionData *selection_data,
481 static gboolean gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
482 GdkEventMotion *event);
484 static void remove_scroll_timeout (GtkIconView *icon_view);
486 static void adjust_wrap_width (GtkIconView *icon_view,
487 GtkIconViewItem *item);
490 static GtkBuildableIface *parent_buildable_iface;
491 static void gtk_icon_view_buildable_init (GtkBuildableIface *iface);
492 static gboolean gtk_icon_view_buildable_custom_tag_start (GtkBuildable *buildable,
495 const gchar *tagname,
496 GMarkupParser *parser,
498 static void gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable,
501 const gchar *tagname,
504 static guint icon_view_signals[LAST_SIGNAL] = { 0 };
506 G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
507 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
508 gtk_icon_view_cell_layout_init)
509 G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
510 gtk_icon_view_buildable_init)
511 G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
514 gtk_icon_view_class_init (GtkIconViewClass *klass)
516 GObjectClass *gobject_class;
517 GtkWidgetClass *widget_class;
518 GtkContainerClass *container_class;
519 GtkBindingSet *binding_set;
521 binding_set = gtk_binding_set_by_class (klass);
523 g_type_class_add_private (klass, sizeof (GtkIconViewPrivate));
525 gobject_class = (GObjectClass *) klass;
526 widget_class = (GtkWidgetClass *) klass;
527 container_class = (GtkContainerClass *) klass;
529 gobject_class->finalize = gtk_icon_view_finalize;
530 gobject_class->set_property = gtk_icon_view_set_property;
531 gobject_class->get_property = gtk_icon_view_get_property;
533 widget_class->destroy = gtk_icon_view_destroy;
534 widget_class->realize = gtk_icon_view_realize;
535 widget_class->unrealize = gtk_icon_view_unrealize;
536 widget_class->style_set = gtk_icon_view_style_set;
537 widget_class->get_accessible = gtk_icon_view_get_accessible;
538 widget_class->get_preferred_width = gtk_icon_view_get_preferred_width;
539 widget_class->get_preferred_height = gtk_icon_view_get_preferred_height;
540 widget_class->size_allocate = gtk_icon_view_size_allocate;
541 widget_class->draw = gtk_icon_view_draw;
542 widget_class->motion_notify_event = gtk_icon_view_motion;
543 widget_class->button_press_event = gtk_icon_view_button_press;
544 widget_class->button_release_event = gtk_icon_view_button_release;
545 widget_class->key_press_event = gtk_icon_view_key_press;
546 widget_class->key_release_event = gtk_icon_view_key_release;
547 widget_class->drag_begin = gtk_icon_view_drag_begin;
548 widget_class->drag_end = gtk_icon_view_drag_end;
549 widget_class->drag_data_get = gtk_icon_view_drag_data_get;
550 widget_class->drag_data_delete = gtk_icon_view_drag_data_delete;
551 widget_class->drag_leave = gtk_icon_view_drag_leave;
552 widget_class->drag_motion = gtk_icon_view_drag_motion;
553 widget_class->drag_drop = gtk_icon_view_drag_drop;
554 widget_class->drag_data_received = gtk_icon_view_drag_data_received;
555 widget_class->state_changed = gtk_icon_view_state_changed;
557 container_class->remove = gtk_icon_view_remove;
558 container_class->forall = gtk_icon_view_forall;
560 klass->select_all = gtk_icon_view_real_select_all;
561 klass->unselect_all = gtk_icon_view_real_unselect_all;
562 klass->select_cursor_item = gtk_icon_view_real_select_cursor_item;
563 klass->toggle_cursor_item = gtk_icon_view_real_toggle_cursor_item;
564 klass->activate_cursor_item = gtk_icon_view_real_activate_cursor_item;
565 klass->move_cursor = gtk_icon_view_real_move_cursor;
569 * GtkIconView:selection-mode:
571 * The ::selection-mode property specifies the selection mode of
572 * icon view. If the mode is #GTK_SELECTION_MULTIPLE, rubberband selection
573 * is enabled, for the other modes, only keyboard selection is possible.
577 g_object_class_install_property (gobject_class,
579 g_param_spec_enum ("selection-mode",
580 P_("Selection mode"),
581 P_("The selection mode"),
582 GTK_TYPE_SELECTION_MODE,
583 GTK_SELECTION_SINGLE,
584 GTK_PARAM_READWRITE));
587 * GtkIconView:pixbuf-column:
589 * The ::pixbuf-column property contains the number of the model column
590 * containing the pixbufs which are displayed. The pixbuf column must be
591 * of type #GDK_TYPE_PIXBUF. Setting this property to -1 turns off the
592 * display of pixbufs.
596 g_object_class_install_property (gobject_class,
598 g_param_spec_int ("pixbuf-column",
600 P_("Model column used to retrieve the icon pixbuf from"),
602 GTK_PARAM_READWRITE));
605 * GtkIconView:text-column:
607 * The ::text-column property contains the number of the model column
608 * containing the texts which are displayed. The text column must be
609 * of type #G_TYPE_STRING. If this property and the :markup-column
610 * property are both set to -1, no texts are displayed.
614 g_object_class_install_property (gobject_class,
616 g_param_spec_int ("text-column",
618 P_("Model column used to retrieve the text from"),
620 GTK_PARAM_READWRITE));
624 * GtkIconView:markup-column:
626 * The ::markup-column property contains the number of the model column
627 * containing markup information to be displayed. The markup column must be
628 * of type #G_TYPE_STRING. If this property and the :text-column property
629 * are both set to column numbers, it overrides the text column.
630 * If both are set to -1, no texts are displayed.
634 g_object_class_install_property (gobject_class,
636 g_param_spec_int ("markup-column",
638 P_("Model column used to retrieve the text if using Pango markup"),
640 GTK_PARAM_READWRITE));
642 g_object_class_install_property (gobject_class,
644 g_param_spec_object ("model",
645 P_("Icon View Model"),
646 P_("The model for the icon view"),
648 GTK_PARAM_READWRITE));
651 * GtkIconView:columns:
653 * The columns property contains the number of the columns in which the
654 * items should be displayed. If it is -1, the number of columns will
655 * be chosen automatically to fill the available area.
659 g_object_class_install_property (gobject_class,
661 g_param_spec_int ("columns",
662 P_("Number of columns"),
663 P_("Number of columns to display"),
665 GTK_PARAM_READWRITE));
669 * GtkIconView:item-width:
671 * The item-width property specifies the width to use for each item.
672 * If it is set to -1, the icon view will automatically determine a
673 * suitable item size.
677 g_object_class_install_property (gobject_class,
679 g_param_spec_int ("item-width",
680 P_("Width for each item"),
681 P_("The width used for each item"),
683 GTK_PARAM_READWRITE));
686 * GtkIconView:spacing:
688 * The spacing property specifies the space which is inserted between
689 * the cells (i.e. the icon and the text) of an item.
693 g_object_class_install_property (gobject_class,
695 g_param_spec_int ("spacing",
697 P_("Space which is inserted between cells of an item"),
699 GTK_PARAM_READWRITE));
702 * GtkIconView:row-spacing:
704 * The row-spacing property specifies the space which is inserted between
705 * the rows of the icon view.
709 g_object_class_install_property (gobject_class,
711 g_param_spec_int ("row-spacing",
713 P_("Space which is inserted between grid rows"),
715 GTK_PARAM_READWRITE));
718 * GtkIconView:column-spacing:
720 * The column-spacing property specifies the space which is inserted between
721 * the columns of the icon view.
725 g_object_class_install_property (gobject_class,
727 g_param_spec_int ("column-spacing",
728 P_("Column Spacing"),
729 P_("Space which is inserted between grid columns"),
731 GTK_PARAM_READWRITE));
734 * GtkIconView:margin:
736 * The margin property specifies the space which is inserted
737 * at the edges of the icon view.
741 g_object_class_install_property (gobject_class,
743 g_param_spec_int ("margin",
745 P_("Space which is inserted at the edges of the icon view"),
747 GTK_PARAM_READWRITE));
750 * GtkIconView:item-orientation:
752 * The item-orientation property specifies how the cells (i.e. the icon and
753 * the text) of the item are positioned relative to each other.
757 g_object_class_install_property (gobject_class,
758 PROP_ITEM_ORIENTATION,
759 g_param_spec_enum ("item-orientation",
760 P_("Item Orientation"),
761 P_("How the text and icon of each item are positioned relative to each other"),
762 GTK_TYPE_ORIENTATION,
763 GTK_ORIENTATION_VERTICAL,
764 GTK_PARAM_READWRITE));
767 * GtkIconView:reorderable:
769 * The reorderable property specifies if the items can be reordered
774 g_object_class_install_property (gobject_class,
776 g_param_spec_boolean ("reorderable",
778 P_("View is reorderable"),
782 g_object_class_install_property (gobject_class,
784 g_param_spec_int ("tooltip-column",
785 P_("Tooltip Column"),
786 P_("The column in the model containing the tooltip texts for the items"),
790 GTK_PARAM_READWRITE));
793 * GtkIconView:item-padding:
795 * The item-padding property specifies the padding around each
796 * of the icon view's item.
800 g_object_class_install_property (gobject_class,
802 g_param_spec_int ("item-padding",
804 P_("Padding around icon view items"),
806 GTK_PARAM_READWRITE));
808 /* Scrollable interface properties */
809 g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment");
810 g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment");
811 g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
812 g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
814 /* Style properties */
815 gtk_widget_class_install_style_property (widget_class,
816 g_param_spec_boxed ("selection-box-color",
817 P_("Selection Box Color"),
818 P_("Color of the selection box"),
820 GTK_PARAM_READABLE));
822 gtk_widget_class_install_style_property (widget_class,
823 g_param_spec_uchar ("selection-box-alpha",
824 P_("Selection Box Alpha"),
825 P_("Opacity of the selection box"),
828 GTK_PARAM_READABLE));
832 * GtkIconView::item-activated:
833 * @iconview: the object on which the signal is emitted
834 * @path: the #GtkTreePath for the activated item
836 * The ::item-activated signal is emitted when the method
837 * gtk_icon_view_item_activated() is called or the user double
838 * clicks an item. It is also emitted when a non-editable item
839 * is selected and one of the keys: Space, Return or Enter is
842 icon_view_signals[ITEM_ACTIVATED] =
843 g_signal_new (I_("item-activated"),
844 G_TYPE_FROM_CLASS (gobject_class),
846 G_STRUCT_OFFSET (GtkIconViewClass, item_activated),
848 g_cclosure_marshal_VOID__BOXED,
853 * GtkIconView::selection-changed:
854 * @iconview: the object on which the signal is emitted
856 * The ::selection-changed signal is emitted when the selection
857 * (i.e. the set of selected items) changes.
859 icon_view_signals[SELECTION_CHANGED] =
860 g_signal_new (I_("selection-changed"),
861 G_TYPE_FROM_CLASS (gobject_class),
863 G_STRUCT_OFFSET (GtkIconViewClass, selection_changed),
865 g_cclosure_marshal_VOID__VOID,
869 * GtkIconView::select-all:
870 * @iconview: the object on which the signal is emitted
872 * A <link linkend="keybinding-signals">keybinding signal</link>
873 * which gets emitted when the user selects all items.
875 * Applications should not connect to it, but may emit it with
876 * g_signal_emit_by_name() if they need to control selection
879 * The default binding for this signal is Ctrl-a.
881 icon_view_signals[SELECT_ALL] =
882 g_signal_new (I_("select-all"),
883 G_TYPE_FROM_CLASS (gobject_class),
884 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
885 G_STRUCT_OFFSET (GtkIconViewClass, select_all),
887 g_cclosure_marshal_VOID__VOID,
891 * GtkIconView::unselect-all:
892 * @iconview: the object on which the signal is emitted
894 * A <link linkend="keybinding-signals">keybinding signal</link>
895 * which gets emitted when the user unselects all items.
897 * Applications should not connect to it, but may emit it with
898 * g_signal_emit_by_name() if they need to control selection
901 * The default binding for this signal is Ctrl-Shift-a.
903 icon_view_signals[UNSELECT_ALL] =
904 g_signal_new (I_("unselect-all"),
905 G_TYPE_FROM_CLASS (gobject_class),
906 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
907 G_STRUCT_OFFSET (GtkIconViewClass, unselect_all),
909 g_cclosure_marshal_VOID__VOID,
913 * GtkIconView::select-cursor-item:
914 * @iconview: the object on which the signal is emitted
916 * A <link linkend="keybinding-signals">keybinding signal</link>
917 * which gets emitted when the user selects the item that is currently
920 * Applications should not connect to it, but may emit it with
921 * g_signal_emit_by_name() if they need to control selection
924 * There is no default binding for this signal.
926 icon_view_signals[SELECT_CURSOR_ITEM] =
927 g_signal_new (I_("select-cursor-item"),
928 G_TYPE_FROM_CLASS (gobject_class),
929 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
930 G_STRUCT_OFFSET (GtkIconViewClass, select_cursor_item),
932 g_cclosure_marshal_VOID__VOID,
936 * GtkIconView::toggle-cursor-item:
937 * @iconview: the object on which the signal is emitted
939 * A <link linkend="keybinding-signals">keybinding signal</link>
940 * which gets emitted when the user toggles whether the currently
941 * focused item is selected or not. The exact effect of this
942 * depend on the selection mode.
944 * Applications should not connect to it, but may emit it with
945 * g_signal_emit_by_name() if they need to control selection
948 * There is no default binding for this signal is Ctrl-Space.
950 icon_view_signals[TOGGLE_CURSOR_ITEM] =
951 g_signal_new (I_("toggle-cursor-item"),
952 G_TYPE_FROM_CLASS (gobject_class),
953 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
954 G_STRUCT_OFFSET (GtkIconViewClass, toggle_cursor_item),
956 g_cclosure_marshal_VOID__VOID,
960 * GtkIconView::activate-cursor-item:
961 * @iconview: the object on which the signal is emitted
963 * A <link linkend="keybinding-signals">keybinding signal</link>
964 * which gets emitted when the user activates the currently
967 * Applications should not connect to it, but may emit it with
968 * g_signal_emit_by_name() if they need to control activation
971 * The default bindings for this signal are Space, Return and Enter.
973 icon_view_signals[ACTIVATE_CURSOR_ITEM] =
974 g_signal_new (I_("activate-cursor-item"),
975 G_TYPE_FROM_CLASS (gobject_class),
976 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
977 G_STRUCT_OFFSET (GtkIconViewClass, activate_cursor_item),
979 _gtk_marshal_BOOLEAN__VOID,
983 * GtkIconView::move-cursor:
984 * @iconview: the object which received the signal
985 * @step: the granularity of the move, as a #GtkMovementStep
986 * @count: the number of @step units to move
988 * The ::move-cursor signal is a
989 * <link linkend="keybinding-signals">keybinding signal</link>
990 * which gets emitted when the user initiates a cursor movement.
992 * Applications should not connect to it, but may emit it with
993 * g_signal_emit_by_name() if they need to control the cursor
996 * The default bindings for this signal include
998 * <listitem>Arrow keys which move by individual steps</listitem>
999 * <listitem>Home/End keys which move to the first/last item</listitem>
1000 * <listitem>PageUp/PageDown which move by "pages"</listitem>
1003 * All of these will extend the selection when combined with
1004 * the Shift modifier.
1006 icon_view_signals[MOVE_CURSOR] =
1007 g_signal_new (I_("move-cursor"),
1008 G_TYPE_FROM_CLASS (gobject_class),
1009 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1010 G_STRUCT_OFFSET (GtkIconViewClass, move_cursor),
1012 _gtk_marshal_BOOLEAN__ENUM_INT,
1014 GTK_TYPE_MOVEMENT_STEP,
1018 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
1020 gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
1022 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
1023 "toggle-cursor-item", 0);
1024 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
1025 "toggle-cursor-item", 0);
1027 gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
1028 "activate-cursor-item", 0);
1029 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
1030 "activate-cursor-item", 0);
1031 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
1032 "activate-cursor-item", 0);
1033 gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
1034 "activate-cursor-item", 0);
1035 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
1036 "activate-cursor-item", 0);
1038 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Up, 0,
1039 GTK_MOVEMENT_DISPLAY_LINES, -1);
1040 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
1041 GTK_MOVEMENT_DISPLAY_LINES, -1);
1043 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Down, 0,
1044 GTK_MOVEMENT_DISPLAY_LINES, 1);
1045 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
1046 GTK_MOVEMENT_DISPLAY_LINES, 1);
1048 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK,
1049 GTK_MOVEMENT_DISPLAY_LINES, -1);
1051 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK,
1052 GTK_MOVEMENT_DISPLAY_LINES, 1);
1054 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Home, 0,
1055 GTK_MOVEMENT_BUFFER_ENDS, -1);
1056 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
1057 GTK_MOVEMENT_BUFFER_ENDS, -1);
1059 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_End, 0,
1060 GTK_MOVEMENT_BUFFER_ENDS, 1);
1061 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
1062 GTK_MOVEMENT_BUFFER_ENDS, 1);
1064 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
1065 GTK_MOVEMENT_PAGES, -1);
1066 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
1067 GTK_MOVEMENT_PAGES, -1);
1069 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
1070 GTK_MOVEMENT_PAGES, 1);
1071 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
1072 GTK_MOVEMENT_PAGES, 1);
1074 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Right, 0,
1075 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1076 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Left, 0,
1077 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1079 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
1080 GTK_MOVEMENT_VISUAL_POSITIONS, 1);
1081 gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
1082 GTK_MOVEMENT_VISUAL_POSITIONS, -1);
1086 gtk_icon_view_buildable_init (GtkBuildableIface *iface)
1088 parent_buildable_iface = g_type_interface_peek_parent (iface);
1089 iface->add_child = _gtk_cell_layout_buildable_add_child;
1090 iface->custom_tag_start = gtk_icon_view_buildable_custom_tag_start;
1091 iface->custom_tag_end = gtk_icon_view_buildable_custom_tag_end;
1095 gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface)
1097 iface->pack_start = gtk_icon_view_cell_layout_pack_start;
1098 iface->pack_end = gtk_icon_view_cell_layout_pack_end;
1099 iface->clear = gtk_icon_view_cell_layout_clear;
1100 iface->add_attribute = gtk_icon_view_cell_layout_add_attribute;
1101 iface->set_cell_data_func = gtk_icon_view_cell_layout_set_cell_data_func;
1102 iface->clear_attributes = gtk_icon_view_cell_layout_clear_attributes;
1103 iface->reorder = gtk_icon_view_cell_layout_reorder;
1104 iface->get_cells = gtk_icon_view_cell_layout_get_cells;
1108 gtk_icon_view_init (GtkIconView *icon_view)
1110 icon_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (icon_view,
1112 GtkIconViewPrivate);
1114 icon_view->priv->width = 0;
1115 icon_view->priv->height = 0;
1116 icon_view->priv->selection_mode = GTK_SELECTION_SINGLE;
1117 icon_view->priv->pressed_button = -1;
1118 icon_view->priv->press_start_x = -1;
1119 icon_view->priv->press_start_y = -1;
1120 icon_view->priv->text_column = -1;
1121 icon_view->priv->markup_column = -1;
1122 icon_view->priv->pixbuf_column = -1;
1123 icon_view->priv->text_cell = -1;
1124 icon_view->priv->pixbuf_cell = -1;
1125 icon_view->priv->tooltip_column = -1;
1127 gtk_widget_set_can_focus (GTK_WIDGET (icon_view), TRUE);
1129 icon_view->priv->cell_list = NULL;
1130 icon_view->priv->n_cells = 0;
1131 icon_view->priv->cursor_cell = -1;
1133 icon_view->priv->item_orientation = GTK_ORIENTATION_VERTICAL;
1135 icon_view->priv->columns = -1;
1136 icon_view->priv->item_width = -1;
1137 icon_view->priv->spacing = 0;
1138 icon_view->priv->row_spacing = 6;
1139 icon_view->priv->column_spacing = 6;
1140 icon_view->priv->margin = 6;
1141 icon_view->priv->item_padding = 6;
1143 icon_view->priv->draw_focus = TRUE;
1146 /* GObject methods */
1148 gtk_icon_view_finalize (GObject *object)
1150 gtk_icon_view_cell_layout_clear (GTK_CELL_LAYOUT (object));
1152 G_OBJECT_CLASS (gtk_icon_view_parent_class)->finalize (object);
1157 gtk_icon_view_set_property (GObject *object,
1159 const GValue *value,
1162 GtkIconView *icon_view;
1164 icon_view = GTK_ICON_VIEW (object);
1168 case PROP_SELECTION_MODE:
1169 gtk_icon_view_set_selection_mode (icon_view, g_value_get_enum (value));
1171 case PROP_PIXBUF_COLUMN:
1172 gtk_icon_view_set_pixbuf_column (icon_view, g_value_get_int (value));
1174 case PROP_TEXT_COLUMN:
1175 gtk_icon_view_set_text_column (icon_view, g_value_get_int (value));
1177 case PROP_MARKUP_COLUMN:
1178 gtk_icon_view_set_markup_column (icon_view, g_value_get_int (value));
1181 gtk_icon_view_set_model (icon_view, g_value_get_object (value));
1183 case PROP_ITEM_ORIENTATION:
1184 gtk_icon_view_set_item_orientation (icon_view, g_value_get_enum (value));
1187 gtk_icon_view_set_columns (icon_view, g_value_get_int (value));
1189 case PROP_ITEM_WIDTH:
1190 gtk_icon_view_set_item_width (icon_view, g_value_get_int (value));
1193 gtk_icon_view_set_spacing (icon_view, g_value_get_int (value));
1195 case PROP_ROW_SPACING:
1196 gtk_icon_view_set_row_spacing (icon_view, g_value_get_int (value));
1198 case PROP_COLUMN_SPACING:
1199 gtk_icon_view_set_column_spacing (icon_view, g_value_get_int (value));
1202 gtk_icon_view_set_margin (icon_view, g_value_get_int (value));
1204 case PROP_REORDERABLE:
1205 gtk_icon_view_set_reorderable (icon_view, g_value_get_boolean (value));
1208 case PROP_TOOLTIP_COLUMN:
1209 gtk_icon_view_set_tooltip_column (icon_view, g_value_get_int (value));
1212 case PROP_ITEM_PADDING:
1213 gtk_icon_view_set_item_padding (icon_view, g_value_get_int (value));
1216 case PROP_HADJUSTMENT:
1217 gtk_icon_view_set_hadjustment (icon_view, g_value_get_object (value));
1219 case PROP_VADJUSTMENT:
1220 gtk_icon_view_set_vadjustment (icon_view, g_value_get_object (value));
1222 case PROP_HSCROLL_POLICY:
1223 icon_view->priv->hscroll_policy = g_value_get_enum (value);
1224 gtk_widget_queue_resize (GTK_WIDGET (icon_view));
1226 case PROP_VSCROLL_POLICY:
1227 icon_view->priv->vscroll_policy = g_value_get_enum (value);
1228 gtk_widget_queue_resize (GTK_WIDGET (icon_view));
1232 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1238 gtk_icon_view_get_property (GObject *object,
1243 GtkIconView *icon_view;
1245 icon_view = GTK_ICON_VIEW (object);
1249 case PROP_SELECTION_MODE:
1250 g_value_set_enum (value, icon_view->priv->selection_mode);
1252 case PROP_PIXBUF_COLUMN:
1253 g_value_set_int (value, icon_view->priv->pixbuf_column);
1255 case PROP_TEXT_COLUMN:
1256 g_value_set_int (value, icon_view->priv->text_column);
1258 case PROP_MARKUP_COLUMN:
1259 g_value_set_int (value, icon_view->priv->markup_column);
1262 g_value_set_object (value, icon_view->priv->model);
1264 case PROP_ITEM_ORIENTATION:
1265 g_value_set_enum (value, icon_view->priv->item_orientation);
1268 g_value_set_int (value, icon_view->priv->columns);
1270 case PROP_ITEM_WIDTH:
1271 g_value_set_int (value, icon_view->priv->item_width);
1274 g_value_set_int (value, icon_view->priv->spacing);
1276 case PROP_ROW_SPACING:
1277 g_value_set_int (value, icon_view->priv->row_spacing);
1279 case PROP_COLUMN_SPACING:
1280 g_value_set_int (value, icon_view->priv->column_spacing);
1283 g_value_set_int (value, icon_view->priv->margin);
1285 case PROP_REORDERABLE:
1286 g_value_set_boolean (value, icon_view->priv->reorderable);
1288 case PROP_TOOLTIP_COLUMN:
1289 g_value_set_int (value, icon_view->priv->tooltip_column);
1292 case PROP_ITEM_PADDING:
1293 g_value_set_int (value, icon_view->priv->item_padding);
1296 case PROP_HADJUSTMENT:
1297 g_value_set_object (value, icon_view->priv->hadjustment);
1299 case PROP_VADJUSTMENT:
1300 g_value_set_object (value, icon_view->priv->vadjustment);
1302 case PROP_HSCROLL_POLICY:
1303 g_value_set_enum (value, icon_view->priv->hscroll_policy);
1305 case PROP_VSCROLL_POLICY:
1306 g_value_set_enum (value, icon_view->priv->vscroll_policy);
1310 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1315 /* GtkWidget methods */
1317 gtk_icon_view_destroy (GtkWidget *widget)
1319 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
1321 gtk_icon_view_stop_editing (icon_view, TRUE);
1323 gtk_icon_view_set_model (icon_view, NULL);
1325 if (icon_view->priv->layout_idle_id != 0)
1327 g_source_remove (icon_view->priv->layout_idle_id);
1328 icon_view->priv->layout_idle_id = 0;
1331 if (icon_view->priv->scroll_to_path != NULL)
1333 gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
1334 icon_view->priv->scroll_to_path = NULL;
1337 remove_scroll_timeout (icon_view);
1339 if (icon_view->priv->hadjustment != NULL)
1341 g_object_unref (icon_view->priv->hadjustment);
1342 icon_view->priv->hadjustment = NULL;
1345 if (icon_view->priv->vadjustment != NULL)
1347 g_object_unref (icon_view->priv->vadjustment);
1348 icon_view->priv->vadjustment = NULL;
1351 GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->destroy (widget);
1355 gtk_icon_view_realize (GtkWidget *widget)
1357 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
1358 GtkAllocation allocation;
1360 GdkWindowAttr attributes;
1361 gint attributes_mask;
1363 gtk_widget_set_realized (widget, TRUE);
1365 gtk_widget_get_allocation (widget, &allocation);
1367 /* Make the main, clipping window */
1368 attributes.window_type = GDK_WINDOW_CHILD;
1369 attributes.x = allocation.x;
1370 attributes.y = allocation.y;
1371 attributes.width = allocation.width;
1372 attributes.height = allocation.height;
1373 attributes.wclass = GDK_INPUT_OUTPUT;
1374 attributes.visual = gtk_widget_get_visual (widget);
1375 attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
1377 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
1379 window = gdk_window_new (gtk_widget_get_parent_window (widget),
1380 &attributes, attributes_mask);
1381 gtk_widget_set_window (widget, window);
1382 gdk_window_set_user_data (window, widget);
1384 gtk_widget_get_allocation (widget, &allocation);
1386 /* Make the window for the icon view */
1389 attributes.width = MAX (icon_view->priv->width, allocation.width);
1390 attributes.height = MAX (icon_view->priv->height, allocation.height);
1391 attributes.event_mask = (GDK_EXPOSURE_MASK |
1393 GDK_POINTER_MOTION_MASK |
1394 GDK_BUTTON_PRESS_MASK |
1395 GDK_BUTTON_RELEASE_MASK |
1396 GDK_KEY_PRESS_MASK |
1397 GDK_KEY_RELEASE_MASK) |
1398 gtk_widget_get_events (widget);
1400 icon_view->priv->bin_window = gdk_window_new (window,
1401 &attributes, attributes_mask);
1402 gdk_window_set_user_data (icon_view->priv->bin_window, widget);
1404 gtk_widget_style_attach (widget);
1405 gdk_window_set_background (icon_view->priv->bin_window,
1406 >k_widget_get_style (widget)->base[gtk_widget_get_state (widget)]);
1408 gdk_window_show (icon_view->priv->bin_window);
1412 gtk_icon_view_unrealize (GtkWidget *widget)
1414 GtkIconView *icon_view;
1416 icon_view = GTK_ICON_VIEW (widget);
1418 gdk_window_set_user_data (icon_view->priv->bin_window, NULL);
1419 gdk_window_destroy (icon_view->priv->bin_window);
1420 icon_view->priv->bin_window = NULL;
1422 GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->unrealize (widget);
1426 gtk_icon_view_state_changed (GtkWidget *widget,
1427 GtkStateType previous_state)
1429 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
1433 if (gtk_widget_get_realized (widget))
1435 style = gtk_widget_get_style (widget);
1436 state = gtk_widget_get_state (widget);
1438 gdk_window_set_background (gtk_widget_get_window (widget), &style->base[state]);
1439 gdk_window_set_background (icon_view->priv->bin_window, &style->base[state]);
1442 gtk_widget_queue_draw (widget);
1446 gtk_icon_view_style_set (GtkWidget *widget,
1447 GtkStyle *previous_style)
1449 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
1453 if (gtk_widget_get_realized (widget))
1455 style = gtk_widget_get_style (widget);
1456 state = gtk_widget_get_state (widget);
1458 gdk_window_set_background (gtk_widget_get_window (widget), &style->base[state]);
1459 gdk_window_set_background (icon_view->priv->bin_window, &style->base[state]);
1462 gtk_widget_queue_resize (widget);
1466 gtk_icon_view_get_preferred_width (GtkWidget *widget,
1470 *minimum = *natural = GTK_ICON_VIEW (widget)->priv->width;
1474 gtk_icon_view_get_preferred_height (GtkWidget *widget,
1478 *minimum = *natural = GTK_ICON_VIEW (widget)->priv->height;
1482 gtk_icon_view_allocate_children (GtkIconView *icon_view)
1486 for (list = icon_view->priv->children; list; list = list->next)
1488 GtkIconViewChild *child = list->data;
1489 GtkAllocation allocation;
1491 /* totally ignore our child's requisition */
1492 if (child->cell < 0)
1494 allocation.x = child->item->x + icon_view->priv->item_padding;
1495 allocation.y = child->item->y + icon_view->priv->item_padding;
1496 allocation.width = child->item->width - icon_view->priv->item_padding * 2;
1497 allocation.height = child->item->height - icon_view->priv->item_padding * 2;
1501 GdkRectangle *box = &child->item->box[child->cell];
1503 allocation.x = box->x;
1504 allocation.y = box->y;
1505 allocation.width = box->width;
1506 allocation.height = box->height;
1509 gtk_widget_size_allocate (child->widget, &allocation);
1514 gtk_icon_view_size_allocate (GtkWidget *widget,
1515 GtkAllocation *allocation)
1517 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
1519 gtk_widget_set_allocation (widget, allocation);
1521 if (gtk_widget_get_realized (widget))
1523 gdk_window_move_resize (gtk_widget_get_window (widget),
1524 allocation->x, allocation->y,
1525 allocation->width, allocation->height);
1526 gdk_window_resize (icon_view->priv->bin_window,
1527 MAX (icon_view->priv->width, allocation->width),
1528 MAX (icon_view->priv->height, allocation->height));
1531 gtk_icon_view_layout (icon_view);
1533 gtk_icon_view_allocate_children (icon_view);
1535 /* Delay signal emission */
1536 g_object_freeze_notify (G_OBJECT (icon_view->priv->hadjustment));
1537 g_object_freeze_notify (G_OBJECT (icon_view->priv->vadjustment));
1539 gtk_icon_view_set_hadjustment_values (icon_view);
1540 gtk_icon_view_set_vadjustment_values (icon_view);
1542 if (gtk_widget_get_realized (widget) &&
1543 icon_view->priv->scroll_to_path)
1546 path = gtk_tree_row_reference_get_path (icon_view->priv->scroll_to_path);
1547 gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
1548 icon_view->priv->scroll_to_path = NULL;
1550 gtk_icon_view_scroll_to_path (icon_view, path,
1551 icon_view->priv->scroll_to_use_align,
1552 icon_view->priv->scroll_to_row_align,
1553 icon_view->priv->scroll_to_col_align);
1554 gtk_tree_path_free (path);
1557 /* Emit any pending signals now */
1558 g_object_thaw_notify (G_OBJECT (icon_view->priv->hadjustment));
1559 g_object_thaw_notify (G_OBJECT (icon_view->priv->vadjustment));
1563 gtk_icon_view_draw (GtkWidget *widget,
1566 GtkIconView *icon_view;
1570 GtkIconViewDropPosition dest_pos;
1571 GtkIconViewItem *dest_item = NULL;
1573 icon_view = GTK_ICON_VIEW (widget);
1575 if (!gtk_cairo_should_draw_window (cr, icon_view->priv->bin_window))
1580 gtk_cairo_transform_to_window (cr, widget, icon_view->priv->bin_window);
1582 cairo_set_line_width (cr, 1.);
1584 gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos);
1588 dest_index = gtk_tree_path_get_indices (path)[0];
1589 gtk_tree_path_free (path);
1594 for (icons = icon_view->priv->items; icons; icons = icons->next)
1596 GtkIconViewItem *item = icons->data;
1600 cairo_rectangle (cr, item->x, item->y, item->width, item->height);
1603 if (gdk_cairo_get_clip_rectangle (cr, NULL))
1605 gtk_icon_view_paint_item (icon_view, cr, item,
1607 icon_view->priv->draw_focus);
1609 if (dest_index == item->index)
1621 style = gtk_widget_get_style (widget);
1622 state = gtk_widget_get_state (widget);
1626 case GTK_ICON_VIEW_DROP_INTO:
1627 gtk_paint_focus (style,
1631 "iconview-drop-indicator",
1632 dest_item->x, dest_item->y,
1633 dest_item->width, dest_item->height);
1635 case GTK_ICON_VIEW_DROP_ABOVE:
1636 gtk_paint_focus (style,
1640 "iconview-drop-indicator",
1641 dest_item->x, dest_item->y - 1,
1642 dest_item->width, 2);
1644 case GTK_ICON_VIEW_DROP_LEFT:
1645 gtk_paint_focus (style,
1649 "iconview-drop-indicator",
1650 dest_item->x - 1, dest_item->y,
1651 2, dest_item->height);
1653 case GTK_ICON_VIEW_DROP_BELOW:
1654 gtk_paint_focus (style,
1658 "iconview-drop-indicator",
1659 dest_item->x, dest_item->y + dest_item->height - 1,
1660 dest_item->width, 2);
1662 case GTK_ICON_VIEW_DROP_RIGHT:
1663 gtk_paint_focus (style,
1667 "iconview-drop-indicator",
1668 dest_item->x + dest_item->width - 1, dest_item->y,
1669 2, dest_item->height);
1670 case GTK_ICON_VIEW_NO_DROP: ;
1675 if (icon_view->priv->doing_rubberband)
1676 gtk_icon_view_paint_rubberband (icon_view, cr);
1680 GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->draw (widget, cr);
1686 rubberband_scroll_timeout (gpointer data)
1688 GtkIconView *icon_view = data;
1690 gtk_adjustment_set_value (icon_view->priv->vadjustment,
1691 icon_view->priv->vadjustment->value +
1692 icon_view->priv->scroll_value_diff);
1694 gtk_icon_view_update_rubberband (icon_view);
1700 gtk_icon_view_motion (GtkWidget *widget,
1701 GdkEventMotion *event)
1703 GtkAllocation allocation;
1704 GtkIconView *icon_view;
1707 icon_view = GTK_ICON_VIEW (widget);
1709 gtk_icon_view_maybe_begin_drag (icon_view, event);
1711 if (icon_view->priv->doing_rubberband)
1713 gtk_icon_view_update_rubberband (widget);
1715 abs_y = event->y - icon_view->priv->height *
1716 (icon_view->priv->vadjustment->value /
1717 (icon_view->priv->vadjustment->upper -
1718 icon_view->priv->vadjustment->lower));
1720 gtk_widget_get_allocation (widget, &allocation);
1722 if (abs_y < 0 || abs_y > allocation.height)
1725 icon_view->priv->scroll_value_diff = abs_y;
1727 icon_view->priv->scroll_value_diff = abs_y - allocation.height;
1729 icon_view->priv->event_last_x = event->x;
1730 icon_view->priv->event_last_y = event->y;
1732 if (icon_view->priv->scroll_timeout_id == 0)
1733 icon_view->priv->scroll_timeout_id = gdk_threads_add_timeout (30, rubberband_scroll_timeout,
1737 remove_scroll_timeout (icon_view);
1744 gtk_icon_view_remove (GtkContainer *container,
1747 GtkIconView *icon_view;
1748 GtkIconViewChild *child = NULL;
1751 icon_view = GTK_ICON_VIEW (container);
1753 tmp_list = icon_view->priv->children;
1756 child = tmp_list->data;
1757 if (child->widget == widget)
1759 gtk_widget_unparent (widget);
1761 icon_view->priv->children = g_list_remove_link (icon_view->priv->children, tmp_list);
1762 g_list_free_1 (tmp_list);
1767 tmp_list = tmp_list->next;
1772 gtk_icon_view_forall (GtkContainer *container,
1773 gboolean include_internals,
1774 GtkCallback callback,
1775 gpointer callback_data)
1777 GtkIconView *icon_view;
1778 GtkIconViewChild *child = NULL;
1781 icon_view = GTK_ICON_VIEW (container);
1783 tmp_list = icon_view->priv->children;
1786 child = tmp_list->data;
1787 tmp_list = tmp_list->next;
1789 (* callback) (child->widget, callback_data);
1794 gtk_icon_view_item_activate_cell (GtkIconView *icon_view,
1795 GtkIconViewItem *item,
1796 GtkIconViewCellInfo *info,
1801 GdkRectangle cell_area;
1802 gboolean visible, mode;
1804 gtk_icon_view_set_cell_data (icon_view, item);
1806 g_object_get (info->cell,
1807 "visible", &visible,
1811 if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
1813 gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
1815 path = gtk_tree_path_new_from_indices (item->index, -1);
1816 path_string = gtk_tree_path_to_string (path);
1817 gtk_tree_path_free (path);
1819 gtk_cell_renderer_activate (info->cell,
1821 GTK_WIDGET (icon_view),
1827 g_free (path_string);
1832 gtk_icon_view_item_selected_changed (GtkIconView *icon_view,
1833 GtkIconViewItem *item)
1836 AtkObject *item_obj;
1838 obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
1841 item_obj = atk_object_ref_accessible_child (obj, item->index);
1842 if (item_obj != NULL)
1844 atk_object_notify_state_change (item_obj, ATK_STATE_SELECTED, item->selected);
1845 g_object_unref (item_obj);
1851 gtk_icon_view_put (GtkIconView *icon_view,
1853 GtkIconViewItem *item,
1856 GtkIconViewChild *child;
1858 child = g_new (GtkIconViewChild, 1);
1860 child->widget = widget;
1864 icon_view->priv->children = g_list_append (icon_view->priv->children, child);
1866 if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
1867 gtk_widget_set_parent_window (child->widget, icon_view->priv->bin_window);
1869 gtk_widget_set_parent (widget, GTK_WIDGET (icon_view));
1873 gtk_icon_view_remove_widget (GtkCellEditable *editable,
1874 GtkIconView *icon_view)
1877 GtkIconViewItem *item;
1879 if (icon_view->priv->edited_item == NULL)
1882 item = icon_view->priv->edited_item;
1883 icon_view->priv->edited_item = NULL;
1884 icon_view->priv->editable = NULL;
1885 for (l = icon_view->priv->cell_list; l; l = l->next)
1887 GtkIconViewCellInfo *info = l->data;
1889 info->editing = FALSE;
1892 if (gtk_widget_has_focus (GTK_WIDGET (editable)))
1893 gtk_widget_grab_focus (GTK_WIDGET (icon_view));
1895 g_signal_handlers_disconnect_by_func (editable,
1896 gtk_icon_view_remove_widget,
1899 gtk_container_remove (GTK_CONTAINER (icon_view),
1900 GTK_WIDGET (editable));
1902 gtk_icon_view_queue_draw_item (icon_view, item);
1907 gtk_icon_view_start_editing (GtkIconView *icon_view,
1908 GtkIconViewItem *item,
1909 GtkIconViewCellInfo *info,
1914 GdkRectangle cell_area;
1915 gboolean visible, mode;
1916 GtkCellEditable *editable;
1918 gtk_icon_view_set_cell_data (icon_view, item);
1920 g_object_get (info->cell,
1921 "visible", &visible,
1924 if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
1926 gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
1928 path = gtk_tree_path_new_from_indices (item->index, -1);
1929 path_string = gtk_tree_path_to_string (path);
1930 gtk_tree_path_free (path);
1932 editable = gtk_cell_renderer_start_editing (info->cell,
1934 GTK_WIDGET (icon_view),
1939 g_free (path_string);
1941 /* the rest corresponds to tree_view_real_start_editing... */
1942 icon_view->priv->edited_item = item;
1943 icon_view->priv->editable = editable;
1944 info->editing = TRUE;
1946 gtk_icon_view_put (icon_view, GTK_WIDGET (editable), item,
1948 gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (editable),
1950 gtk_widget_grab_focus (GTK_WIDGET (editable));
1951 g_signal_connect (editable, "remove-widget",
1952 G_CALLBACK (gtk_icon_view_remove_widget),
1959 gtk_icon_view_stop_editing (GtkIconView *icon_view,
1960 gboolean cancel_editing)
1962 GtkCellRenderer *cell = NULL;
1963 GtkIconViewItem *item;
1966 if (icon_view->priv->edited_item == NULL)
1970 * This is very evil. We need to do this, because
1971 * gtk_cell_editable_editing_done may trigger gtk_icon_view_row_changed
1972 * later on. If gtk_icon_view_row_changed notices
1973 * icon_view->priv->edited_item != NULL, it'll call
1974 * gtk_icon_view_stop_editing again. Bad things will happen then.
1976 * Please read that again if you intend to modify anything here.
1979 item = icon_view->priv->edited_item;
1980 icon_view->priv->edited_item = NULL;
1982 for (l = icon_view->priv->cell_list; l; l = l->next)
1984 GtkIconViewCellInfo *info = l->data;
1996 gtk_cell_renderer_stop_editing (cell, cancel_editing);
1997 if (!cancel_editing)
1998 gtk_cell_editable_editing_done (icon_view->priv->editable);
2000 icon_view->priv->edited_item = item;
2002 gtk_cell_editable_remove_widget (icon_view->priv->editable);
2006 * gtk_icon_view_set_cursor:
2007 * @icon_view: A #GtkIconView
2008 * @path: A #GtkTreePath
2009 * @cell: (allow-none): One of the cell renderers of @icon_view, or %NULL
2010 * @start_editing: %TRUE if the specified cell should start being edited.
2012 * Sets the current keyboard focus to be at @path, and selects it. This is
2013 * useful when you want to focus the user's attention on a particular item.
2014 * If @cell is not %NULL, then focus is given to the cell specified by
2015 * it. Additionally, if @start_editing is %TRUE, then editing should be
2016 * started in the specified cell.
2018 * This function is often followed by <literal>gtk_widget_grab_focus
2019 * (icon_view)</literal> in order to give keyboard focus to the widget.
2020 * Please note that editing can only happen when the widget is realized.
2025 gtk_icon_view_set_cursor (GtkIconView *icon_view,
2027 GtkCellRenderer *cell,
2028 gboolean start_editing)
2030 GtkIconViewItem *item = NULL;
2031 GtkIconViewCellInfo *info = NULL;
2035 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
2036 g_return_if_fail (path != NULL);
2037 g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
2039 gtk_icon_view_stop_editing (icon_view, TRUE);
2041 if (gtk_tree_path_get_depth (path) == 1)
2042 item = g_list_nth_data (icon_view->priv->items,
2043 gtk_tree_path_get_indices(path)[0]);
2049 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
2053 if (info->cell == cell)
2062 g_return_if_fail (cell == NULL || info != NULL);
2064 gtk_icon_view_set_cursor_item (icon_view, item, cell_pos);
2065 gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.0, 0.0);
2067 if (info && start_editing)
2068 gtk_icon_view_start_editing (icon_view, item, info, NULL);
2072 * gtk_icon_view_get_cursor:
2073 * @icon_view: A #GtkIconView
2074 * @path: (allow-none): Return location for the current cursor path, or %NULL
2075 * @cell: (allow-none): Return location the current focus cell, or %NULL
2077 * Fills in @path and @cell with the current cursor path and cell.
2078 * If the cursor isn't currently set, then *@path will be %NULL.
2079 * If no cell currently has focus, then *@cell will be %NULL.
2081 * The returned #GtkTreePath must be freed with gtk_tree_path_free().
2083 * Return value: %TRUE if the cursor is set.
2088 gtk_icon_view_get_cursor (GtkIconView *icon_view,
2090 GtkCellRenderer **cell)
2092 GtkIconViewItem *item;
2093 GtkIconViewCellInfo *info;
2095 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
2097 item = icon_view->priv->cursor_item;
2098 if (icon_view->priv->cursor_cell < 0)
2101 info = g_list_nth_data (icon_view->priv->cell_list,
2102 icon_view->priv->cursor_cell);
2107 *path = gtk_tree_path_new_from_indices (item->index, -1);
2120 return (item != NULL);
2124 gtk_icon_view_button_press (GtkWidget *widget,
2125 GdkEventButton *event)
2127 GtkIconView *icon_view;
2128 GtkIconViewItem *item;
2129 GtkIconViewCellInfo *info = NULL;
2130 gboolean dirty = FALSE;
2131 GtkCellRendererMode mode;
2132 gint cursor_cell = -1;
2134 icon_view = GTK_ICON_VIEW (widget);
2136 if (event->window != icon_view->priv->bin_window)
2139 if (!gtk_widget_has_focus (widget))
2140 gtk_widget_grab_focus (widget);
2142 if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
2144 item = gtk_icon_view_get_item_at_coords (icon_view,
2150 * We consider only the the cells' area as the item area if the
2151 * item is not selected, but if it *is* selected, the complete
2152 * selection rectangle is considered to be part of the item.
2154 if (item != NULL && (info != NULL || item->selected))
2158 g_object_get (info->cell, "mode", &mode, NULL);
2160 if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE ||
2161 mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2162 cursor_cell = g_list_index (icon_view->priv->cell_list, info);
2165 gtk_icon_view_scroll_to_item (icon_view, item);
2167 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
2169 gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
2171 else if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE &&
2172 (event->state & GDK_SHIFT_MASK))
2174 gtk_icon_view_unselect_all_internal (icon_view);
2176 gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
2177 if (!icon_view->priv->anchor_item)
2178 icon_view->priv->anchor_item = item;
2180 gtk_icon_view_select_all_between (icon_view,
2181 icon_view->priv->anchor_item,
2187 if ((icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE ||
2188 ((icon_view->priv->selection_mode == GTK_SELECTION_SINGLE) && item->selected)) &&
2189 (event->state & GDK_CONTROL_MASK))
2191 item->selected = !item->selected;
2192 gtk_icon_view_queue_draw_item (icon_view, item);
2197 gtk_icon_view_unselect_all_internal (icon_view);
2199 item->selected = TRUE;
2200 gtk_icon_view_queue_draw_item (icon_view, item);
2203 gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
2204 icon_view->priv->anchor_item = item;
2207 /* Save press to possibly begin a drag */
2208 if (icon_view->priv->pressed_button < 0)
2210 icon_view->priv->pressed_button = event->button;
2211 icon_view->priv->press_start_x = event->x;
2212 icon_view->priv->press_start_y = event->y;
2215 if (!icon_view->priv->last_single_clicked)
2216 icon_view->priv->last_single_clicked = item;
2218 /* cancel the current editing, if it exists */
2219 gtk_icon_view_stop_editing (icon_view, TRUE);
2223 if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2224 gtk_icon_view_item_activate_cell (icon_view, item, info,
2226 else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2227 gtk_icon_view_start_editing (icon_view, item, info,
2233 if (icon_view->priv->selection_mode != GTK_SELECTION_BROWSE &&
2234 !(event->state & GDK_CONTROL_MASK))
2236 dirty = gtk_icon_view_unselect_all_internal (icon_view);
2239 if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
2240 gtk_icon_view_start_rubberbanding (icon_view, event->device, event->x, event->y);
2243 /* don't draw keyboard focus around an clicked-on item */
2244 icon_view->priv->draw_focus = FALSE;
2247 if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
2249 item = gtk_icon_view_get_item_at_coords (icon_view,
2254 if (item && item == icon_view->priv->last_single_clicked)
2258 path = gtk_tree_path_new_from_indices (item->index, -1);
2259 gtk_icon_view_item_activated (icon_view, path);
2260 gtk_tree_path_free (path);
2263 icon_view->priv->last_single_clicked = NULL;
2264 icon_view->priv->pressed_button = -1;
2268 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2270 return event->button == 1;
2274 gtk_icon_view_button_release (GtkWidget *widget,
2275 GdkEventButton *event)
2277 GtkIconView *icon_view;
2279 icon_view = GTK_ICON_VIEW (widget);
2281 if (icon_view->priv->pressed_button == event->button)
2282 icon_view->priv->pressed_button = -1;
2284 gtk_icon_view_stop_rubberbanding (icon_view);
2286 remove_scroll_timeout (icon_view);
2292 gtk_icon_view_key_press (GtkWidget *widget,
2295 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
2297 if (icon_view->priv->doing_rubberband)
2299 if (event->keyval == GDK_KEY_Escape)
2300 gtk_icon_view_stop_rubberbanding (icon_view);
2305 return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->key_press_event (widget, event);
2309 gtk_icon_view_key_release (GtkWidget *widget,
2312 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
2314 if (icon_view->priv->doing_rubberband)
2317 return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->key_press_event (widget, event);
2321 gtk_icon_view_update_rubberband (gpointer data)
2323 GtkIconView *icon_view;
2325 GdkRectangle old_area;
2326 GdkRectangle new_area;
2327 GdkRectangle common;
2328 cairo_region_t *invalid_region;
2330 icon_view = GTK_ICON_VIEW (data);
2332 gdk_window_get_device_position (icon_view->priv->bin_window,
2333 icon_view->priv->rubberband_device,
2339 old_area.x = MIN (icon_view->priv->rubberband_x1,
2340 icon_view->priv->rubberband_x2);
2341 old_area.y = MIN (icon_view->priv->rubberband_y1,
2342 icon_view->priv->rubberband_y2);
2343 old_area.width = ABS (icon_view->priv->rubberband_x2 -
2344 icon_view->priv->rubberband_x1) + 1;
2345 old_area.height = ABS (icon_view->priv->rubberband_y2 -
2346 icon_view->priv->rubberband_y1) + 1;
2348 new_area.x = MIN (icon_view->priv->rubberband_x1, x);
2349 new_area.y = MIN (icon_view->priv->rubberband_y1, y);
2350 new_area.width = ABS (x - icon_view->priv->rubberband_x1) + 1;
2351 new_area.height = ABS (y - icon_view->priv->rubberband_y1) + 1;
2353 invalid_region = cairo_region_create_rectangle (&old_area);
2354 cairo_region_union_rectangle (invalid_region, &new_area);
2356 gdk_rectangle_intersect (&old_area, &new_area, &common);
2357 if (common.width > 2 && common.height > 2)
2359 cairo_region_t *common_region;
2361 /* make sure the border is invalidated */
2367 common_region = cairo_region_create_rectangle (&common);
2369 cairo_region_subtract (invalid_region, common_region);
2370 cairo_region_destroy (common_region);
2373 gdk_window_invalidate_region (icon_view->priv->bin_window, invalid_region, TRUE);
2375 cairo_region_destroy (invalid_region);
2377 icon_view->priv->rubberband_x2 = x;
2378 icon_view->priv->rubberband_y2 = y;
2380 gtk_icon_view_update_rubberband_selection (icon_view);
2384 gtk_icon_view_start_rubberbanding (GtkIconView *icon_view,
2391 if (icon_view->priv->rubberband_device)
2394 for (items = icon_view->priv->items; items; items = items->next)
2396 GtkIconViewItem *item = items->data;
2398 item->selected_before_rubberbanding = item->selected;
2401 icon_view->priv->rubberband_x1 = x;
2402 icon_view->priv->rubberband_y1 = y;
2403 icon_view->priv->rubberband_x2 = x;
2404 icon_view->priv->rubberband_y2 = y;
2406 icon_view->priv->doing_rubberband = TRUE;
2407 icon_view->priv->rubberband_device = device;
2409 gtk_device_grab_add (GTK_WIDGET (icon_view), device, TRUE);
2413 gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view)
2415 if (!icon_view->priv->doing_rubberband)
2418 gtk_device_grab_remove (GTK_WIDGET (icon_view),
2419 icon_view->priv->rubberband_device);
2421 icon_view->priv->doing_rubberband = FALSE;
2422 icon_view->priv->rubberband_device = NULL;
2424 gtk_widget_queue_draw (GTK_WIDGET (icon_view));
2428 gtk_icon_view_update_rubberband_selection (GtkIconView *icon_view)
2431 gint x, y, width, height;
2432 gboolean dirty = FALSE;
2434 x = MIN (icon_view->priv->rubberband_x1,
2435 icon_view->priv->rubberband_x2);
2436 y = MIN (icon_view->priv->rubberband_y1,
2437 icon_view->priv->rubberband_y2);
2438 width = ABS (icon_view->priv->rubberband_x1 -
2439 icon_view->priv->rubberband_x2);
2440 height = ABS (icon_view->priv->rubberband_y1 -
2441 icon_view->priv->rubberband_y2);
2443 for (items = icon_view->priv->items; items; items = items->next)
2445 GtkIconViewItem *item = items->data;
2449 is_in = gtk_icon_view_item_hit_test (icon_view, item,
2450 x, y, width, height);
2452 selected = is_in ^ item->selected_before_rubberbanding;
2454 if (item->selected != selected)
2456 item->selected = selected;
2458 gtk_icon_view_queue_draw_item (icon_view, item);
2463 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2467 gtk_icon_view_item_hit_test (GtkIconView *icon_view,
2468 GtkIconViewItem *item,
2477 if (MIN (x + width, item->x + item->width) - MAX (x, item->x) <= 0 ||
2478 MIN (y + height, item->y + item->height) - MAX (y, item->y) <= 0)
2481 for (l = icon_view->priv->cell_list; l; l = l->next)
2483 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
2485 if (!gtk_cell_renderer_get_visible (info->cell))
2488 gtk_icon_view_get_cell_box (icon_view, item, info, &box);
2490 if (MIN (x + width, box.x + box.width) - MAX (x, box.x) > 0 &&
2491 MIN (y + height, box.y + box.height) - MAX (y, box.y) > 0)
2499 gtk_icon_view_unselect_all_internal (GtkIconView *icon_view)
2501 gboolean dirty = FALSE;
2504 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
2507 for (items = icon_view->priv->items; items; items = items->next)
2509 GtkIconViewItem *item = items->data;
2513 item->selected = FALSE;
2515 gtk_icon_view_queue_draw_item (icon_view, item);
2516 gtk_icon_view_item_selected_changed (icon_view, item);
2524 /* GtkIconView signals */
2526 gtk_icon_view_real_select_all (GtkIconView *icon_view)
2528 gtk_icon_view_select_all (icon_view);
2532 gtk_icon_view_real_unselect_all (GtkIconView *icon_view)
2534 gtk_icon_view_unselect_all (icon_view);
2538 gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view)
2540 gtk_icon_view_unselect_all (icon_view);
2542 if (icon_view->priv->cursor_item != NULL)
2543 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
2547 gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view)
2550 GtkCellRendererMode mode;
2551 GtkIconViewCellInfo *info = NULL;
2553 if (!icon_view->priv->cursor_item)
2556 info = g_list_nth_data (icon_view->priv->cell_list,
2557 icon_view->priv->cursor_cell);
2561 g_object_get (info->cell, "mode", &mode, NULL);
2563 if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
2565 gtk_icon_view_item_activate_cell (icon_view,
2566 icon_view->priv->cursor_item,
2570 else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
2572 gtk_icon_view_start_editing (icon_view,
2573 icon_view->priv->cursor_item,
2579 path = gtk_tree_path_new_from_indices (icon_view->priv->cursor_item->index, -1);
2580 gtk_icon_view_item_activated (icon_view, path);
2581 gtk_tree_path_free (path);
2587 gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view)
2589 if (!icon_view->priv->cursor_item)
2592 switch (icon_view->priv->selection_mode)
2594 case GTK_SELECTION_NONE:
2596 case GTK_SELECTION_BROWSE:
2597 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
2599 case GTK_SELECTION_SINGLE:
2600 if (icon_view->priv->cursor_item->selected)
2601 gtk_icon_view_unselect_item (icon_view, icon_view->priv->cursor_item);
2603 gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
2605 case GTK_SELECTION_MULTIPLE:
2606 icon_view->priv->cursor_item->selected = !icon_view->priv->cursor_item->selected;
2607 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
2609 gtk_icon_view_item_selected_changed (icon_view, icon_view->priv->cursor_item);
2610 gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
2615 /* Internal functions */
2617 gtk_icon_view_process_updates (GtkIconView *icon_view)
2619 /* Prior to drawing, we check if a layout has been scheduled. If so,
2620 * do it now that all cell view items have valid sizes before we proceeed
2621 * (and resize the bin_window if required).
2623 if (icon_view->priv->layout_idle_id != 0)
2624 gtk_icon_view_layout (icon_view);
2626 gdk_window_process_updates (icon_view->priv->bin_window, TRUE);
2630 gtk_icon_view_set_hadjustment_values (GtkIconView *icon_view)
2632 GtkAllocation allocation;
2633 GtkAdjustment *adj = icon_view->priv->hadjustment;
2634 gdouble old_page_size;
2640 gtk_widget_get_allocation (GTK_WIDGET (icon_view), &allocation);
2642 old_value = gtk_adjustment_get_value (adj);
2643 old_upper = gtk_adjustment_get_upper (adj);
2644 old_page_size = gtk_adjustment_get_page_size (adj);
2645 new_upper = MAX (allocation.width, icon_view->priv->width);
2650 "page-size", (gdouble)allocation.width,
2651 "step-increment", allocation.width * 0.1,
2652 "page-increment", allocation.width * 0.9,
2655 if (gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL)
2657 /* Make sure no scrolling occurs for RTL locales also (if possible) */
2658 /* Quick explanation:
2659 * In LTR locales, leftmost portion of visible rectangle should stay
2660 * fixed, which means left edge of scrollbar thumb should remain fixed
2661 * and thus adjustment's value should stay the same.
2663 * In RTL locales, we want to keep rightmost portion of visible
2664 * rectangle fixed. This means right edge of thumb should remain fixed.
2665 * In this case, upper - value - page_size should remain constant.
2667 new_value = (new_upper - allocation.width) -
2668 (old_upper - old_value - old_page_size);
2669 new_value = CLAMP (new_value, 0, new_upper - allocation.width);
2672 new_value = CLAMP (old_value, 0, new_upper - allocation.width);
2674 if (new_value != old_value)
2675 gtk_adjustment_set_value (adj, new_value);
2679 gtk_icon_view_set_vadjustment_values (GtkIconView *icon_view)
2681 GtkAllocation allocation;
2682 GtkAdjustment *adj = icon_view->priv->vadjustment;
2687 gtk_widget_get_allocation (GTK_WIDGET (icon_view), &allocation);
2689 old_value = gtk_adjustment_get_value (adj);
2690 new_upper = MAX (allocation.height, icon_view->priv->height);
2695 "page-size", (gdouble)allocation.height,
2696 "step-increment", allocation.height * 0.1,
2697 "page-increment", allocation.height * 0.9,
2700 new_value = CLAMP (old_value, 0, new_upper - allocation.height);
2701 if (new_value != old_value)
2702 gtk_adjustment_set_value (adj, new_value);
2706 gtk_icon_view_set_hadjustment (GtkIconView *icon_view,
2707 GtkAdjustment *adjustment)
2709 GtkIconViewPrivate *priv = icon_view->priv;
2711 if (adjustment && priv->hadjustment == adjustment)
2714 if (priv->hadjustment != NULL)
2716 g_signal_handlers_disconnect_matched (priv->hadjustment,
2717 G_SIGNAL_MATCH_DATA,
2718 0, 0, NULL, NULL, icon_view);
2719 g_object_unref (priv->hadjustment);
2723 adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
2726 g_signal_connect (adjustment, "value-changed",
2727 G_CALLBACK (gtk_icon_view_adjustment_changed), icon_view);
2728 priv->hadjustment = g_object_ref_sink (adjustment);
2729 gtk_icon_view_set_hadjustment_values (icon_view);
2731 gtk_icon_view_accessible_set_adjustment (icon_view,
2732 GTK_ORIENTATION_HORIZONTAL,
2735 g_object_notify (G_OBJECT (icon_view), "hadjustment");
2739 gtk_icon_view_set_vadjustment (GtkIconView *icon_view,
2740 GtkAdjustment *adjustment)
2742 GtkIconViewPrivate *priv = icon_view->priv;
2744 if (adjustment && priv->vadjustment == adjustment)
2747 if (priv->vadjustment != NULL)
2749 g_signal_handlers_disconnect_matched (priv->vadjustment,
2750 G_SIGNAL_MATCH_DATA,
2751 0, 0, NULL, NULL, icon_view);
2752 g_object_unref (priv->vadjustment);
2756 adjustment = gtk_adjustment_new (0.0, 0.0, 0.0,
2759 g_signal_connect (adjustment, "value-changed",
2760 G_CALLBACK (gtk_icon_view_adjustment_changed), icon_view);
2761 priv->vadjustment = g_object_ref_sink (adjustment);
2762 gtk_icon_view_set_vadjustment_values (icon_view);
2764 gtk_icon_view_accessible_set_adjustment (icon_view,
2765 GTK_ORIENTATION_VERTICAL,
2768 g_object_notify (G_OBJECT (icon_view), "vadjustment");
2772 gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment,
2773 GtkIconView *icon_view)
2775 GtkIconViewPrivate *priv = icon_view->priv;
2777 if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
2779 gdk_window_move (priv->bin_window,
2780 - priv->hadjustment->value,
2781 - priv->vadjustment->value);
2783 if (icon_view->priv->doing_rubberband)
2784 gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view));
2786 gtk_icon_view_process_updates (icon_view);
2791 gtk_icon_view_layout_single_row (GtkIconView *icon_view,
2796 gint *maximum_width)
2798 GtkAllocation allocation;
2799 GtkWidget *widget = GTK_WIDGET (icon_view);
2801 gint x, current_width;
2802 GList *items, *last_item;
2809 rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
2810 max_height = g_new0 (gint, icon_view->priv->n_cells);
2817 gtk_widget_style_get (widget,
2818 "focus-line-width", &focus_width,
2821 x += icon_view->priv->margin + focus_width;
2822 current_width += 2 * (icon_view->priv->margin + focus_width);
2827 GtkIconViewItem *item = items->data;
2829 gtk_icon_view_calculate_item_size (icon_view, item);
2830 colspan = 1 + (item->width - 1) / (item_width + icon_view->priv->column_spacing);
2832 item->width = colspan * item_width + (colspan - 1) * icon_view->priv->column_spacing;
2834 current_width += item->width;
2836 if (items != first_item)
2838 gtk_widget_get_allocation (widget, &allocation);
2840 if ((icon_view->priv->columns <= 0 && current_width > allocation.width) ||
2841 (icon_view->priv->columns > 0 && col >= icon_view->priv->columns))
2845 current_width += icon_view->priv->column_spacing + 2 * focus_width;
2847 item->y = *y + focus_width;
2850 x = current_width - (icon_view->priv->margin + focus_width);
2852 for (i = 0; i < icon_view->priv->n_cells; i++)
2853 max_height[i] = MAX (max_height[i], item->box[i].height);
2855 if (current_width > *maximum_width)
2856 *maximum_width = current_width;
2862 items = items->next;
2867 /* Now go through the row again and align the icons */
2868 for (items = first_item; items != last_item; items = items->next)
2870 GtkIconViewItem *item = items->data;
2874 item->x = *maximum_width - item->width - item->x;
2875 item->col = col - 1 - item->col;
2878 gtk_icon_view_calculate_item_size2 (icon_view, item, max_height);
2880 /* We may want to readjust the new y coordinate. */
2881 if (item->y + item->height + focus_width + icon_view->priv->row_spacing > *y)
2882 *y = item->y + item->height + focus_width + icon_view->priv->row_spacing;
2885 g_free (max_height);
2891 gtk_icon_view_set_adjustment_upper (GtkAdjustment *adj,
2894 if (upper != adj->upper)
2896 gdouble min = MAX (0.0, upper - adj->page_size);
2897 gboolean value_changed = FALSE;
2901 if (adj->value > min)
2904 value_changed = TRUE;
2907 gtk_adjustment_changed (adj);
2910 gtk_adjustment_value_changed (adj);
2915 gtk_icon_view_layout (GtkIconView *icon_view)
2917 GtkAllocation allocation;
2920 gint y = 0, maximum_width = 0;
2923 gboolean size_changed = FALSE;
2925 if (icon_view->priv->layout_idle_id != 0)
2927 g_source_remove (icon_view->priv->layout_idle_id);
2928 icon_view->priv->layout_idle_id = 0;
2931 if (icon_view->priv->model == NULL)
2934 widget = GTK_WIDGET (icon_view);
2936 item_width = icon_view->priv->item_width;
2940 for (icons = icon_view->priv->items; icons; icons = icons->next)
2942 GtkIconViewItem *item = icons->data;
2943 gtk_icon_view_calculate_item_size (icon_view, item);
2944 item_width = MAX (item_width, item->width);
2949 icons = icon_view->priv->items;
2950 y += icon_view->priv->margin;
2955 gtk_icon_view_set_cell_data (icon_view, icons->data);
2956 adjust_wrap_width (icon_view, icons->data);
2961 icons = gtk_icon_view_layout_single_row (icon_view, icons,
2963 &y, &maximum_width);
2966 while (icons != NULL);
2968 if (maximum_width != icon_view->priv->width)
2970 icon_view->priv->width = maximum_width;
2971 size_changed = TRUE;
2974 y += icon_view->priv->margin;
2976 if (y != icon_view->priv->height)
2978 icon_view->priv->height = y;
2979 size_changed = TRUE;
2982 gtk_icon_view_set_adjustment_upper (icon_view->priv->hadjustment,
2983 icon_view->priv->width);
2984 gtk_icon_view_set_adjustment_upper (icon_view->priv->vadjustment,
2985 icon_view->priv->height);
2988 gtk_widget_queue_resize_no_redraw (widget);
2990 gtk_widget_get_allocation (widget, &allocation);
2991 if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
2992 gdk_window_resize (icon_view->priv->bin_window,
2993 MAX (icon_view->priv->width, allocation.width),
2994 MAX (icon_view->priv->height, allocation.height));
2996 if (icon_view->priv->scroll_to_path)
3000 path = gtk_tree_row_reference_get_path (icon_view->priv->scroll_to_path);
3001 gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
3002 icon_view->priv->scroll_to_path = NULL;
3004 gtk_icon_view_scroll_to_path (icon_view, path,
3005 icon_view->priv->scroll_to_use_align,
3006 icon_view->priv->scroll_to_row_align,
3007 icon_view->priv->scroll_to_col_align);
3008 gtk_tree_path_free (path);
3011 gtk_widget_queue_draw (widget);
3015 gtk_icon_view_get_cell_area (GtkIconView *icon_view,
3016 GtkIconViewItem *item,
3017 GtkIconViewCellInfo *info,
3018 GdkRectangle *cell_area)
3020 g_return_if_fail (info->position < item->n_cells);
3022 if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3024 cell_area->x = item->box[info->position].x - item->before[info->position];
3025 cell_area->y = item->y + icon_view->priv->item_padding;
3026 cell_area->width = item->box[info->position].width +
3027 item->before[info->position] + item->after[info->position];
3028 cell_area->height = item->height - icon_view->priv->item_padding * 2;
3032 cell_area->x = item->x + icon_view->priv->item_padding;
3033 cell_area->y = item->box[info->position].y - item->before[info->position];
3034 cell_area->width = item->width - icon_view->priv->item_padding * 2;
3035 cell_area->height = item->box[info->position].height +
3036 item->before[info->position] + item->after[info->position];
3041 gtk_icon_view_get_cell_box (GtkIconView *icon_view,
3042 GtkIconViewItem *item,
3043 GtkIconViewCellInfo *info,
3046 g_return_if_fail (info->position < item->n_cells);
3048 *box = item->box[info->position];
3051 /* try to guess a reasonable wrap width for an implicit text cell renderer
3054 adjust_wrap_width (GtkIconView *icon_view,
3055 GtkIconViewItem *item)
3057 GtkIconViewCellInfo *text_info;
3058 GtkIconViewCellInfo *pixbuf_info;
3061 if (icon_view->priv->text_cell != -1 &&
3062 icon_view->priv->pixbuf_cell != -1)
3064 GtkRequisition min_size;
3067 text_info = g_list_nth_data (icon_view->priv->cell_list,
3068 icon_view->priv->text_cell);
3069 pixbuf_info = g_list_nth_data (icon_view->priv->cell_list,
3070 icon_view->priv->pixbuf_cell);
3072 gtk_cell_renderer_get_preferred_size (pixbuf_info->cell,
3073 GTK_WIDGET (icon_view),
3076 if (icon_view->priv->item_width > 0)
3077 item_width = icon_view->priv->item_width;
3079 item_width = item->width;
3081 if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
3082 wrap_width = item_width;
3084 if (item->width == -1 && item_width <= 0)
3085 wrap_width = MAX (2 * min_size.width, 50);
3087 wrap_width = item_width - min_size.width - icon_view->priv->spacing;
3090 wrap_width -= icon_view->priv->item_padding * 2;
3092 g_object_set (text_info->cell, "wrap-width", wrap_width, NULL);
3093 g_object_set (text_info->cell, "width", wrap_width, NULL);
3098 gtk_icon_view_calculate_item_size (GtkIconView *icon_view,
3099 GtkIconViewItem *item)
3101 GtkRequisition min_size;
3105 if (item->width != -1 && item->height != -1)
3108 if (item->n_cells != icon_view->priv->n_cells)
3110 g_free (item->before);
3111 g_free (item->after);
3114 item->before = g_new0 (gint, icon_view->priv->n_cells);
3115 item->after = g_new0 (gint, icon_view->priv->n_cells);
3116 item->box = g_new0 (GdkRectangle, icon_view->priv->n_cells);
3118 item->n_cells = icon_view->priv->n_cells;
3121 gtk_icon_view_set_cell_data (icon_view, item);
3123 spacing = icon_view->priv->spacing;
3127 for (l = icon_view->priv->cell_list; l; l = l->next)
3129 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
3131 if (!gtk_cell_renderer_get_visible (info->cell))
3134 gtk_cell_renderer_get_preferred_size (info->cell,
3135 GTK_WIDGET (icon_view),
3137 item->box[info->position].width = min_size.width;
3138 item->box[info->position].height = min_size.height;
3140 if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3142 item->width += item->box[info->position].width
3143 + (info->position > 0 ? spacing : 0);
3144 item->height = MAX (item->height, item->box[info->position].height);
3148 item->width = MAX (item->width, item->box[info->position].width);
3149 item->height += item->box[info->position].height + (info->position > 0 ? spacing : 0);
3153 item->width += icon_view->priv->item_padding * 2;
3154 item->height += icon_view->priv->item_padding * 2;
3158 gtk_icon_view_calculate_item_size2 (GtkIconView *icon_view,
3159 GtkIconViewItem *item,
3162 GtkRequisition min_size;
3163 GdkRectangle cell_area;
3169 rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL;
3171 gtk_icon_view_set_cell_data (icon_view, item);
3173 spacing = icon_view->priv->spacing;
3176 for (i = 0; i < icon_view->priv->n_cells; i++)
3178 if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3179 item->height = MAX (item->height, max_height[i]);
3181 item->height += max_height[i] + (i > 0 ? spacing : 0);
3184 cell_area.x = item->x + icon_view->priv->item_padding;
3185 cell_area.y = item->y + icon_view->priv->item_padding;
3187 for (k = 0; k < 2; k++)
3188 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
3190 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
3192 if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END))
3195 if (!gtk_cell_renderer_get_visible (info->cell))
3198 if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3200 /* We should not subtract icon_view->priv->item_padding from item->height,
3201 * because item->height is recalculated above using
3202 * max_height which does not contain item padding.
3204 cell_area.width = item->box[info->position].width;
3205 cell_area.height = item->height;
3209 /* item->width is not recalculated and thus needs to be
3210 * corrected for the padding.
3212 cell_area.width = item->width - 2 * icon_view->priv->item_padding;
3213 cell_area.height = max_height[i];
3216 gtk_cell_renderer_get_preferred_size (info->cell,
3217 GTK_WIDGET (icon_view),
3219 item->box[info->position].width = min_size.width;
3220 item->box[info->position].height = min_size.height;
3222 _gtk_cell_renderer_calc_offset (info->cell, &cell_area,
3223 gtk_widget_get_direction (GTK_WIDGET (icon_view)),
3224 item->box[info->position].width, item->box[info->position].height,
3225 &item->box[info->position].x, &item->box[info->position].y);
3226 item->box[info->position].x += cell_area.x;
3227 item->box[info->position].y += cell_area.y;
3229 if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3231 item->before[info->position] = item->box[info->position].x - cell_area.x;
3232 item->after[info->position] = cell_area.width - item->box[info->position].width - item->before[info->position];
3233 cell_area.x += cell_area.width + spacing;
3237 if (item->box[info->position].width > item->width - icon_view->priv->item_padding * 2)
3239 item->width = item->box[info->position].width + icon_view->priv->item_padding * 2;
3240 cell_area.width = item->width;
3242 item->before[info->position] = item->box[info->position].y - cell_area.y;
3243 item->after[info->position] = cell_area.height - item->box[info->position].height - item->before[info->position];
3244 cell_area.y += cell_area.height + spacing;
3248 if (rtl && icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
3250 for (i = 0; i < icon_view->priv->n_cells; i++)
3252 item->box[i].x = item->x + item->width -
3253 (item->box[i].x + item->box[i].width - item->x);
3257 item->height += icon_view->priv->item_padding * 2;
3261 gtk_icon_view_invalidate_sizes (GtkIconView *icon_view)
3263 g_list_foreach (icon_view->priv->items,
3264 (GFunc)gtk_icon_view_item_invalidate_size, NULL);
3268 gtk_icon_view_item_invalidate_size (GtkIconViewItem *item)
3275 gtk_icon_view_paint_item (GtkIconView *icon_view,
3277 GtkIconViewItem *item,
3280 gboolean draw_focus)
3284 GdkRectangle cell_area, box;
3288 GtkCellRendererState flags;
3290 GtkWidget *widget = GTK_WIDGET (icon_view);
3292 if (icon_view->priv->model == NULL)
3295 gtk_icon_view_set_cell_data (icon_view, item);
3297 style = gtk_widget_get_style (widget);
3298 gtk_widget_style_get (widget,
3299 "focus-line-width", &focus_width,
3302 padding = focus_width;
3306 flags = GTK_CELL_RENDERER_SELECTED;
3307 if (gtk_widget_has_focus (widget))
3308 state = GTK_STATE_SELECTED;
3310 state = GTK_STATE_ACTIVE;
3315 state = GTK_STATE_NORMAL;
3320 gtk_paint_flat_box (style,
3324 GTK_WIDGET (icon_view),
3327 item->width, item->height);
3330 for (l = icon_view->priv->cell_list; l; l = l->next)
3332 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
3334 if (!gtk_cell_renderer_get_visible (info->cell))
3337 gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
3339 cell_area.x = x - item->x + cell_area.x;
3340 cell_area.y = y - item->y + cell_area.y;
3342 gtk_cell_renderer_render (info->cell,
3345 &cell_area, &cell_area, flags);
3349 gtk_widget_has_focus (widget) &&
3350 item == icon_view->priv->cursor_item)
3352 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
3354 GtkCellRendererMode mode;
3355 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
3357 if (!gtk_cell_renderer_get_visible (info->cell))
3360 /* If found a editable/activatable cell, draw focus on it. */
3361 g_object_get (info->cell, "mode", &mode, NULL);
3362 if (icon_view->priv->cursor_cell < 0 &&
3363 mode != GTK_CELL_RENDERER_MODE_INERT)
3364 icon_view->priv->cursor_cell = i;
3366 gtk_icon_view_get_cell_box (icon_view, item, info, &box);
3368 if (i == icon_view->priv->cursor_cell)
3370 gtk_paint_focus (style,
3375 x - item->x + box.x - padding,
3376 y - item->y + box.y - padding,
3377 box.width + 2 * padding,
3378 box.height + 2 * padding);
3383 /* If there are no editable/activatable cells, draw focus
3384 * around the whole item.
3386 if (icon_view->priv->cursor_cell < 0)
3387 gtk_paint_focus (style,
3394 item->width + 2 * padding,
3395 item->height + 2 * padding);
3400 gtk_icon_view_paint_rubberband (GtkIconView *icon_view,
3404 GdkColor *fill_color_gdk;
3405 guchar fill_color_alpha;
3409 rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2);
3410 rect.y = MIN (icon_view->priv->rubberband_y1, icon_view->priv->rubberband_y2);
3411 rect.width = ABS (icon_view->priv->rubberband_x1 - icon_view->priv->rubberband_x2) + 1;
3412 rect.height = ABS (icon_view->priv->rubberband_y1 - icon_view->priv->rubberband_y2) + 1;
3414 gtk_widget_style_get (GTK_WIDGET (icon_view),
3415 "selection-box-color", &fill_color_gdk,
3416 "selection-box-alpha", &fill_color_alpha,
3419 if (!fill_color_gdk)
3420 fill_color_gdk = gdk_color_copy (>k_widget_get_style (GTK_WIDGET (icon_view))->base[GTK_STATE_SELECTED]);
3422 gdk_cairo_set_source_color (cr, fill_color_gdk);
3424 gdk_cairo_rectangle (cr, &rect);
3427 cairo_paint_with_alpha (cr, fill_color_alpha / 255.);
3429 cairo_rectangle (cr,
3430 rect.x + 0.5, rect.y + 0.5,
3431 rect.width - 1, rect.height - 1);
3434 gdk_color_free (fill_color_gdk);
3440 gtk_icon_view_queue_draw_path (GtkIconView *icon_view,
3446 index = gtk_tree_path_get_indices (path)[0];
3448 for (l = icon_view->priv->items; l; l = l->next)
3450 GtkIconViewItem *item = l->data;
3452 if (item->index == index)
3454 gtk_icon_view_queue_draw_item (icon_view, item);
3461 gtk_icon_view_queue_draw_item (GtkIconView *icon_view,
3462 GtkIconViewItem *item)
3467 gtk_widget_style_get (GTK_WIDGET (icon_view),
3468 "focus-line-width", &focus_width,
3471 rect.x = item->x - focus_width;
3472 rect.y = item->y - focus_width;
3473 rect.width = item->width + 2 * focus_width;
3474 rect.height = item->height + 2 * focus_width;
3476 if (icon_view->priv->bin_window)
3477 gdk_window_invalidate_rect (icon_view->priv->bin_window, &rect, TRUE);
3481 layout_callback (gpointer user_data)
3483 GtkIconView *icon_view;
3485 icon_view = GTK_ICON_VIEW (user_data);
3487 icon_view->priv->layout_idle_id = 0;
3489 gtk_icon_view_layout (icon_view);
3495 gtk_icon_view_queue_layout (GtkIconView *icon_view)
3497 if (icon_view->priv->layout_idle_id != 0)
3500 icon_view->priv->layout_idle_id =
3501 gdk_threads_add_idle_full (GTK_ICON_VIEW_PRIORITY_LAYOUT,
3502 layout_callback, icon_view, NULL);
3506 gtk_icon_view_set_cursor_item (GtkIconView *icon_view,
3507 GtkIconViewItem *item,
3511 AtkObject *item_obj;
3512 AtkObject *cursor_item_obj;
3514 if (icon_view->priv->cursor_item == item &&
3515 (cursor_cell < 0 || cursor_cell == icon_view->priv->cursor_cell))
3518 obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
3519 if (icon_view->priv->cursor_item != NULL)
3521 gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
3524 cursor_item_obj = atk_object_ref_accessible_child (obj, icon_view->priv->cursor_item->index);
3525 if (cursor_item_obj != NULL)
3526 atk_object_notify_state_change (cursor_item_obj, ATK_STATE_FOCUSED, FALSE);
3529 icon_view->priv->cursor_item = item;
3530 if (cursor_cell >= 0)
3531 icon_view->priv->cursor_cell = cursor_cell;
3533 gtk_icon_view_queue_draw_item (icon_view, item);
3535 /* Notify that accessible focus object has changed */
3536 item_obj = atk_object_ref_accessible_child (obj, item->index);
3538 if (item_obj != NULL)
3540 atk_focus_tracker_notify (item_obj);
3541 atk_object_notify_state_change (item_obj, ATK_STATE_FOCUSED, TRUE);
3542 g_object_unref (item_obj);
3547 static GtkIconViewItem *
3548 gtk_icon_view_item_new (void)
3550 GtkIconViewItem *item;
3552 item = g_new0 (GtkIconViewItem, 1);
3561 gtk_icon_view_item_free (GtkIconViewItem *item)
3563 g_return_if_fail (item != NULL);
3565 g_free (item->before);
3566 g_free (item->after);
3573 static GtkIconViewItem *
3574 gtk_icon_view_get_item_at_coords (GtkIconView *icon_view,
3577 gboolean only_in_cell,
3578 GtkIconViewCellInfo **cell_at_pos)
3584 *cell_at_pos = NULL;
3586 for (items = icon_view->priv->items; items; items = items->next)
3588 GtkIconViewItem *item = items->data;
3590 if (x >= item->x - icon_view->priv->column_spacing/2 && x <= item->x + item->width + icon_view->priv->column_spacing/2 &&
3591 y >= item->y - icon_view->priv->row_spacing/2 && y <= item->y + item->height + icon_view->priv->row_spacing/2)
3593 if (only_in_cell || cell_at_pos)
3595 gtk_icon_view_set_cell_data (icon_view, item);
3597 for (l = icon_view->priv->cell_list; l; l = l->next)
3599 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
3601 if (!gtk_cell_renderer_get_visible (info->cell))
3604 gtk_icon_view_get_cell_box (icon_view, item, info, &box);
3606 if ((x >= box.x && x <= box.x + box.width &&
3607 y >= box.y && y <= box.y + box.height) ||
3609 x <= box.x + box.width &&
3611 y <= box.y + box.height))
3614 *cell_at_pos = info;
3632 gtk_icon_view_select_item (GtkIconView *icon_view,
3633 GtkIconViewItem *item)
3635 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3636 g_return_if_fail (item != NULL);
3641 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
3643 else if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
3644 gtk_icon_view_unselect_all_internal (icon_view);
3646 item->selected = TRUE;
3648 gtk_icon_view_item_selected_changed (icon_view, item);
3649 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3651 gtk_icon_view_queue_draw_item (icon_view, item);
3656 gtk_icon_view_unselect_item (GtkIconView *icon_view,
3657 GtkIconViewItem *item)
3659 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
3660 g_return_if_fail (item != NULL);
3662 if (!item->selected)
3665 if (icon_view->priv->selection_mode == GTK_SELECTION_NONE ||
3666 icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
3669 item->selected = FALSE;
3671 gtk_icon_view_item_selected_changed (icon_view, item);
3672 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3674 gtk_icon_view_queue_draw_item (icon_view, item);
3678 verify_items (GtkIconView *icon_view)
3683 for (items = icon_view->priv->items; items; items = items->next)
3685 GtkIconViewItem *item = items->data;
3687 if (item->index != i)
3688 g_error ("List item does not match its index: "
3689 "item index %d and list index %d\n", item->index, i);
3696 gtk_icon_view_row_changed (GtkTreeModel *model,
3701 GtkIconView *icon_view = GTK_ICON_VIEW (data);
3702 GtkIconViewItem *item;
3705 /* ignore changes in branches */
3706 if (gtk_tree_path_get_depth (path) > 1)
3709 gtk_icon_view_stop_editing (icon_view, TRUE);
3711 index = gtk_tree_path_get_indices(path)[0];
3712 item = g_list_nth_data (icon_view->priv->items, index);
3714 gtk_icon_view_item_invalidate_size (item);
3715 gtk_icon_view_queue_layout (icon_view);
3717 verify_items (icon_view);
3721 gtk_icon_view_row_inserted (GtkTreeModel *model,
3726 GtkIconView *icon_view = GTK_ICON_VIEW (data);
3728 GtkIconViewItem *item;
3729 gboolean iters_persist;
3732 /* ignore changes in branches */
3733 if (gtk_tree_path_get_depth (path) > 1)
3736 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
3738 index = gtk_tree_path_get_indices(path)[0];
3740 item = gtk_icon_view_item_new ();
3745 item->index = index;
3747 /* FIXME: We can be more efficient here,
3748 we can store a tail pointer and use that when
3749 appending (which is a rather common operation)
3751 icon_view->priv->items = g_list_insert (icon_view->priv->items,
3754 list = g_list_nth (icon_view->priv->items, index + 1);
3755 for (; list; list = list->next)
3762 verify_items (icon_view);
3764 gtk_icon_view_queue_layout (icon_view);
3768 gtk_icon_view_row_deleted (GtkTreeModel *model,
3772 GtkIconView *icon_view = GTK_ICON_VIEW (data);
3774 GtkIconViewItem *item;
3776 gboolean emit = FALSE;
3778 /* ignore changes in branches */
3779 if (gtk_tree_path_get_depth (path) > 1)
3782 index = gtk_tree_path_get_indices(path)[0];
3784 list = g_list_nth (icon_view->priv->items, index);
3787 gtk_icon_view_stop_editing (icon_view, TRUE);
3789 if (item == icon_view->priv->anchor_item)
3790 icon_view->priv->anchor_item = NULL;
3792 if (item == icon_view->priv->cursor_item)
3793 icon_view->priv->cursor_item = NULL;
3798 gtk_icon_view_item_free (item);
3800 for (next = list->next; next; next = next->next)
3807 icon_view->priv->items = g_list_delete_link (icon_view->priv->items, list);
3809 verify_items (icon_view);
3811 gtk_icon_view_queue_layout (icon_view);
3814 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
3818 gtk_icon_view_rows_reordered (GtkTreeModel *model,
3819 GtkTreePath *parent,
3824 GtkIconView *icon_view = GTK_ICON_VIEW (data);
3827 GList *items = NULL, *list;
3828 GtkIconViewItem **item_array;
3831 /* ignore changes in branches */
3835 gtk_icon_view_stop_editing (icon_view, TRUE);
3837 length = gtk_tree_model_iter_n_children (model, NULL);
3839 order = g_new (gint, length);
3840 for (i = 0; i < length; i++)
3841 order [new_order[i]] = i;
3843 item_array = g_new (GtkIconViewItem *, length);
3844 for (i = 0, list = icon_view->priv->items; list != NULL; list = list->next, i++)
3845 item_array[order[i]] = list->data;
3848 for (i = length - 1; i >= 0; i--)
3850 item_array[i]->index = i;
3851 items = g_list_prepend (items, item_array[i]);
3854 g_free (item_array);
3855 g_list_free (icon_view->priv->items);
3856 icon_view->priv->items = items;
3858 gtk_icon_view_queue_layout (icon_view);
3860 verify_items (icon_view);
3864 gtk_icon_view_build_items (GtkIconView *icon_view)
3868 gboolean iters_persist;
3869 GList *items = NULL;
3871 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
3873 if (!gtk_tree_model_get_iter_first (icon_view->priv->model,
3881 GtkIconViewItem *item = gtk_icon_view_item_new ();
3890 items = g_list_prepend (items, item);
3892 } while (gtk_tree_model_iter_next (icon_view->priv->model, &iter));
3894 icon_view->priv->items = g_list_reverse (items);
3898 gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
3901 GtkMovementStep step,
3905 gtk_binding_entry_add_signal (binding_set, keyval, modmask,
3906 I_("move-cursor"), 2,
3910 gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
3915 if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
3918 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
3923 gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
3930 gtk_icon_view_real_move_cursor (GtkIconView *icon_view,
3931 GtkMovementStep step,
3934 GdkModifierType state;
3936 g_return_val_if_fail (GTK_ICON_VIEW (icon_view), FALSE);
3937 g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
3938 step == GTK_MOVEMENT_VISUAL_POSITIONS ||
3939 step == GTK_MOVEMENT_DISPLAY_LINES ||
3940 step == GTK_MOVEMENT_PAGES ||
3941 step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
3943 if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
3946 gtk_icon_view_stop_editing (icon_view, FALSE);
3947 gtk_widget_grab_focus (GTK_WIDGET (icon_view));
3949 if (gtk_get_current_event_state (&state))
3951 if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
3952 icon_view->priv->ctrl_pressed = TRUE;
3953 if ((state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK)
3954 icon_view->priv->shift_pressed = TRUE;
3956 /* else we assume not pressed */
3960 case GTK_MOVEMENT_LOGICAL_POSITIONS:
3961 case GTK_MOVEMENT_VISUAL_POSITIONS:
3962 gtk_icon_view_move_cursor_left_right (icon_view, count);
3964 case GTK_MOVEMENT_DISPLAY_LINES:
3965 gtk_icon_view_move_cursor_up_down (icon_view, count);
3967 case GTK_MOVEMENT_PAGES:
3968 gtk_icon_view_move_cursor_page_up_down (icon_view, count);
3970 case GTK_MOVEMENT_BUFFER_ENDS:
3971 gtk_icon_view_move_cursor_start_end (icon_view, count);
3974 g_assert_not_reached ();
3977 icon_view->priv->ctrl_pressed = FALSE;
3978 icon_view->priv->shift_pressed = FALSE;
3980 icon_view->priv->draw_focus = TRUE;
3985 static GtkIconViewItem *
3986 find_item (GtkIconView *icon_view,
3987 GtkIconViewItem *current,
3993 GtkIconViewItem *item;
3995 /* FIXME: this could be more efficient
3997 row = current->row + row_ofs;
3998 col = current->col + col_ofs;
4000 for (items = icon_view->priv->items; items; items = items->next)
4003 if (item->row == row && item->col == col)
4011 find_cell (GtkIconView *icon_view,
4012 GtkIconViewItem *item,
4014 GtkOrientation orientation,
4024 if (icon_view->priv->item_orientation != orientation)
4027 gtk_icon_view_set_cell_data (icon_view, item);
4029 focusable = g_new0 (gint, icon_view->priv->n_cells);
4033 for (k = 0; k < 2; k++)
4034 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
4036 GtkCellRendererMode mode;
4037 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
4039 if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END))
4042 if (!gtk_cell_renderer_get_visible (info->cell))
4045 g_object_get (info->cell, "mode", &mode, NULL);
4046 if (mode != GTK_CELL_RENDERER_MODE_INERT)
4049 current = n_focusable;
4051 focusable[n_focusable] = i;
4057 if (n_focusable == 0)
4065 current = step > 0 ? 0 : n_focusable - 1;
4066 cell = focusable[current];
4069 if (current + *count < 0)
4072 *count = current + *count;
4074 else if (current + *count > n_focusable - 1)
4077 *count = current + *count - (n_focusable - 1);
4081 cell = focusable[current + *count];
4090 static GtkIconViewItem *
4091 find_item_page_up_down (GtkIconView *icon_view,
4092 GtkIconViewItem *current,
4099 y = current->y + count * icon_view->priv->vadjustment->page_size;
4101 item = g_list_find (icon_view->priv->items, current);
4106 for (next = item->next; next; next = next->next)
4108 if (((GtkIconViewItem *)next->data)->col == col)
4111 if (!next || ((GtkIconViewItem *)next->data)->y > y)
4121 for (next = item->prev; next; next = next->prev)
4123 if (((GtkIconViewItem *)next->data)->col == col)
4126 if (!next || ((GtkIconViewItem *)next->data)->y < y)
4140 gtk_icon_view_select_all_between (GtkIconView *icon_view,
4141 GtkIconViewItem *anchor,
4142 GtkIconViewItem *cursor)
4145 GtkIconViewItem *item;
4146 gint row1, row2, col1, col2;
4147 gboolean dirty = FALSE;
4149 if (anchor->row < cursor->row)
4160 if (anchor->col < cursor->col)
4171 for (items = icon_view->priv->items; items; items = items->next)
4175 if (row1 <= item->row && item->row <= row2 &&
4176 col1 <= item->col && item->col <= col2)
4178 if (!item->selected)
4181 item->selected = TRUE;
4182 gtk_icon_view_item_selected_changed (icon_view, item);
4184 gtk_icon_view_queue_draw_item (icon_view, item);
4192 gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
4195 GtkIconViewItem *item;
4197 gboolean dirty = FALSE;
4199 GtkDirectionType direction;
4201 if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
4204 direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN;
4206 if (!icon_view->priv->cursor_item)
4211 list = icon_view->priv->items;
4213 list = g_list_last (icon_view->priv->items);
4215 item = list ? list->data : NULL;
4220 item = icon_view->priv->cursor_item;
4221 cell = icon_view->priv->cursor_cell;
4222 step = count > 0 ? 1 : -1;
4225 cell = find_cell (icon_view, item, cell,
4226 GTK_ORIENTATION_VERTICAL,
4231 item = find_item (icon_view, item, step, 0);
4232 count = count - step;
4238 if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction))
4240 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view));
4242 gtk_widget_child_focus (toplevel,
4243 direction == GTK_DIR_UP ?
4244 GTK_DIR_TAB_BACKWARD :
4245 GTK_DIR_TAB_FORWARD);
4251 if (icon_view->priv->ctrl_pressed ||
4252 !icon_view->priv->shift_pressed ||
4253 !icon_view->priv->anchor_item ||
4254 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
4255 icon_view->priv->anchor_item = item;
4257 gtk_icon_view_set_cursor_item (icon_view, item, cell);
4259 if (!icon_view->priv->ctrl_pressed &&
4260 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
4262 dirty = gtk_icon_view_unselect_all_internal (icon_view);
4263 dirty = gtk_icon_view_select_all_between (icon_view,
4264 icon_view->priv->anchor_item,
4268 gtk_icon_view_scroll_to_item (icon_view, item);
4271 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
4275 gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
4278 GtkIconViewItem *item;
4279 gboolean dirty = FALSE;
4281 if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
4284 if (!icon_view->priv->cursor_item)
4289 list = icon_view->priv->items;
4291 list = g_list_last (icon_view->priv->items);
4293 item = list ? list->data : NULL;
4296 item = find_item_page_up_down (icon_view,
4297 icon_view->priv->cursor_item,
4300 if (item == icon_view->priv->cursor_item)
4301 gtk_widget_error_bell (GTK_WIDGET (icon_view));
4306 if (icon_view->priv->ctrl_pressed ||
4307 !icon_view->priv->shift_pressed ||
4308 !icon_view->priv->anchor_item ||
4309 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
4310 icon_view->priv->anchor_item = item;
4312 gtk_icon_view_set_cursor_item (icon_view, item, -1);
4314 if (!icon_view->priv->ctrl_pressed &&
4315 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
4317 dirty = gtk_icon_view_unselect_all_internal (icon_view);
4318 dirty = gtk_icon_view_select_all_between (icon_view,
4319 icon_view->priv->anchor_item,
4323 gtk_icon_view_scroll_to_item (icon_view, item);
4326 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
4330 gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
4333 GtkIconViewItem *item;
4335 gboolean dirty = FALSE;
4337 GtkDirectionType direction;
4339 if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
4342 direction = count < 0 ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
4344 if (!icon_view->priv->cursor_item)
4349 list = icon_view->priv->items;
4351 list = g_list_last (icon_view->priv->items);
4353 item = list ? list->data : NULL;
4357 item = icon_view->priv->cursor_item;
4358 cell = icon_view->priv->cursor_cell;
4359 step = count > 0 ? 1 : -1;
4362 cell = find_cell (icon_view, item, cell,
4363 GTK_ORIENTATION_HORIZONTAL,
4368 item = find_item (icon_view, item, 0, step);
4369 count = count - step;
4375 if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction))
4377 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view));
4379 gtk_widget_child_focus (toplevel,
4380 direction == GTK_DIR_LEFT ?
4381 GTK_DIR_TAB_BACKWARD :
4382 GTK_DIR_TAB_FORWARD);
4388 if (icon_view->priv->ctrl_pressed ||
4389 !icon_view->priv->shift_pressed ||
4390 !icon_view->priv->anchor_item ||
4391 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
4392 icon_view->priv->anchor_item = item;
4394 gtk_icon_view_set_cursor_item (icon_view, item, cell);
4396 if (!icon_view->priv->ctrl_pressed &&
4397 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
4399 dirty = gtk_icon_view_unselect_all_internal (icon_view);
4400 dirty = gtk_icon_view_select_all_between (icon_view,
4401 icon_view->priv->anchor_item,
4405 gtk_icon_view_scroll_to_item (icon_view, item);
4408 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
4412 gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
4415 GtkIconViewItem *item;
4417 gboolean dirty = FALSE;
4419 if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
4423 list = icon_view->priv->items;
4425 list = g_list_last (icon_view->priv->items);
4427 item = list ? list->data : NULL;
4429 if (item == icon_view->priv->cursor_item)
4430 gtk_widget_error_bell (GTK_WIDGET (icon_view));
4435 if (icon_view->priv->ctrl_pressed ||
4436 !icon_view->priv->shift_pressed ||
4437 !icon_view->priv->anchor_item ||
4438 icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
4439 icon_view->priv->anchor_item = item;
4441 gtk_icon_view_set_cursor_item (icon_view, item, -1);
4443 if (!icon_view->priv->ctrl_pressed &&
4444 icon_view->priv->selection_mode != GTK_SELECTION_NONE)
4446 dirty = gtk_icon_view_unselect_all_internal (icon_view);
4447 dirty = gtk_icon_view_select_all_between (icon_view,
4448 icon_view->priv->anchor_item,
4452 gtk_icon_view_scroll_to_item (icon_view, item);
4455 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
4459 * gtk_icon_view_scroll_to_path:
4460 * @icon_view: A #GtkIconView.
4461 * @path: The path of the item to move to.
4462 * @use_align: whether to use alignment arguments, or %FALSE.
4463 * @row_align: The vertical alignment of the item specified by @path.
4464 * @col_align: The horizontal alignment of the item specified by @path.
4466 * Moves the alignments of @icon_view to the position specified by @path.
4467 * @row_align determines where the row is placed, and @col_align determines
4468 * where @column is placed. Both are expected to be between 0.0 and 1.0.
4469 * 0.0 means left/top alignment, 1.0 means right/bottom alignment, 0.5 means
4472 * If @use_align is %FALSE, then the alignment arguments are ignored, and the
4473 * tree does the minimum amount of work to scroll the item onto the screen.
4474 * This means that the item will be scrolled to the edge closest to its current
4475 * position. If the item is currently visible on the screen, nothing is done.
4477 * This function only works if the model is set, and @path is a valid row on
4478 * the model. If the model changes before the @icon_view is realized, the
4479 * centered path will be modified to reflect this change.
4484 gtk_icon_view_scroll_to_path (GtkIconView *icon_view,
4490 GtkIconViewItem *item = NULL;
4493 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
4494 g_return_if_fail (path != NULL);
4495 g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
4496 g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
4498 widget = GTK_WIDGET (icon_view);
4500 if (gtk_tree_path_get_depth (path) > 0)
4501 item = g_list_nth_data (icon_view->priv->items,
4502 gtk_tree_path_get_indices(path)[0]);
4504 if (!item || item->width < 0 ||
4505 !gtk_widget_get_realized (widget))
4507 if (icon_view->priv->scroll_to_path)
4508 gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
4510 icon_view->priv->scroll_to_path = NULL;
4513 icon_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (icon_view), icon_view->priv->model, path);
4515 icon_view->priv->scroll_to_use_align = use_align;
4516 icon_view->priv->scroll_to_row_align = row_align;
4517 icon_view->priv->scroll_to_col_align = col_align;
4524 GtkAllocation allocation;
4529 gtk_widget_style_get (widget,
4530 "focus-line-width", &focus_width,
4533 gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
4535 gtk_widget_get_allocation (widget, &allocation);
4537 offset = y + item->y - focus_width - row_align * (allocation.height - item->height);
4539 gtk_adjustment_set_value (icon_view->priv->vadjustment,
4540 icon_view->priv->vadjustment->value + offset);
4542 offset = x + item->x - focus_width - col_align * (allocation.width - item->width);
4544 gtk_adjustment_set_value (icon_view->priv->hadjustment,
4545 icon_view->priv->hadjustment->value + offset);
4547 gtk_adjustment_changed (icon_view->priv->hadjustment);
4548 gtk_adjustment_changed (icon_view->priv->vadjustment);
4551 gtk_icon_view_scroll_to_item (icon_view, item);
4556 gtk_icon_view_scroll_to_item (GtkIconView *icon_view,
4557 GtkIconViewItem *item)
4559 GtkAllocation allocation;
4560 GtkWidget *widget = GTK_WIDGET (icon_view);
4561 gint x, y, width, height;
4564 gtk_widget_style_get (widget,
4565 "focus-line-width", &focus_width,
4568 width = gdk_window_get_width (icon_view->priv->bin_window);
4569 height = gdk_window_get_height (icon_view->priv->bin_window);
4570 gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
4572 gtk_widget_get_allocation (widget, &allocation);
4574 if (y + item->y - focus_width < 0)
4575 gtk_adjustment_set_value (icon_view->priv->vadjustment,
4576 icon_view->priv->vadjustment->value + y + item->y - focus_width);
4577 else if (y + item->y + item->height + focus_width > allocation.height)
4578 gtk_adjustment_set_value (icon_view->priv->vadjustment,
4579 icon_view->priv->vadjustment->value + y + item->y + item->height
4580 + focus_width - allocation.height);
4582 if (x + item->x - focus_width < 0)
4583 gtk_adjustment_set_value (icon_view->priv->hadjustment,
4584 icon_view->priv->hadjustment->value + x + item->x - focus_width);
4585 else if (x + item->x + item->width + focus_width > allocation.width)
4586 gtk_adjustment_set_value (icon_view->priv->hadjustment,
4587 icon_view->priv->hadjustment->value + x + item->x + item->width
4588 + focus_width - allocation.width);
4590 gtk_adjustment_changed (icon_view->priv->hadjustment);
4591 gtk_adjustment_changed (icon_view->priv->vadjustment);
4594 /* GtkCellLayout implementation */
4595 static GtkIconViewCellInfo *
4596 gtk_icon_view_get_cell_info (GtkIconView *icon_view,
4597 GtkCellRenderer *renderer)
4601 for (i = icon_view->priv->cell_list; i; i = i->next)
4603 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)i->data;
4605 if (info->cell == renderer)
4613 gtk_icon_view_set_cell_data (GtkIconView *icon_view,
4614 GtkIconViewItem *item)
4617 gboolean iters_persist;
4620 iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
4626 path = gtk_tree_path_new_from_indices (item->index, -1);
4627 if (!gtk_tree_model_get_iter (icon_view->priv->model, &iter, path))
4629 gtk_tree_path_free (path);
4634 for (i = icon_view->priv->cell_list; i; i = i->next)
4637 GtkIconViewCellInfo *info = i->data;
4639 g_object_freeze_notify (G_OBJECT (info->cell));
4641 for (j = info->attributes; j && j->next; j = j->next->next)
4643 gchar *property = j->data;
4644 gint column = GPOINTER_TO_INT (j->next->data);
4645 GValue value = {0, };
4647 gtk_tree_model_get_value (icon_view->priv->model, &iter,
4649 g_object_set_property (G_OBJECT (info->cell),
4651 g_value_unset (&value);
4655 (* info->func) (GTK_CELL_LAYOUT (icon_view),
4657 icon_view->priv->model,
4661 g_object_thaw_notify (G_OBJECT (info->cell));
4666 free_cell_attributes (GtkIconViewCellInfo *info)
4670 list = info->attributes;
4671 while (list && list->next)
4673 g_free (list->data);
4674 list = list->next->next;
4677 g_slist_free (info->attributes);
4678 info->attributes = NULL;
4682 free_cell_info (GtkIconViewCellInfo *info)
4684 free_cell_attributes (info);
4686 g_object_unref (info->cell);
4689 (* info->destroy) (info->func_data);
4695 gtk_icon_view_cell_layout_pack_start (GtkCellLayout *layout,
4696 GtkCellRenderer *renderer,
4699 GtkIconViewCellInfo *info;
4700 GtkIconView *icon_view = GTK_ICON_VIEW (layout);
4702 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
4703 g_return_if_fail (!gtk_icon_view_get_cell_info (icon_view, renderer));
4705 g_object_ref_sink (renderer);
4707 info = g_new0 (GtkIconViewCellInfo, 1);
4708 info->cell = renderer;
4709 info->expand = expand ? TRUE : FALSE;
4710 info->pack = GTK_PACK_START;
4711 info->position = icon_view->priv->n_cells;
4713 icon_view->priv->cell_list = g_list_append (icon_view->priv->cell_list, info);
4714 icon_view->priv->n_cells++;
4718 gtk_icon_view_cell_layout_pack_end (GtkCellLayout *layout,
4719 GtkCellRenderer *renderer,
4722 GtkIconViewCellInfo *info;
4723 GtkIconView *icon_view = GTK_ICON_VIEW (layout);
4725 g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
4726 g_return_if_fail (!gtk_icon_view_get_cell_info (icon_view, renderer));
4728 g_object_ref_sink (renderer);
4730 info = g_new0 (GtkIconViewCellInfo, 1);
4731 info->cell = renderer;
4732 info->expand = expand ? TRUE : FALSE;
4733 info->pack = GTK_PACK_END;
4734 info->position = icon_view->priv->n_cells;
4736 icon_view->priv->cell_list = g_list_append (icon_view->priv->cell_list, info);
4737 icon_view->priv->n_cells++;
4741 gtk_icon_view_cell_layout_add_attribute (GtkCellLayout *layout,
4742 GtkCellRenderer *renderer,
4743 const gchar *attribute,
4746 GtkIconViewCellInfo *info;
4747 GtkIconView *icon_view = GTK_ICON_VIEW (layout);
4749 info = gtk_icon_view_get_cell_info (icon_view, renderer);
4750 g_return_if_fail (info != NULL);
4752 info->attributes = g_slist_prepend (info->attributes,
4753 GINT_TO_POINTER (column));
4754 info->attributes = g_slist_prepend (info->attributes,
4755 g_strdup (attribute));
4759 gtk_icon_view_cell_layout_clear (GtkCellLayout *layout)
4761 GtkIconView *icon_view = GTK_ICON_VIEW (layout);
4763 while (icon_view->priv->cell_list)
4765 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)icon_view->priv->cell_list->data;
4766 free_cell_info (info);
4767 icon_view->priv->cell_list = g_list_delete_link (icon_view->priv->cell_list,
4768 icon_view->priv->cell_list);
4771 icon_view->priv->n_cells = 0;
4775 gtk_icon_view_cell_layout_set_cell_data_func (GtkCellLayout *layout,
4776 GtkCellRenderer *cell,
4777 GtkCellLayoutDataFunc func,
4779 GDestroyNotify destroy)
4781 GtkIconViewCellInfo *info;
4782 GtkIconView *icon_view = GTK_ICON_VIEW (layout);
4784 info = gtk_icon_view_get_cell_info (icon_view, cell);
4785 g_return_if_fail (info != NULL);
4789 GDestroyNotify d = info->destroy;
4791 info->destroy = NULL;
4792 d (info->func_data);
4796 info->func_data = func_data;
4797 info->destroy = destroy;
4801 gtk_icon_view_cell_layout_clear_attributes (GtkCellLayout *layout,
4802 GtkCellRenderer *renderer)
4804 GtkIconViewCellInfo *info;
4806 info = gtk_icon_view_get_cell_info (GTK_ICON_VIEW (layout), renderer);
4808 free_cell_attributes (info);
4812 gtk_icon_view_cell_layout_reorder (GtkCellLayout *layout,
4813 GtkCellRenderer *cell,
4816 GtkIconView *icon_view;
4818 GtkIconViewCellInfo *info;
4821 icon_view = GTK_ICON_VIEW (layout);
4823 g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
4825 info = gtk_icon_view_get_cell_info (icon_view, cell);
4827 g_return_if_fail (info != NULL);
4828 g_return_if_fail (position >= 0);
4830 link = g_list_find (icon_view->priv->cell_list, info);
4832 g_return_if_fail (link != NULL);
4834 icon_view->priv->cell_list = g_list_delete_link (icon_view->priv->cell_list,
4836 icon_view->priv->cell_list = g_list_insert (icon_view->priv->cell_list,
4839 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
4846 gtk_widget_queue_draw (GTK_WIDGET (icon_view));
4850 gtk_icon_view_cell_layout_get_cells (GtkCellLayout *layout)
4852 GtkIconView *icon_view = (GtkIconView *)layout;
4853 GList *retval = NULL, *l;
4855 for (l = icon_view->priv->cell_list; l; l = l->next)
4857 GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
4859 retval = g_list_prepend (retval, info->cell);
4862 return g_list_reverse (retval);
4869 * gtk_icon_view_new:
4871 * Creates a new #GtkIconView widget
4873 * Return value: A newly created #GtkIconView widget
4878 gtk_icon_view_new (void)
4880 return g_object_new (GTK_TYPE_ICON_VIEW, NULL);
4884 * gtk_icon_view_new_with_model:
4885 * @model: The model.
4887 * Creates a new #GtkIconView widget with the model @model.
4889 * Return value: A newly created #GtkIconView widget.
4894 gtk_icon_view_new_with_model (GtkTreeModel *model)
4896 return g_object_new (GTK_TYPE_ICON_VIEW, "model", model, NULL);
4900 * gtk_icon_view_convert_widget_to_bin_window_coords:
4901 * @icon_view: a #GtkIconView
4902 * @wx: X coordinate relative to the widget
4903 * @wy: Y coordinate relative to the widget
4904 * @bx: return location for bin_window X coordinate
4905 * @by: return location for bin_window Y coordinate
4907 * Converts widget coordinates to coordinates for the bin_window,
4908 * as expected by e.g. gtk_icon_view_get_path_at_pos().
4913 gtk_icon_view_convert_widget_to_bin_window_coords (GtkIconView *icon_view,
4921 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
4923 if (icon_view->priv->bin_window)
4924 gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
4935 * gtk_icon_view_get_path_at_pos:
4936 * @icon_view: A #GtkIconView.
4937 * @x: The x position to be identified
4938 * @y: The y position to be identified
4940 * Finds the path at the point (@x, @y), relative to bin_window coordinates.
4941 * See gtk_icon_view_get_item_at_pos(), if you are also interested in
4942 * the cell at the specified position.
4943 * See gtk_icon_view_convert_widget_to_bin_window_coords() for converting
4944 * widget coordinates to bin_window coordinates.
4946 * Return value: The #GtkTreePath corresponding to the icon or %NULL
4947 * if no icon exists at that position.
4952 gtk_icon_view_get_path_at_pos (GtkIconView *icon_view,
4956 GtkIconViewItem *item;
4959 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
4961 item = gtk_icon_view_get_item_at_coords (icon_view, x, y, TRUE, NULL);
4966 path = gtk_tree_path_new_from_indices (item->index, -1);
4972 * gtk_icon_view_get_item_at_pos:
4973 * @icon_view: A #GtkIconView.
4974 * @x: The x position to be identified
4975 * @y: The y position to be identified
4976 * @path: (allow-none): Return location for the path, or %NULL
4977 * @cell: Return location for the renderer responsible for the cell
4978 * at (@x, @y), or %NULL
4980 * Finds the path at the point (@x, @y), relative to bin_window coordinates.
4981 * In contrast to gtk_icon_view_get_path_at_pos(), this function also
4982 * obtains the cell at the specified position. The returned path should
4983 * be freed with gtk_tree_path_free().
4984 * See gtk_icon_view_convert_widget_to_bin_window_coords() for converting
4985 * widget coordinates to bin_window coordinates.
4987 * Return value: %TRUE if an item exists at the specified position
4992 gtk_icon_view_get_item_at_pos (GtkIconView *icon_view,
4996 GtkCellRenderer **cell)
4998 GtkIconViewItem *item;
4999 GtkIconViewCellInfo *info;
5001 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
5003 item = gtk_icon_view_get_item_at_coords (icon_view, x, y, TRUE, &info);
5008 *path = gtk_tree_path_new_from_indices (item->index, -1);
5021 return (item != NULL);
5025 * gtk_icon_view_set_tooltip_item:
5026 * @icon_view: a #GtkIconView
5027 * @tooltip: a #GtkTooltip
5028 * @path: a #GtkTreePath
5030 * Sets the tip area of @tooltip to be the area covered by the item at @path.
5031 * See also gtk_icon_view_set_tooltip_column() for a simpler alternative.
5032 * See also gtk_tooltip_set_tip_area().
5037 gtk_icon_view_set_tooltip_item (GtkIconView *icon_view,
5038 GtkTooltip *tooltip,
5041 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5042 g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
5044 gtk_icon_view_set_tooltip_cell (icon_view, tooltip, path, NULL);
5048 * gtk_icon_view_set_tooltip_cell:
5049 * @icon_view: a #GtkIconView
5050 * @tooltip: a #GtkTooltip
5051 * @path: a #GtkTreePath
5052 * @cell: (allow-none): a #GtkCellRenderer or %NULL
5054 * Sets the tip area of @tooltip to the area which @cell occupies in
5055 * the item pointed to by @path. See also gtk_tooltip_set_tip_area().
5057 * See also gtk_icon_view_set_tooltip_column() for a simpler alternative.
5062 gtk_icon_view_set_tooltip_cell (GtkIconView *icon_view,
5063 GtkTooltip *tooltip,
5065 GtkCellRenderer *cell)
5068 GtkIconViewItem *item = NULL;
5069 GtkIconViewCellInfo *info = NULL;
5072 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5073 g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
5074 g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
5076 if (gtk_tree_path_get_depth (path) > 0)
5077 item = g_list_nth_data (icon_view->priv->items,
5078 gtk_tree_path_get_indices(path)[0]);
5085 info = gtk_icon_view_get_cell_info (icon_view, cell);
5086 gtk_icon_view_get_cell_area (icon_view, item, info, &rect);
5092 rect.width = item->width;
5093 rect.height = item->height;
5096 if (icon_view->priv->bin_window)
5098 gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
5103 gtk_tooltip_set_tip_area (tooltip, &rect);
5108 * gtk_icon_view_get_tooltip_context:
5109 * @icon_view: an #GtkIconView
5110 * @x: the x coordinate (relative to widget coordinates)
5111 * @y: the y coordinate (relative to widget coordinates)
5112 * @keyboard_tip: whether this is a keyboard tooltip or not
5113 * @model: (out) (allow-none): a pointer to receive a #GtkTreeModel or %NULL
5114 * @path: (out) (allow-none): a pointer to receive a #GtkTreePath or %NULL
5115 * @iter: (out) (allow-none): a pointer to receive a #GtkTreeIter or %NULL
5117 * This function is supposed to be used in a #GtkWidget::query-tooltip
5118 * signal handler for #GtkIconView. The @x, @y and @keyboard_tip values
5119 * which are received in the signal handler, should be passed to this
5120 * function without modification.
5122 * The return value indicates whether there is an icon view item at the given
5123 * coordinates (%TRUE) or not (%FALSE) for mouse tooltips. For keyboard
5124 * tooltips the item returned will be the cursor item. When %TRUE, then any of
5125 * @model, @path and @iter which have been provided will be set to point to
5126 * that row and the corresponding model. @x and @y will always be converted
5127 * to be relative to @icon_view's bin_window if @keyboard_tooltip is %FALSE.
5129 * Return value: whether or not the given tooltip context points to a item
5134 gtk_icon_view_get_tooltip_context (GtkIconView *icon_view,
5137 gboolean keyboard_tip,
5138 GtkTreeModel **model,
5142 GtkTreePath *tmppath = NULL;
5144 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
5145 g_return_val_if_fail (x != NULL, FALSE);
5146 g_return_val_if_fail (y != NULL, FALSE);
5150 gtk_icon_view_get_cursor (icon_view, &tmppath, NULL);
5157 gtk_icon_view_convert_widget_to_bin_window_coords (icon_view, *x, *y,
5160 if (!gtk_icon_view_get_item_at_pos (icon_view, *x, *y, &tmppath, NULL))
5165 *model = gtk_icon_view_get_model (icon_view);
5168 gtk_tree_model_get_iter (gtk_icon_view_get_model (icon_view),
5174 gtk_tree_path_free (tmppath);
5180 gtk_icon_view_set_tooltip_query_cb (GtkWidget *widget,
5183 gboolean keyboard_tip,
5184 GtkTooltip *tooltip,
5190 GtkTreeModel *model;
5191 GtkIconView *icon_view = GTK_ICON_VIEW (widget);
5193 if (!gtk_icon_view_get_tooltip_context (GTK_ICON_VIEW (widget),
5196 &model, &path, &iter))
5199 gtk_tree_model_get (model, &iter, icon_view->priv->tooltip_column, &str, -1);
5203 gtk_tree_path_free (path);
5207 gtk_tooltip_set_markup (tooltip, str);
5208 gtk_icon_view_set_tooltip_item (icon_view, tooltip, path);
5210 gtk_tree_path_free (path);
5218 * gtk_icon_view_set_tooltip_column:
5219 * @icon_view: a #GtkIconView
5220 * @column: an integer, which is a valid column number for @icon_view's model
5222 * If you only plan to have simple (text-only) tooltips on full items, you
5223 * can use this function to have #GtkIconView handle these automatically
5224 * for you. @column should be set to the column in @icon_view's model
5225 * containing the tooltip texts, or -1 to disable this feature.
5227 * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
5228 * @icon_view will connect a #GtkWidget::query-tooltip signal handler.
5233 gtk_icon_view_set_tooltip_column (GtkIconView *icon_view,
5236 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5238 if (column == icon_view->priv->tooltip_column)
5243 g_signal_handlers_disconnect_by_func (icon_view,
5244 gtk_icon_view_set_tooltip_query_cb,
5246 gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), FALSE);
5250 if (icon_view->priv->tooltip_column == -1)
5252 g_signal_connect (icon_view, "query-tooltip",
5253 G_CALLBACK (gtk_icon_view_set_tooltip_query_cb), NULL);
5254 gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), TRUE);
5258 icon_view->priv->tooltip_column = column;
5259 g_object_notify (G_OBJECT (icon_view), "tooltip-column");
5263 * gtk_icon_view_get_tooltip_column:
5264 * @icon_view: a #GtkIconView
5266 * Returns the column of @icon_view's model which is being used for
5267 * displaying tooltips on @icon_view's rows.
5269 * Return value: the index of the tooltip column that is currently being
5270 * used, or -1 if this is disabled.
5275 gtk_icon_view_get_tooltip_column (GtkIconView *icon_view)
5277 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), 0);
5279 return icon_view->priv->tooltip_column;
5283 * gtk_icon_view_get_visible_range:
5284 * @icon_view: A #GtkIconView
5285 * @start_path: (allow-none): Return location for start of region, or %NULL
5286 * @end_path: (allow-none): Return location for end of region, or %NULL
5288 * Sets @start_path and @end_path to be the first and last visible path.
5289 * Note that there may be invisible paths in between.
5291 * Both paths should be freed with gtk_tree_path_free() after use.
5293 * Return value: %TRUE, if valid paths were placed in @start_path and @end_path
5298 gtk_icon_view_get_visible_range (GtkIconView *icon_view,
5299 GtkTreePath **start_path,
5300 GtkTreePath **end_path)
5302 gint start_index = -1;
5303 gint end_index = -1;
5306 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
5308 if (icon_view->priv->hadjustment == NULL ||
5309 icon_view->priv->vadjustment == NULL)
5312 if (start_path == NULL && end_path == NULL)
5315 for (icons = icon_view->priv->items; icons; icons = icons->next)
5317 GtkIconViewItem *item = icons->data;
5319 if ((item->x + item->width >= (int)icon_view->priv->hadjustment->value) &&
5320 (item->y + item->height >= (int)icon_view->priv->vadjustment->value) &&
5321 (item->x <= (int) (icon_view->priv->hadjustment->value + icon_view->priv->hadjustment->page_size)) &&
5322 (item->y <= (int) (icon_view->priv->vadjustment->value + icon_view->priv->vadjustment->page_size)))
5324 if (start_index == -1)
5325 start_index = item->index;
5326 end_index = item->index;
5330 if (start_path && start_index != -1)
5331 *start_path = gtk_tree_path_new_from_indices (start_index, -1);
5332 if (end_path && end_index != -1)
5333 *end_path = gtk_tree_path_new_from_indices (end_index, -1);
5335 return start_index != -1;
5339 * gtk_icon_view_selected_foreach:
5340 * @icon_view: A #GtkIconView.
5341 * @func: (scope call): The function to call for each selected icon.
5342 * @data: User data to pass to the function.
5344 * Calls a function for each selected icon. Note that the model or
5345 * selection cannot be modified from within this function.
5350 gtk_icon_view_selected_foreach (GtkIconView *icon_view,
5351 GtkIconViewForeachFunc func,
5356 for (list = icon_view->priv->items; list; list = list->next)
5358 GtkIconViewItem *item = list->data;
5359 GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
5362 (* func) (icon_view, path, data);
5364 gtk_tree_path_free (path);
5369 * gtk_icon_view_set_selection_mode:
5370 * @icon_view: A #GtkIconView.
5371 * @mode: The selection mode
5373 * Sets the selection mode of the @icon_view.
5378 gtk_icon_view_set_selection_mode (GtkIconView *icon_view,
5379 GtkSelectionMode mode)
5381 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5383 if (mode == icon_view->priv->selection_mode)
5386 if (mode == GTK_SELECTION_NONE ||
5387 icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
5388 gtk_icon_view_unselect_all (icon_view);
5390 icon_view->priv->selection_mode = mode;
5392 g_object_notify (G_OBJECT (icon_view), "selection-mode");
5396 * gtk_icon_view_get_selection_mode:
5397 * @icon_view: A #GtkIconView.
5399 * Gets the selection mode of the @icon_view.
5401 * Return value: the current selection mode
5406 gtk_icon_view_get_selection_mode (GtkIconView *icon_view)
5408 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), GTK_SELECTION_SINGLE);
5410 return icon_view->priv->selection_mode;
5414 * gtk_icon_view_set_model:
5415 * @icon_view: A #GtkIconView.
5416 * @model: (allow-none): The model.
5418 * Sets the model for a #GtkIconView.
5419 * If the @icon_view already has a model set, it will remove
5420 * it before setting the new model. If @model is %NULL, then
5421 * it will unset the old model.
5426 gtk_icon_view_set_model (GtkIconView *icon_view,
5427 GtkTreeModel *model)
5429 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5430 g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
5432 if (icon_view->priv->model == model)
5435 if (icon_view->priv->scroll_to_path)
5437 gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
5438 icon_view->priv->scroll_to_path = NULL;
5441 gtk_icon_view_stop_editing (icon_view, TRUE);
5447 if (icon_view->priv->pixbuf_column != -1)
5449 column_type = gtk_tree_model_get_column_type (model,
5450 icon_view->priv->pixbuf_column);
5452 g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
5455 if (icon_view->priv->text_column != -1)
5457 column_type = gtk_tree_model_get_column_type (model,
5458 icon_view->priv->text_column);
5460 g_return_if_fail (column_type == G_TYPE_STRING);
5463 if (icon_view->priv->markup_column != -1)
5465 column_type = gtk_tree_model_get_column_type (model,
5466 icon_view->priv->markup_column);
5468 g_return_if_fail (column_type == G_TYPE_STRING);
5473 if (icon_view->priv->model)
5475 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
5476 gtk_icon_view_row_changed,
5478 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
5479 gtk_icon_view_row_inserted,
5481 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
5482 gtk_icon_view_row_deleted,
5484 g_signal_handlers_disconnect_by_func (icon_view->priv->model,
5485 gtk_icon_view_rows_reordered,
5488 g_object_unref (icon_view->priv->model);
5490 g_list_foreach (icon_view->priv->items, (GFunc)gtk_icon_view_item_free, NULL);
5491 g_list_free (icon_view->priv->items);
5492 icon_view->priv->items = NULL;
5493 icon_view->priv->anchor_item = NULL;
5494 icon_view->priv->cursor_item = NULL;
5495 icon_view->priv->last_single_clicked = NULL;
5496 icon_view->priv->width = 0;
5497 icon_view->priv->height = 0;
5500 icon_view->priv->model = model;
5502 if (icon_view->priv->model)
5504 g_object_ref (icon_view->priv->model);
5505 g_signal_connect (icon_view->priv->model,
5507 G_CALLBACK (gtk_icon_view_row_changed),
5509 g_signal_connect (icon_view->priv->model,
5511 G_CALLBACK (gtk_icon_view_row_inserted),
5513 g_signal_connect (icon_view->priv->model,
5515 G_CALLBACK (gtk_icon_view_row_deleted),
5517 g_signal_connect (icon_view->priv->model,
5519 G_CALLBACK (gtk_icon_view_rows_reordered),
5522 gtk_icon_view_build_items (icon_view);
5524 gtk_icon_view_queue_layout (icon_view);
5527 g_object_notify (G_OBJECT (icon_view), "model");
5529 if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
5530 gtk_widget_queue_resize (GTK_WIDGET (icon_view));
5534 * gtk_icon_view_get_model:
5535 * @icon_view: a #GtkIconView
5537 * Returns the model the #GtkIconView is based on. Returns %NULL if the
5540 * Return value: (transfer none): A #GtkTreeModel, or %NULL if none is
5541 * currently being used.
5546 gtk_icon_view_get_model (GtkIconView *icon_view)
5548 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
5550 return icon_view->priv->model;
5554 update_text_cell (GtkIconView *icon_view)
5556 GtkIconViewCellInfo *info;
5560 if (icon_view->priv->text_column == -1 &&
5561 icon_view->priv->markup_column == -1)
5563 if (icon_view->priv->text_cell != -1)
5565 if (icon_view->priv->pixbuf_cell > icon_view->priv->text_cell)
5566 icon_view->priv->pixbuf_cell--;
5568 info = g_list_nth_data (icon_view->priv->cell_list,
5569 icon_view->priv->text_cell);
5571 icon_view->priv->cell_list = g_list_remove (icon_view->priv->cell_list, info);
5573 free_cell_info (info);
5575 icon_view->priv->n_cells--;
5576 icon_view->priv->text_cell = -1;
5581 if (icon_view->priv->text_cell == -1)
5583 GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
5584 gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (icon_view), cell, FALSE);
5585 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
5588 if (info->cell == cell)
5590 icon_view->priv->text_cell = i;
5596 info = g_list_nth_data (icon_view->priv->cell_list,
5597 icon_view->priv->text_cell);
5599 if (icon_view->priv->markup_column != -1)
5600 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
5602 "markup", icon_view->priv->markup_column,
5605 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
5607 "text", icon_view->priv->text_column,
5610 if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
5611 g_object_set (info->cell,
5612 "alignment", PANGO_ALIGN_CENTER,
5613 "wrap-mode", PANGO_WRAP_WORD_CHAR,
5618 g_object_set (info->cell,
5619 "alignment", PANGO_ALIGN_LEFT,
5620 "wrap-mode", PANGO_WRAP_WORD_CHAR,
5628 update_pixbuf_cell (GtkIconView *icon_view)
5630 GtkIconViewCellInfo *info;
5634 if (icon_view->priv->pixbuf_column == -1)
5636 if (icon_view->priv->pixbuf_cell != -1)
5638 if (icon_view->priv->text_cell > icon_view->priv->pixbuf_cell)
5639 icon_view->priv->text_cell--;
5641 info = g_list_nth_data (icon_view->priv->cell_list,
5642 icon_view->priv->pixbuf_cell);
5644 icon_view->priv->cell_list = g_list_remove (icon_view->priv->cell_list, info);
5646 free_cell_info (info);
5648 icon_view->priv->n_cells--;
5649 icon_view->priv->pixbuf_cell = -1;
5654 if (icon_view->priv->pixbuf_cell == -1)
5656 GtkCellRenderer *cell = gtk_cell_renderer_pixbuf_new ();
5658 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (icon_view), cell, FALSE);
5659 for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
5662 if (info->cell == cell)
5664 icon_view->priv->pixbuf_cell = i;
5670 info = g_list_nth_data (icon_view->priv->cell_list,
5671 icon_view->priv->pixbuf_cell);
5673 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
5675 "pixbuf", icon_view->priv->pixbuf_column,
5678 if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
5679 g_object_set (info->cell,
5684 g_object_set (info->cell,
5692 * gtk_icon_view_set_text_column:
5693 * @icon_view: A #GtkIconView.
5694 * @column: A column in the currently used model, or -1 to display no text
5696 * Sets the column with text for @icon_view to be @column. The text
5697 * column must be of type #G_TYPE_STRING.
5702 gtk_icon_view_set_text_column (GtkIconView *icon_view,
5705 if (column == icon_view->priv->text_column)
5709 icon_view->priv->text_column = -1;
5712 if (icon_view->priv->model != NULL)
5716 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
5718 g_return_if_fail (column_type == G_TYPE_STRING);
5721 icon_view->priv->text_column = column;
5724 gtk_icon_view_stop_editing (icon_view, TRUE);
5726 update_text_cell (icon_view);
5728 gtk_icon_view_invalidate_sizes (icon_view);
5729 gtk_icon_view_queue_layout (icon_view);
5731 g_object_notify (G_OBJECT (icon_view), "text-column");
5735 * gtk_icon_view_get_text_column:
5736 * @icon_view: A #GtkIconView.
5738 * Returns the column with text for @icon_view.
5740 * Returns: the text column, or -1 if it's unset.
5745 gtk_icon_view_get_text_column (GtkIconView *icon_view)
5747 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
5749 return icon_view->priv->text_column;
5753 * gtk_icon_view_set_markup_column:
5754 * @icon_view: A #GtkIconView.
5755 * @column: A column in the currently used model, or -1 to display no text
5757 * Sets the column with markup information for @icon_view to be
5758 * @column. The markup column must be of type #G_TYPE_STRING.
5759 * If the markup column is set to something, it overrides
5760 * the text column set by gtk_icon_view_set_text_column().
5765 gtk_icon_view_set_markup_column (GtkIconView *icon_view,
5768 if (column == icon_view->priv->markup_column)
5772 icon_view->priv->markup_column = -1;
5775 if (icon_view->priv->model != NULL)
5779 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
5781 g_return_if_fail (column_type == G_TYPE_STRING);
5784 icon_view->priv->markup_column = column;
5787 gtk_icon_view_stop_editing (icon_view, TRUE);
5789 update_text_cell (icon_view);
5791 gtk_icon_view_invalidate_sizes (icon_view);
5792 gtk_icon_view_queue_layout (icon_view);
5794 g_object_notify (G_OBJECT (icon_view), "markup-column");
5798 * gtk_icon_view_get_markup_column:
5799 * @icon_view: A #GtkIconView.
5801 * Returns the column with markup text for @icon_view.
5803 * Returns: the markup column, or -1 if it's unset.
5808 gtk_icon_view_get_markup_column (GtkIconView *icon_view)
5810 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
5812 return icon_view->priv->markup_column;
5816 * gtk_icon_view_set_pixbuf_column:
5817 * @icon_view: A #GtkIconView.
5818 * @column: A column in the currently used model, or -1 to disable
5820 * Sets the column with pixbufs for @icon_view to be @column. The pixbuf
5821 * column must be of type #GDK_TYPE_PIXBUF
5826 gtk_icon_view_set_pixbuf_column (GtkIconView *icon_view,
5829 if (column == icon_view->priv->pixbuf_column)
5833 icon_view->priv->pixbuf_column = -1;
5836 if (icon_view->priv->model != NULL)
5840 column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
5842 g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
5845 icon_view->priv->pixbuf_column = column;
5848 gtk_icon_view_stop_editing (icon_view, TRUE);
5850 update_pixbuf_cell (icon_view);
5852 gtk_icon_view_invalidate_sizes (icon_view);
5853 gtk_icon_view_queue_layout (icon_view);
5855 g_object_notify (G_OBJECT (icon_view), "pixbuf-column");
5860 * gtk_icon_view_get_pixbuf_column:
5861 * @icon_view: A #GtkIconView.
5863 * Returns the column with pixbufs for @icon_view.
5865 * Returns: the pixbuf column, or -1 if it's unset.
5870 gtk_icon_view_get_pixbuf_column (GtkIconView *icon_view)
5872 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
5874 return icon_view->priv->pixbuf_column;
5878 * gtk_icon_view_select_path:
5879 * @icon_view: A #GtkIconView.
5880 * @path: The #GtkTreePath to be selected.
5882 * Selects the row at @path.
5887 gtk_icon_view_select_path (GtkIconView *icon_view,
5890 GtkIconViewItem *item = NULL;
5892 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5893 g_return_if_fail (icon_view->priv->model != NULL);
5894 g_return_if_fail (path != NULL);
5896 if (gtk_tree_path_get_depth (path) > 0)
5897 item = g_list_nth_data (icon_view->priv->items,
5898 gtk_tree_path_get_indices(path)[0]);
5901 gtk_icon_view_select_item (icon_view, item);
5905 * gtk_icon_view_unselect_path:
5906 * @icon_view: A #GtkIconView.
5907 * @path: The #GtkTreePath to be unselected.
5909 * Unselects the row at @path.
5914 gtk_icon_view_unselect_path (GtkIconView *icon_view,
5917 GtkIconViewItem *item;
5919 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5920 g_return_if_fail (icon_view->priv->model != NULL);
5921 g_return_if_fail (path != NULL);
5923 item = g_list_nth_data (icon_view->priv->items,
5924 gtk_tree_path_get_indices(path)[0]);
5929 gtk_icon_view_unselect_item (icon_view, item);
5933 * gtk_icon_view_get_selected_items:
5934 * @icon_view: A #GtkIconView.
5936 * Creates a list of paths of all selected items. Additionally, if you are
5937 * planning on modifying the model after calling this function, you may
5938 * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
5939 * To do this, you can use gtk_tree_row_reference_new().
5941 * To free the return value, use:
5943 * g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
5944 * g_list_free (list);
5947 * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row.
5952 gtk_icon_view_get_selected_items (GtkIconView *icon_view)
5955 GList *selected = NULL;
5957 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
5959 for (list = icon_view->priv->items; list != NULL; list = list->next)
5961 GtkIconViewItem *item = list->data;
5965 GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
5967 selected = g_list_prepend (selected, path);
5975 * gtk_icon_view_select_all:
5976 * @icon_view: A #GtkIconView.
5978 * Selects all the icons. @icon_view must has its selection mode set
5979 * to #GTK_SELECTION_MULTIPLE.
5984 gtk_icon_view_select_all (GtkIconView *icon_view)
5987 gboolean dirty = FALSE;
5989 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
5991 if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
5994 for (items = icon_view->priv->items; items; items = items->next)
5996 GtkIconViewItem *item = items->data;
5998 if (!item->selected)
6001 item->selected = TRUE;
6002 gtk_icon_view_queue_draw_item (icon_view, item);
6007 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
6011 * gtk_icon_view_unselect_all:
6012 * @icon_view: A #GtkIconView.
6014 * Unselects all the icons.
6019 gtk_icon_view_unselect_all (GtkIconView *icon_view)
6021 gboolean dirty = FALSE;
6023 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6025 if (icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
6028 dirty = gtk_icon_view_unselect_all_internal (icon_view);
6031 g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
6035 * gtk_icon_view_path_is_selected:
6036 * @icon_view: A #GtkIconView.
6037 * @path: A #GtkTreePath to check selection on.
6039 * Returns %TRUE if the icon pointed to by @path is currently
6040 * selected. If @path does not point to a valid location, %FALSE is returned.
6042 * Return value: %TRUE if @path is selected.
6047 gtk_icon_view_path_is_selected (GtkIconView *icon_view,
6050 GtkIconViewItem *item;
6052 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
6053 g_return_val_if_fail (icon_view->priv->model != NULL, FALSE);
6054 g_return_val_if_fail (path != NULL, FALSE);
6056 item = g_list_nth_data (icon_view->priv->items,
6057 gtk_tree_path_get_indices(path)[0]);
6062 return item->selected;
6066 * gtk_icon_view_get_item_row:
6067 * @icon_view: a #GtkIconView
6068 * @path: the #GtkTreePath of the item
6070 * Gets the row in which the item @path is currently
6071 * displayed. Row numbers start at 0.
6073 * Returns: The row in which the item is displayed
6078 gtk_icon_view_get_item_row (GtkIconView *icon_view,
6081 GtkIconViewItem *item;
6083 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6084 g_return_val_if_fail (icon_view->priv->model != NULL, -1);
6085 g_return_val_if_fail (path != NULL, -1);
6087 item = g_list_nth_data (icon_view->priv->items,
6088 gtk_tree_path_get_indices(path)[0]);
6097 * gtk_icon_view_get_item_column:
6098 * @icon_view: a #GtkIconView
6099 * @path: the #GtkTreePath of the item
6101 * Gets the column in which the item @path is currently
6102 * displayed. Column numbers start at 0.
6104 * Returns: The column in which the item is displayed
6109 gtk_icon_view_get_item_column (GtkIconView *icon_view,
6112 GtkIconViewItem *item;
6114 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6115 g_return_val_if_fail (icon_view->priv->model != NULL, -1);
6116 g_return_val_if_fail (path != NULL, -1);
6118 item = g_list_nth_data (icon_view->priv->items,
6119 gtk_tree_path_get_indices(path)[0]);
6128 * gtk_icon_view_item_activated:
6129 * @icon_view: A #GtkIconView
6130 * @path: The #GtkTreePath to be activated
6132 * Activates the item determined by @path.
6137 gtk_icon_view_item_activated (GtkIconView *icon_view,
6140 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6141 g_return_if_fail (path != NULL);
6143 g_signal_emit (icon_view, icon_view_signals[ITEM_ACTIVATED], 0, path);
6147 * gtk_icon_view_set_item_orientation:
6148 * @icon_view: a #GtkIconView
6149 * @orientation: the relative position of texts and icons
6151 * Sets the ::item-orientation property which determines whether the labels
6152 * are drawn beside the icons instead of below.
6157 gtk_icon_view_set_item_orientation (GtkIconView *icon_view,
6158 GtkOrientation orientation)
6160 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6162 if (icon_view->priv->item_orientation != orientation)
6164 icon_view->priv->item_orientation = orientation;
6166 gtk_icon_view_stop_editing (icon_view, TRUE);
6167 gtk_icon_view_invalidate_sizes (icon_view);
6168 gtk_icon_view_queue_layout (icon_view);
6170 update_text_cell (icon_view);
6171 update_pixbuf_cell (icon_view);
6173 g_object_notify (G_OBJECT (icon_view), "item-orientation");
6178 * gtk_icon_view_get_item_orientation:
6179 * @icon_view: a #GtkIconView
6181 * Returns the value of the ::item-orientation property which determines
6182 * whether the labels are drawn beside the icons instead of below.
6184 * Return value: the relative position of texts and icons
6189 gtk_icon_view_get_item_orientation (GtkIconView *icon_view)
6191 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view),
6192 GTK_ORIENTATION_VERTICAL);
6194 return icon_view->priv->item_orientation;
6198 * gtk_icon_view_set_columns:
6199 * @icon_view: a #GtkIconView
6200 * @columns: the number of columns
6202 * Sets the ::columns property which determines in how
6203 * many columns the icons are arranged. If @columns is
6204 * -1, the number of columns will be chosen automatically
6205 * to fill the available area.
6210 gtk_icon_view_set_columns (GtkIconView *icon_view,
6213 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6215 if (icon_view->priv->columns != columns)
6217 icon_view->priv->columns = columns;
6219 gtk_icon_view_stop_editing (icon_view, TRUE);
6220 gtk_icon_view_queue_layout (icon_view);
6222 g_object_notify (G_OBJECT (icon_view), "columns");
6227 * gtk_icon_view_get_columns:
6228 * @icon_view: a #GtkIconView
6230 * Returns the value of the ::columns property.
6232 * Return value: the number of columns, or -1
6237 gtk_icon_view_get_columns (GtkIconView *icon_view)
6239 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6241 return icon_view->priv->columns;
6245 * gtk_icon_view_set_item_width:
6246 * @icon_view: a #GtkIconView
6247 * @item_width: the width for each item
6249 * Sets the ::item-width property which specifies the width
6250 * to use for each item. If it is set to -1, the icon view will
6251 * automatically determine a suitable item size.
6256 gtk_icon_view_set_item_width (GtkIconView *icon_view,
6259 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6261 if (icon_view->priv->item_width != item_width)
6263 icon_view->priv->item_width = item_width;
6265 gtk_icon_view_stop_editing (icon_view, TRUE);
6266 gtk_icon_view_invalidate_sizes (icon_view);
6267 gtk_icon_view_queue_layout (icon_view);
6269 update_text_cell (icon_view);
6271 g_object_notify (G_OBJECT (icon_view), "item-width");
6276 * gtk_icon_view_get_item_width:
6277 * @icon_view: a #GtkIconView
6279 * Returns the value of the ::item-width property.
6281 * Return value: the width of a single item, or -1
6286 gtk_icon_view_get_item_width (GtkIconView *icon_view)
6288 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6290 return icon_view->priv->item_width;
6295 * gtk_icon_view_set_spacing:
6296 * @icon_view: a #GtkIconView
6297 * @spacing: the spacing
6299 * Sets the ::spacing property which specifies the space
6300 * which is inserted between the cells (i.e. the icon and
6301 * the text) of an item.
6306 gtk_icon_view_set_spacing (GtkIconView *icon_view,
6309 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6311 if (icon_view->priv->spacing != spacing)
6313 icon_view->priv->spacing = spacing;
6315 gtk_icon_view_stop_editing (icon_view, TRUE);
6316 gtk_icon_view_invalidate_sizes (icon_view);
6317 gtk_icon_view_queue_layout (icon_view);
6319 g_object_notify (G_OBJECT (icon_view), "spacing");
6324 * gtk_icon_view_get_spacing:
6325 * @icon_view: a #GtkIconView
6327 * Returns the value of the ::spacing property.
6329 * Return value: the space between cells
6334 gtk_icon_view_get_spacing (GtkIconView *icon_view)
6336 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6338 return icon_view->priv->spacing;
6342 * gtk_icon_view_set_row_spacing:
6343 * @icon_view: a #GtkIconView
6344 * @row_spacing: the row spacing
6346 * Sets the ::row-spacing property which specifies the space
6347 * which is inserted between the rows of the icon view.
6352 gtk_icon_view_set_row_spacing (GtkIconView *icon_view,
6355 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6357 if (icon_view->priv->row_spacing != row_spacing)
6359 icon_view->priv->row_spacing = row_spacing;
6361 gtk_icon_view_stop_editing (icon_view, TRUE);
6362 gtk_icon_view_invalidate_sizes (icon_view);
6363 gtk_icon_view_queue_layout (icon_view);
6365 g_object_notify (G_OBJECT (icon_view), "row-spacing");
6370 * gtk_icon_view_get_row_spacing:
6371 * @icon_view: a #GtkIconView
6373 * Returns the value of the ::row-spacing property.
6375 * Return value: the space between rows
6380 gtk_icon_view_get_row_spacing (GtkIconView *icon_view)
6382 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6384 return icon_view->priv->row_spacing;
6388 * gtk_icon_view_set_column_spacing:
6389 * @icon_view: a #GtkIconView
6390 * @column_spacing: the column spacing
6392 * Sets the ::column-spacing property which specifies the space
6393 * which is inserted between the columns of the icon view.
6398 gtk_icon_view_set_column_spacing (GtkIconView *icon_view,
6399 gint column_spacing)
6401 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6403 if (icon_view->priv->column_spacing != column_spacing)
6405 icon_view->priv->column_spacing = column_spacing;
6407 gtk_icon_view_stop_editing (icon_view, TRUE);
6408 gtk_icon_view_invalidate_sizes (icon_view);
6409 gtk_icon_view_queue_layout (icon_view);
6411 g_object_notify (G_OBJECT (icon_view), "column-spacing");
6416 * gtk_icon_view_get_column_spacing:
6417 * @icon_view: a #GtkIconView
6419 * Returns the value of the ::column-spacing property.
6421 * Return value: the space between columns
6426 gtk_icon_view_get_column_spacing (GtkIconView *icon_view)
6428 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6430 return icon_view->priv->column_spacing;
6434 * gtk_icon_view_set_margin:
6435 * @icon_view: a #GtkIconView
6436 * @margin: the margin
6438 * Sets the ::margin property which specifies the space
6439 * which is inserted at the top, bottom, left and right
6445 gtk_icon_view_set_margin (GtkIconView *icon_view,
6448 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6450 if (icon_view->priv->margin != margin)
6452 icon_view->priv->margin = margin;
6454 gtk_icon_view_stop_editing (icon_view, TRUE);
6455 gtk_icon_view_invalidate_sizes (icon_view);
6456 gtk_icon_view_queue_layout (icon_view);
6458 g_object_notify (G_OBJECT (icon_view), "margin");
6463 * gtk_icon_view_get_margin:
6464 * @icon_view: a #GtkIconView
6466 * Returns the value of the ::margin property.
6468 * Return value: the space at the borders
6473 gtk_icon_view_get_margin (GtkIconView *icon_view)
6475 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6477 return icon_view->priv->margin;
6481 * gtk_icon_view_set_item_padding:
6482 * @icon_view: a #GtkIconView
6483 * @item_padding: the item padding
6485 * Sets the #GtkIconView:item-padding property which specifies the padding
6486 * around each of the icon view's items.
6491 gtk_icon_view_set_item_padding (GtkIconView *icon_view,
6494 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
6496 if (icon_view->priv->item_padding != item_padding)
6498 icon_view->priv->item_padding = item_padding;
6500 gtk_icon_view_stop_editing (icon_view, TRUE);
6501 gtk_icon_view_invalidate_sizes (icon_view);
6502 gtk_icon_view_queue_layout (icon_view);
6504 g_object_notify (G_OBJECT (icon_view), "item-padding");
6509 * gtk_icon_view_get_item_padding:
6510 * @icon_view: a #GtkIconView
6512 * Returns the value of the ::item-padding property.
6514 * Return value: the padding around items
6519 gtk_icon_view_get_item_padding (GtkIconView *icon_view)
6521 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
6523 return icon_view->priv->item_padding;
6526 /* Get/set whether drag_motion requested the drag data and
6527 * drag_data_received should thus not actually insert the data,
6528 * since the data doesn't result from a drop.
6531 set_status_pending (GdkDragContext *context,
6532 GdkDragAction suggested_action)
6534 g_object_set_data (G_OBJECT (context),
6535 I_("gtk-icon-view-status-pending"),
6536 GINT_TO_POINTER (suggested_action));
6539 static GdkDragAction
6540 get_status_pending (GdkDragContext *context)
6542 return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
6543 "gtk-icon-view-status-pending"));
6547 unset_reorderable (GtkIconView *icon_view)
6549 if (icon_view->priv->reorderable)
6551 icon_view->priv->reorderable = FALSE;
6552 g_object_notify (G_OBJECT (icon_view), "reorderable");
6557 set_source_row (GdkDragContext *context,
6558 GtkTreeModel *model,
6559 GtkTreePath *source_row)
6562 g_object_set_data_full (G_OBJECT (context),
6563 I_("gtk-icon-view-source-row"),
6564 gtk_tree_row_reference_new (model, source_row),
6565 (GDestroyNotify) gtk_tree_row_reference_free);
6567 g_object_set_data_full (G_OBJECT (context),
6568 I_("gtk-icon-view-source-row"),
6573 get_source_row (GdkDragContext *context)
6575 GtkTreeRowReference *ref;
6577 ref = g_object_get_data (G_OBJECT (context), "gtk-icon-view-source-row");
6580 return gtk_tree_row_reference_get_path (ref);
6587 GtkTreeRowReference *dest_row;
6588 gboolean empty_view_drop;
6589 gboolean drop_append_mode;
6593 dest_row_free (gpointer data)
6595 DestRow *dr = (DestRow *)data;
6597 gtk_tree_row_reference_free (dr->dest_row);
6602 set_dest_row (GdkDragContext *context,
6603 GtkTreeModel *model,
6604 GtkTreePath *dest_row,
6605 gboolean empty_view_drop,
6606 gboolean drop_append_mode)
6612 g_object_set_data_full (G_OBJECT (context),
6613 I_("gtk-icon-view-dest-row"),
6618 dr = g_new0 (DestRow, 1);
6620 dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
6621 dr->empty_view_drop = empty_view_drop;
6622 dr->drop_append_mode = drop_append_mode;
6623 g_object_set_data_full (G_OBJECT (context),
6624 I_("gtk-icon-view-dest-row"),
6625 dr, (GDestroyNotify) dest_row_free);
6629 get_dest_row (GdkDragContext *context)
6633 dr = g_object_get_data (G_OBJECT (context), "gtk-icon-view-dest-row");
6637 GtkTreePath *path = NULL;
6640 path = gtk_tree_row_reference_get_path (dr->dest_row);
6641 else if (dr->empty_view_drop)
6642 path = gtk_tree_path_new_from_indices (0, -1);
6646 if (path && dr->drop_append_mode)
6647 gtk_tree_path_next (path);
6656 check_model_dnd (GtkTreeModel *model,
6657 GType required_iface,
6658 const gchar *signal)
6660 if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
6662 g_warning ("You must override the default '%s' handler "
6663 "on GtkIconView when using models that don't support "
6664 "the %s interface and enabling drag-and-drop. The simplest way to do this "
6665 "is to connect to '%s' and call "
6666 "g_signal_stop_emission_by_name() in your signal handler to prevent "
6667 "the default handler from running. Look at the source code "
6668 "for the default handler in gtkiconview.c to get an idea what "
6669 "your handler should do. (gtkiconview.c is in the GTK+ source "
6670 "code.) If you're using GTK+ from a language other than C, "
6671 "there may be a more natural way to override default handlers, e.g. via derivation.",
6672 signal, g_type_name (required_iface), signal);
6680 remove_scroll_timeout (GtkIconView *icon_view)
6682 if (icon_view->priv->scroll_timeout_id != 0)
6684 g_source_remove (icon_view->priv->scroll_timeout_id);
6686 icon_view->priv->scroll_timeout_id = 0;
6691 gtk_icon_view_autoscroll (GtkIconView *icon_view)
6694 gint px, py, x, y, width, height;
6695 gint hoffset, voffset;
6697 window = gtk_widget_get_window (GTK_WIDGET (icon_view));
6699 gdk_window_get_pointer (window, &px, &py, NULL);
6700 gdk_window_get_geometry (window, &x, &y, &width, &height, NULL);
6702 /* see if we are near the edge. */
6703 voffset = py - (y + 2 * SCROLL_EDGE_SIZE);
6705 voffset = MAX (py - (y + height - 2 * SCROLL_EDGE_SIZE), 0);
6707 hoffset = px - (x + 2 * SCROLL_EDGE_SIZE);
6709 hoffset = MAX (px - (x + width - 2 * SCROLL_EDGE_SIZE), 0);
6712 gtk_adjustment_set_value (icon_view->priv->vadjustment,
6713 icon_view->priv->vadjustment->value + voffset);
6716 gtk_adjustment_set_value (icon_view->priv->hadjustment,
6717 icon_view->priv->hadjustment->value + hoffset);
6722 drag_scroll_timeout (gpointer data)
6724 GtkIconView *icon_view = GTK_ICON_VIEW (data);
6726 gtk_icon_view_autoscroll (icon_view);
6733 set_destination (GtkIconView *icon_view,
6734 GdkDragContext *context,
6737 GdkDragAction *suggested_action,
6741 GtkTreePath *path = NULL;
6742 GtkIconViewDropPosition pos;
6743 GtkIconViewDropPosition old_pos;
6744 GtkTreePath *old_dest_path = NULL;
6745 gboolean can_drop = FALSE;
6747 widget = GTK_WIDGET (icon_view);
6749 *suggested_action = 0;
6752 if (!icon_view->priv->dest_set)
6754 /* someone unset us as a drag dest, note that if
6755 * we return FALSE drag_leave isn't called
6758 gtk_icon_view_set_drag_dest_item (icon_view,
6760 GTK_ICON_VIEW_DROP_LEFT);
6762 remove_scroll_timeout (GTK_ICON_VIEW (widget));
6764 return FALSE; /* no longer a drop site */
6767 *target = gtk_drag_dest_find_target (widget, context,
6768 gtk_drag_dest_get_target_list (widget));
6769 if (*target == GDK_NONE)
6772 if (!gtk_icon_view_get_dest_item_at_pos (icon_view, x, y, &path, &pos))
6775 GtkTreeModel *model;
6777 /* the row got dropped on empty space, let's setup a special case
6781 gtk_tree_path_free (path);
6783 model = gtk_icon_view_get_model (icon_view);
6785 n_children = gtk_tree_model_iter_n_children (model, NULL);
6788 pos = GTK_ICON_VIEW_DROP_BELOW;
6789 path = gtk_tree_path_new_from_indices (n_children - 1, -1);
6793 pos = GTK_ICON_VIEW_DROP_ABOVE;
6794 path = gtk_tree_path_new_from_indices (0, -1);
6804 gtk_icon_view_get_drag_dest_item (icon_view,
6809 gtk_tree_path_free (old_dest_path);
6811 if (TRUE /* FIXME if the location droppable predicate */)
6819 GtkWidget *source_widget;
6821 *suggested_action = context->suggested_action;
6822 source_widget = gtk_drag_get_source_widget (context);
6824 if (source_widget == widget)
6826 /* Default to MOVE, unless the user has
6827 * pressed ctrl or shift to affect available actions
6829 if ((context->actions & GDK_ACTION_MOVE) != 0)
6830 *suggested_action = GDK_ACTION_MOVE;
6833 gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (widget),
6838 /* can't drop here */
6839 gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (widget),
6841 GTK_ICON_VIEW_DROP_LEFT);
6845 gtk_tree_path_free (path);
6851 get_logical_destination (GtkIconView *icon_view,
6852 gboolean *drop_append_mode)
6854 /* adjust path to point to the row the drop goes in front of */
6855 GtkTreePath *path = NULL;
6856 GtkIconViewDropPosition pos;
6858 *drop_append_mode = FALSE;
6860 gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
6865 if (pos == GTK_ICON_VIEW_DROP_RIGHT ||
6866 pos == GTK_ICON_VIEW_DROP_BELOW)
6869 GtkTreeModel *model = icon_view->priv->model;
6871 if (!gtk_tree_model_get_iter (model, &iter, path) ||
6872 !gtk_tree_model_iter_next (model, &iter))
6873 *drop_append_mode = TRUE;
6876 *drop_append_mode = FALSE;
6877 gtk_tree_path_next (path);
6885 gtk_icon_view_maybe_begin_drag (GtkIconView *icon_view,
6886 GdkEventMotion *event)
6888 GtkWidget *widget = GTK_WIDGET (icon_view);
6889 GdkDragContext *context;
6890 GtkTreePath *path = NULL;
6892 GtkTreeModel *model;
6893 gboolean retval = FALSE;
6895 if (!icon_view->priv->source_set)
6898 if (icon_view->priv->pressed_button < 0)
6901 if (!gtk_drag_check_threshold (GTK_WIDGET (icon_view),
6902 icon_view->priv->press_start_x,
6903 icon_view->priv->press_start_y,
6904 event->x, event->y))
6907 model = gtk_icon_view_get_model (icon_view);
6912 button = icon_view->priv->pressed_button;
6913 icon_view->priv->pressed_button = -1;
6915 path = gtk_icon_view_get_path_at_pos (icon_view,
6916 icon_view->priv->press_start_x,
6917 icon_view->priv->press_start_y);
6922 if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
6923 !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
6927 /* FIXME Check whether we're a start button, if not return FALSE and
6931 /* Now we can begin the drag */
6935 context = gtk_drag_begin (widget,
6936 gtk_drag_source_get_target_list (widget),
6937 icon_view->priv->source_actions,
6941 set_source_row (context, model, path);
6945 gtk_tree_path_free (path);
6950 /* Source side drag signals */
6952 gtk_icon_view_drag_begin (GtkWidget *widget,
6953 GdkDragContext *context)
6955 GtkIconView *icon_view;
6956 GtkIconViewItem *item;
6957 cairo_surface_t *icon;
6961 icon_view = GTK_ICON_VIEW (widget);
6963 /* if the user uses a custom DnD impl, we don't set the icon here */
6964 if (!icon_view->priv->dest_set && !icon_view->priv->source_set)
6967 item = gtk_icon_view_get_item_at_coords (icon_view,
6968 icon_view->priv->press_start_x,
6969 icon_view->priv->press_start_y,
6973 g_return_if_fail (item != NULL);
6975 x = icon_view->priv->press_start_x - item->x + 1;
6976 y = icon_view->priv->press_start_y - item->y + 1;
6978 path = gtk_tree_path_new_from_indices (item->index, -1);
6979 icon = gtk_icon_view_create_drag_icon (icon_view, path);
6980 gtk_tree_path_free (path);
6982 cairo_surface_set_device_offset (icon, -x, -y);
6984 gtk_drag_set_icon_surface (context, icon);
6986 cairo_surface_destroy (icon);
6990 gtk_icon_view_drag_end (GtkWidget *widget,
6991 GdkDragContext *context)
6997 gtk_icon_view_drag_data_get (GtkWidget *widget,
6998 GdkDragContext *context,
6999 GtkSelectionData *selection_data,
7003 GtkIconView *icon_view;
7004 GtkTreeModel *model;
7005 GtkTreePath *source_row;
7007 icon_view = GTK_ICON_VIEW (widget);
7008 model = gtk_icon_view_get_model (icon_view);
7013 if (!icon_view->priv->source_set)
7016 source_row = get_source_row (context);
7018 if (source_row == NULL)
7021 /* We can implement the GTK_TREE_MODEL_ROW target generically for
7022 * any model; for DragSource models there are some other targets
7026 if (GTK_IS_TREE_DRAG_SOURCE (model) &&
7027 gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
7032 /* If drag_data_get does nothing, try providing row data. */
7033 if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
7034 gtk_tree_set_row_drag_data (selection_data,
7039 gtk_tree_path_free (source_row);
7043 gtk_icon_view_drag_data_delete (GtkWidget *widget,
7044 GdkDragContext *context)
7046 GtkTreeModel *model;
7047 GtkIconView *icon_view;
7048 GtkTreePath *source_row;
7050 icon_view = GTK_ICON_VIEW (widget);
7051 model = gtk_icon_view_get_model (icon_view);
7053 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag-data-delete"))
7056 if (!icon_view->priv->source_set)
7059 source_row = get_source_row (context);
7061 if (source_row == NULL)
7064 gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
7067 gtk_tree_path_free (source_row);
7069 set_source_row (context, NULL, NULL);
7072 /* Target side drag signals */
7074 gtk_icon_view_drag_leave (GtkWidget *widget,
7075 GdkDragContext *context,
7078 GtkIconView *icon_view;
7080 icon_view = GTK_ICON_VIEW (widget);
7082 /* unset any highlight row */
7083 gtk_icon_view_set_drag_dest_item (icon_view,
7085 GTK_ICON_VIEW_DROP_LEFT);
7087 remove_scroll_timeout (icon_view);
7091 gtk_icon_view_drag_motion (GtkWidget *widget,
7092 GdkDragContext *context,
7097 GtkTreePath *path = NULL;
7098 GtkIconViewDropPosition pos;
7099 GtkIconView *icon_view;
7100 GdkDragAction suggested_action = 0;
7104 icon_view = GTK_ICON_VIEW (widget);
7106 if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
7109 gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
7111 /* we only know this *after* set_desination_row */
7112 empty = icon_view->priv->empty_view_drop;
7114 if (path == NULL && !empty)
7116 /* Can't drop here. */
7117 gdk_drag_status (context, 0, time);
7121 if (icon_view->priv->scroll_timeout_id == 0)
7123 icon_view->priv->scroll_timeout_id =
7124 gdk_threads_add_timeout (50, drag_scroll_timeout, icon_view);
7127 if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
7129 /* Request data so we can use the source row when
7130 * determining whether to accept the drop
7132 set_status_pending (context, suggested_action);
7133 gtk_drag_get_data (widget, context, target, time);
7137 set_status_pending (context, 0);
7138 gdk_drag_status (context, suggested_action, time);
7143 gtk_tree_path_free (path);
7149 gtk_icon_view_drag_drop (GtkWidget *widget,
7150 GdkDragContext *context,
7155 GtkIconView *icon_view;
7157 GdkDragAction suggested_action = 0;
7158 GdkAtom target = GDK_NONE;
7159 GtkTreeModel *model;
7160 gboolean drop_append_mode;
7162 icon_view = GTK_ICON_VIEW (widget);
7163 model = gtk_icon_view_get_model (icon_view);
7165 remove_scroll_timeout (GTK_ICON_VIEW (widget));
7167 if (!icon_view->priv->dest_set)
7170 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-drop"))
7173 if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
7176 path = get_logical_destination (icon_view, &drop_append_mode);
7178 if (target != GDK_NONE && path != NULL)
7180 /* in case a motion had requested drag data, change things so we
7181 * treat drag data receives as a drop.
7183 set_status_pending (context, 0);
7184 set_dest_row (context, model, path,
7185 icon_view->priv->empty_view_drop, drop_append_mode);
7189 gtk_tree_path_free (path);
7191 /* Unset this thing */
7192 gtk_icon_view_set_drag_dest_item (icon_view, NULL, GTK_ICON_VIEW_DROP_LEFT);
7194 if (target != GDK_NONE)
7196 gtk_drag_get_data (widget, context, target, time);
7204 gtk_icon_view_drag_data_received (GtkWidget *widget,
7205 GdkDragContext *context,
7208 GtkSelectionData *selection_data,
7213 gboolean accepted = FALSE;
7214 GtkTreeModel *model;
7215 GtkIconView *icon_view;
7216 GtkTreePath *dest_row;
7217 GdkDragAction suggested_action;
7218 gboolean drop_append_mode;
7220 icon_view = GTK_ICON_VIEW (widget);
7221 model = gtk_icon_view_get_model (icon_view);
7223 if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-data-received"))
7226 if (!icon_view->priv->dest_set)
7229 suggested_action = get_status_pending (context);
7231 if (suggested_action)
7233 /* We are getting this data due to a request in drag_motion,
7234 * rather than due to a request in drag_drop, so we are just
7235 * supposed to call drag_status, not actually paste in the
7238 path = get_logical_destination (icon_view, &drop_append_mode);
7241 suggested_action = 0;
7243 if (suggested_action)
7245 if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
7248 suggested_action = 0;
7251 gdk_drag_status (context, suggested_action, time);
7254 gtk_tree_path_free (path);
7256 /* If you can't drop, remove user drop indicator until the next motion */
7257 if (suggested_action == 0)
7258 gtk_icon_view_set_drag_dest_item (icon_view,
7260 GTK_ICON_VIEW_DROP_LEFT);
7265 dest_row = get_dest_row (context);
7267 if (dest_row == NULL)
7270 if (selection_data->length >= 0)
7272 if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
7278 gtk_drag_finish (context,
7280 (context->action == GDK_ACTION_MOVE),
7283 gtk_tree_path_free (dest_row);
7286 set_dest_row (context, NULL, NULL, FALSE, FALSE);
7289 /* Drag-and-Drop support */
7291 * gtk_icon_view_enable_model_drag_source:
7292 * @icon_view: a #GtkIconTreeView
7293 * @start_button_mask: Mask of allowed buttons to start drag
7294 * @targets: the table of targets that the drag will support
7295 * @n_targets: the number of items in @targets
7296 * @actions: the bitmask of possible actions for a drag from this
7299 * Turns @icon_view into a drag source for automatic DND. Calling this
7300 * method sets #GtkIconView:reorderable to %FALSE.
7305 gtk_icon_view_enable_model_drag_source (GtkIconView *icon_view,
7306 GdkModifierType start_button_mask,
7307 const GtkTargetEntry *targets,
7309 GdkDragAction actions)
7311 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7313 gtk_drag_source_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions);
7315 icon_view->priv->start_button_mask = start_button_mask;
7316 icon_view->priv->source_actions = actions;
7318 icon_view->priv->source_set = TRUE;
7320 unset_reorderable (icon_view);
7324 * gtk_icon_view_enable_model_drag_dest:
7325 * @icon_view: a #GtkIconView
7326 * @targets: the table of targets that the drag will support
7327 * @n_targets: the number of items in @targets
7328 * @actions: the bitmask of possible actions for a drag to this
7331 * Turns @icon_view into a drop destination for automatic DND. Calling this
7332 * method sets #GtkIconView:reorderable to %FALSE.
7337 gtk_icon_view_enable_model_drag_dest (GtkIconView *icon_view,
7338 const GtkTargetEntry *targets,
7340 GdkDragAction actions)
7342 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7344 gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions);
7346 icon_view->priv->dest_actions = actions;
7348 icon_view->priv->dest_set = TRUE;
7350 unset_reorderable (icon_view);
7354 * gtk_icon_view_unset_model_drag_source:
7355 * @icon_view: a #GtkIconView
7357 * Undoes the effect of gtk_icon_view_enable_model_drag_source(). Calling this
7358 * method sets #GtkIconView:reorderable to %FALSE.
7363 gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view)
7365 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7367 if (icon_view->priv->source_set)
7369 gtk_drag_source_unset (GTK_WIDGET (icon_view));
7370 icon_view->priv->source_set = FALSE;
7373 unset_reorderable (icon_view);
7377 * gtk_icon_view_unset_model_drag_dest:
7378 * @icon_view: a #GtkIconView
7380 * Undoes the effect of gtk_icon_view_enable_model_drag_dest(). Calling this
7381 * method sets #GtkIconView:reorderable to %FALSE.
7386 gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view)
7388 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7390 if (icon_view->priv->dest_set)
7392 gtk_drag_dest_unset (GTK_WIDGET (icon_view));
7393 icon_view->priv->dest_set = FALSE;
7396 unset_reorderable (icon_view);
7399 /* These are useful to implement your own custom stuff. */
7401 * gtk_icon_view_set_drag_dest_item:
7402 * @icon_view: a #GtkIconView
7403 * @path: (allow-none): The path of the item to highlight, or %NULL.
7404 * @pos: Specifies where to drop, relative to the item
7406 * Sets the item that is highlighted for feedback.
7411 gtk_icon_view_set_drag_dest_item (GtkIconView *icon_view,
7413 GtkIconViewDropPosition pos)
7415 /* Note; this function is exported to allow a custom DND
7416 * implementation, so it can't touch TreeViewDragInfo
7419 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7421 if (icon_view->priv->dest_item)
7423 GtkTreePath *current_path;
7424 current_path = gtk_tree_row_reference_get_path (icon_view->priv->dest_item);
7425 gtk_tree_row_reference_free (icon_view->priv->dest_item);
7426 icon_view->priv->dest_item = NULL;
7428 gtk_icon_view_queue_draw_path (icon_view, current_path);
7429 gtk_tree_path_free (current_path);
7432 /* special case a drop on an empty model */
7433 icon_view->priv->empty_view_drop = FALSE;
7434 if (pos == GTK_ICON_VIEW_DROP_ABOVE && path
7435 && gtk_tree_path_get_depth (path) == 1
7436 && gtk_tree_path_get_indices (path)[0] == 0)
7440 n_children = gtk_tree_model_iter_n_children (icon_view->priv->model,
7443 if (n_children == 0)
7444 icon_view->priv->empty_view_drop = TRUE;
7447 icon_view->priv->dest_pos = pos;
7451 icon_view->priv->dest_item =
7452 gtk_tree_row_reference_new_proxy (G_OBJECT (icon_view),
7453 icon_view->priv->model, path);
7455 gtk_icon_view_queue_draw_path (icon_view, path);
7460 * gtk_icon_view_get_drag_dest_item:
7461 * @icon_view: a #GtkIconView
7462 * @path: (allow-none): Return location for the path of the highlighted item, or %NULL.
7463 * @pos: (allow-none): Return location for the drop position, or %NULL
7465 * Gets information about the item that is highlighted for feedback.
7470 gtk_icon_view_get_drag_dest_item (GtkIconView *icon_view,
7472 GtkIconViewDropPosition *pos)
7474 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7478 if (icon_view->priv->dest_item)
7479 *path = gtk_tree_row_reference_get_path (icon_view->priv->dest_item);
7485 *pos = icon_view->priv->dest_pos;
7489 * gtk_icon_view_get_dest_item_at_pos:
7490 * @icon_view: a #GtkIconView
7491 * @drag_x: the position to determine the destination item for
7492 * @drag_y: the position to determine the destination item for
7493 * @path: (allow-none): Return location for the path of the item, or %NULL.
7494 * @pos: (allow-none): Return location for the drop position, or %NULL
7496 * Determines the destination item for a given position.
7498 * Return value: whether there is an item at the given position.
7503 gtk_icon_view_get_dest_item_at_pos (GtkIconView *icon_view,
7507 GtkIconViewDropPosition *pos)
7509 GtkIconViewItem *item;
7511 /* Note; this function is exported to allow a custom DND
7512 * implementation, so it can't touch TreeViewDragInfo
7515 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
7516 g_return_val_if_fail (drag_x >= 0, FALSE);
7517 g_return_val_if_fail (drag_y >= 0, FALSE);
7518 g_return_val_if_fail (icon_view->priv->bin_window != NULL, FALSE);
7524 item = gtk_icon_view_get_item_at_coords (icon_view,
7525 drag_x + icon_view->priv->hadjustment->value,
7526 drag_y + icon_view->priv->vadjustment->value,
7533 *path = gtk_tree_path_new_from_indices (item->index, -1);
7537 if (drag_x < item->x + item->width / 4)
7538 *pos = GTK_ICON_VIEW_DROP_LEFT;
7539 else if (drag_x > item->x + item->width * 3 / 4)
7540 *pos = GTK_ICON_VIEW_DROP_RIGHT;
7541 else if (drag_y < item->y + item->height / 4)
7542 *pos = GTK_ICON_VIEW_DROP_ABOVE;
7543 else if (drag_y > item->y + item->height * 3 / 4)
7544 *pos = GTK_ICON_VIEW_DROP_BELOW;
7546 *pos = GTK_ICON_VIEW_DROP_INTO;
7553 * gtk_icon_view_create_drag_icon:
7554 * @icon_view: a #GtkIconView
7555 * @path: a #GtkTreePath in @icon_view
7557 * Creates a #cairo_surface_t representation of the item at @path.
7558 * This image is used for a drag icon.
7560 * Return value: (transfer full) a newly-allocated surface of the drag icon.
7565 gtk_icon_view_create_drag_icon (GtkIconView *icon_view,
7570 cairo_surface_t *surface;
7574 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
7575 g_return_val_if_fail (path != NULL, NULL);
7577 widget = GTK_WIDGET (icon_view);
7579 if (!gtk_widget_get_realized (widget))
7582 index = gtk_tree_path_get_indices (path)[0];
7584 for (l = icon_view->priv->items; l; l = l->next)
7586 GtkIconViewItem *item = l->data;
7588 if (index == item->index)
7590 surface = gdk_window_create_similar_surface (icon_view->priv->bin_window,
7591 CAIRO_CONTENT_COLOR,
7595 cr = cairo_create (surface);
7596 cairo_set_line_width (cr, 1.);
7598 gdk_cairo_set_source_color (cr, >k_widget_get_style (widget)->base[gtk_widget_get_state (widget)]);
7599 cairo_rectangle (cr, 0, 0, item->width + 2, item->height + 2);
7604 cairo_rectangle (cr, 0, 0, item->width, item->height);
7607 gtk_icon_view_paint_item (icon_view, cr, item, 1, 1, FALSE);
7611 cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
7612 cairo_rectangle (cr, 0.5, 0.5, item->width + 1, item->height + 1);
7625 * gtk_icon_view_get_reorderable:
7626 * @icon_view: a #GtkIconView
7628 * Retrieves whether the user can reorder the list via drag-and-drop.
7629 * See gtk_icon_view_set_reorderable().
7631 * Return value: %TRUE if the list can be reordered.
7636 gtk_icon_view_get_reorderable (GtkIconView *icon_view)
7638 g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
7640 return icon_view->priv->reorderable;
7643 static const GtkTargetEntry item_targets[] = {
7644 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
7649 * gtk_icon_view_set_reorderable:
7650 * @icon_view: A #GtkIconView.
7651 * @reorderable: %TRUE, if the list of items can be reordered.
7653 * This function is a convenience function to allow you to reorder models that
7654 * support the #GtkTreeDragSourceIface and the #GtkTreeDragDestIface. Both
7655 * #GtkTreeStore and #GtkListStore support these. If @reorderable is %TRUE, then
7656 * the user can reorder the model by dragging and dropping rows. The
7657 * developer can listen to these changes by connecting to the model's
7658 * row_inserted and row_deleted signals. The reordering is implemented by setting up
7659 * the icon view as a drag source and destination. Therefore, drag and
7660 * drop can not be used in a reorderable view for any other purpose.
7662 * This function does not give you any degree of control over the order -- any
7663 * reordering is allowed. If more control is needed, you should probably
7664 * handle drag and drop manually.
7669 gtk_icon_view_set_reorderable (GtkIconView *icon_view,
7670 gboolean reorderable)
7672 g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
7674 reorderable = reorderable != FALSE;
7676 if (icon_view->priv->reorderable == reorderable)
7681 gtk_icon_view_enable_model_drag_source (icon_view,
7684 G_N_ELEMENTS (item_targets),
7686 gtk_icon_view_enable_model_drag_dest (icon_view,
7688 G_N_ELEMENTS (item_targets),
7693 gtk_icon_view_unset_model_drag_source (icon_view);
7694 gtk_icon_view_unset_model_drag_dest (icon_view);
7697 icon_view->priv->reorderable = reorderable;
7699 g_object_notify (G_OBJECT (icon_view), "reorderable");
7703 /* Accessibility Support */
7705 static gpointer accessible_parent_class;
7706 static gpointer accessible_item_parent_class;
7707 static GQuark accessible_private_data_quark = 0;
7709 #define GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE (gtk_icon_view_item_accessible_get_type ())
7710 #define GTK_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, GtkIconViewItemAccessible))
7711 #define GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE))
7713 static GType gtk_icon_view_item_accessible_get_type (void);
7724 GtkIconViewItem *item;
7728 AtkStateSet *state_set;
7732 GtkTextBuffer *text_buffer;
7734 gchar *action_descriptions[LAST_ACTION];
7735 gchar *image_description;
7736 guint action_idle_handler;
7737 } GtkIconViewItemAccessible;
7739 static const gchar *const gtk_icon_view_item_accessible_action_names[] =
7745 static const gchar *const gtk_icon_view_item_accessible_action_descriptions[] =
7750 typedef struct _GtkIconViewItemAccessibleClass
7752 AtkObjectClass parent_class;
7754 } GtkIconViewItemAccessibleClass;
7756 static gboolean gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item);
7759 gtk_icon_view_item_accessible_idle_do_action (gpointer data)
7761 GtkIconViewItemAccessible *item;
7762 GtkIconView *icon_view;
7765 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (data);
7766 item->action_idle_handler = 0;
7768 if (item->widget != NULL)
7770 icon_view = GTK_ICON_VIEW (item->widget);
7771 path = gtk_tree_path_new_from_indices (item->item->index, -1);
7772 gtk_icon_view_item_activated (icon_view, path);
7773 gtk_tree_path_free (path);
7780 gtk_icon_view_item_accessible_action_do_action (AtkAction *action,
7783 GtkIconViewItemAccessible *item;
7785 if (i < 0 || i >= LAST_ACTION)
7788 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
7790 if (!GTK_IS_ICON_VIEW (item->widget))
7793 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
7798 case ACTION_ACTIVATE:
7799 if (!item->action_idle_handler)
7800 item->action_idle_handler = gdk_threads_add_idle (gtk_icon_view_item_accessible_idle_do_action, item);
7803 g_assert_not_reached ();
7811 gtk_icon_view_item_accessible_action_get_n_actions (AtkAction *action)
7816 static const gchar *
7817 gtk_icon_view_item_accessible_action_get_description (AtkAction *action,
7820 GtkIconViewItemAccessible *item;
7822 if (i < 0 || i >= LAST_ACTION)
7825 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
7827 if (item->action_descriptions[i])
7828 return item->action_descriptions[i];
7830 return gtk_icon_view_item_accessible_action_descriptions[i];
7833 static const gchar *
7834 gtk_icon_view_item_accessible_action_get_name (AtkAction *action,
7837 if (i < 0 || i >= LAST_ACTION)
7840 return gtk_icon_view_item_accessible_action_names[i];
7844 gtk_icon_view_item_accessible_action_set_description (AtkAction *action,
7846 const gchar *description)
7848 GtkIconViewItemAccessible *item;
7850 if (i < 0 || i >= LAST_ACTION)
7853 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
7855 g_free (item->action_descriptions[i]);
7857 item->action_descriptions[i] = g_strdup (description);
7863 atk_action_item_interface_init (AtkActionIface *iface)
7865 iface->do_action = gtk_icon_view_item_accessible_action_do_action;
7866 iface->get_n_actions = gtk_icon_view_item_accessible_action_get_n_actions;
7867 iface->get_description = gtk_icon_view_item_accessible_action_get_description;
7868 iface->get_name = gtk_icon_view_item_accessible_action_get_name;
7869 iface->set_description = gtk_icon_view_item_accessible_action_set_description;
7872 static const gchar *
7873 gtk_icon_view_item_accessible_image_get_image_description (AtkImage *image)
7875 GtkIconViewItemAccessible *item;
7877 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
7879 return item->image_description;
7883 gtk_icon_view_item_accessible_image_set_image_description (AtkImage *image,
7884 const gchar *description)
7886 GtkIconViewItemAccessible *item;
7888 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
7890 g_free (item->image_description);
7891 item->image_description = g_strdup (description);
7897 get_pixbuf_box (GtkIconView *icon_view,
7898 GtkIconViewItem *item,
7903 for (l = icon_view->priv->cell_list; l; l = l->next)
7905 GtkIconViewCellInfo *info = l->data;
7907 if (GTK_IS_CELL_RENDERER_PIXBUF (info->cell))
7909 gtk_icon_view_get_cell_box (icon_view, item, info, box);
7919 get_text (GtkIconView *icon_view,
7920 GtkIconViewItem *item)
7925 for (l = icon_view->priv->cell_list; l; l = l->next)
7927 GtkIconViewCellInfo *info = l->data;
7929 if (GTK_IS_CELL_RENDERER_TEXT (info->cell))
7931 g_object_get (info->cell, "text", &text, NULL);
7941 gtk_icon_view_item_accessible_image_get_image_size (AtkImage *image,
7945 GtkIconViewItemAccessible *item;
7948 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
7950 if (!GTK_IS_ICON_VIEW (item->widget))
7953 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
7956 if (get_pixbuf_box (GTK_ICON_VIEW (item->widget), item->item, &box))
7959 *height = box.height;
7964 gtk_icon_view_item_accessible_image_get_image_position (AtkImage *image,
7967 AtkCoordType coord_type)
7969 GtkIconViewItemAccessible *item;
7972 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
7974 if (!GTK_IS_ICON_VIEW (item->widget))
7977 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
7980 atk_component_get_position (ATK_COMPONENT (image), x, y, coord_type);
7982 if (get_pixbuf_box (GTK_ICON_VIEW (item->widget), item->item, &box))
7984 *x+= box.x - item->item->x;
7985 *y+= box.y - item->item->y;
7991 atk_image_item_interface_init (AtkImageIface *iface)
7993 iface->get_image_description = gtk_icon_view_item_accessible_image_get_image_description;
7994 iface->set_image_description = gtk_icon_view_item_accessible_image_set_image_description;
7995 iface->get_image_size = gtk_icon_view_item_accessible_image_get_image_size;
7996 iface->get_image_position = gtk_icon_view_item_accessible_image_get_image_position;
8000 gtk_icon_view_item_accessible_text_get_text (AtkText *text,
8004 GtkIconViewItemAccessible *item;
8005 GtkTextIter start, end;
8006 GtkTextBuffer *buffer;
8008 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8010 if (!GTK_IS_ICON_VIEW (item->widget))
8013 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8016 buffer = item->text_buffer;
8017 gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
8019 gtk_text_buffer_get_end_iter (buffer, &end);
8021 gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
8023 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
8027 gtk_icon_view_item_accessible_text_get_character_at_offset (AtkText *text,
8030 GtkIconViewItemAccessible *item;
8031 GtkTextIter start, end;
8032 GtkTextBuffer *buffer;
8036 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8038 if (!GTK_IS_ICON_VIEW (item->widget))
8041 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8044 buffer = item->text_buffer;
8045 if (offset >= gtk_text_buffer_get_char_count (buffer))
8048 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
8050 gtk_text_iter_forward_char (&end);
8051 string = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
8052 unichar = g_utf8_get_char (string);
8060 get_pango_text_offsets (PangoLayout *layout,
8061 GtkTextBuffer *buffer,
8063 AtkTextBoundary boundary_type,
8067 GtkTextIter *start_iter,
8068 GtkTextIter *end_iter)
8070 PangoLayoutIter *iter;
8071 PangoLayoutLine *line, *prev_line = NULL, *prev_prev_line = NULL;
8072 gint index, start_index, end_index;
8074 gboolean found = FALSE;
8076 text = pango_layout_get_text (layout);
8077 index = g_utf8_offset_to_pointer (text, offset) - text;
8078 iter = pango_layout_get_iter (layout);
8081 line = pango_layout_iter_get_line_readonly (iter);
8082 start_index = line->start_index;
8083 end_index = start_index + line->length;
8085 if (index >= start_index && index <= end_index)
8088 * Found line for offset
8094 * We want the previous line
8098 switch (boundary_type)
8100 case ATK_TEXT_BOUNDARY_LINE_START:
8101 end_index = start_index;
8102 start_index = prev_line->start_index;
8104 case ATK_TEXT_BOUNDARY_LINE_END:
8106 start_index = prev_prev_line->start_index +
8107 prev_prev_line->length;
8108 end_index = prev_line->start_index + prev_line->length;
8111 g_assert_not_reached();
8115 start_index = end_index = 0;
8118 switch (boundary_type)
8120 case ATK_TEXT_BOUNDARY_LINE_START:
8121 if (pango_layout_iter_next_line (iter))
8122 end_index = pango_layout_iter_get_line_readonly (iter)->start_index;
8124 case ATK_TEXT_BOUNDARY_LINE_END:
8126 start_index = prev_line->start_index +
8130 g_assert_not_reached();
8135 * We want the next line
8137 if (pango_layout_iter_next_line (iter))
8139 line = pango_layout_iter_get_line_readonly (iter);
8140 switch (boundary_type)
8142 case ATK_TEXT_BOUNDARY_LINE_START:
8143 start_index = line->start_index;
8144 if (pango_layout_iter_next_line (iter))
8145 end_index = pango_layout_iter_get_line_readonly (iter)->start_index;
8147 end_index = start_index + line->length;
8149 case ATK_TEXT_BOUNDARY_LINE_END:
8150 start_index = end_index;
8151 end_index = line->start_index + line->length;
8154 g_assert_not_reached();
8158 start_index = end_index;
8164 prev_prev_line = prev_line;
8167 while (pango_layout_iter_next_line (iter));
8171 start_index = prev_line->start_index + prev_line->length;
8172 end_index = start_index;
8174 pango_layout_iter_free (iter);
8175 *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
8176 *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
8178 gtk_text_buffer_get_iter_at_offset (buffer, start_iter, *start_offset);
8179 gtk_text_buffer_get_iter_at_offset (buffer, end_iter, *end_offset);
8184 gtk_icon_view_item_accessible_text_get_text_before_offset (AtkText *text,
8186 AtkTextBoundary boundary_type,
8190 GtkIconViewItemAccessible *item;
8191 GtkTextIter start, end;
8192 GtkTextBuffer *buffer;
8194 GtkIconView *icon_view;
8197 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8199 if (!GTK_IS_ICON_VIEW (item->widget))
8202 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8205 buffer = item->text_buffer;
8207 if (!gtk_text_buffer_get_char_count (buffer))
8211 return g_strdup ("");
8213 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
8217 switch (boundary_type)
8219 case ATK_TEXT_BOUNDARY_CHAR:
8220 gtk_text_iter_backward_char(&start);
8222 case ATK_TEXT_BOUNDARY_WORD_START:
8223 if (!gtk_text_iter_starts_word (&start))
8224 gtk_text_iter_backward_word_start (&start);
8226 gtk_text_iter_backward_word_start(&start);
8228 case ATK_TEXT_BOUNDARY_WORD_END:
8229 if (gtk_text_iter_inside_word (&start) &&
8230 !gtk_text_iter_starts_word (&start))
8231 gtk_text_iter_backward_word_start (&start);
8232 while (!gtk_text_iter_ends_word (&start))
8234 if (!gtk_text_iter_backward_char (&start))
8238 gtk_text_iter_backward_word_start(&start);
8239 while (!gtk_text_iter_ends_word (&start))
8241 if (!gtk_text_iter_backward_char (&start))
8245 case ATK_TEXT_BOUNDARY_SENTENCE_START:
8246 if (!gtk_text_iter_starts_sentence (&start))
8247 gtk_text_iter_backward_sentence_start (&start);
8249 gtk_text_iter_backward_sentence_start (&start);
8251 case ATK_TEXT_BOUNDARY_SENTENCE_END:
8252 if (gtk_text_iter_inside_sentence (&start) &&
8253 !gtk_text_iter_starts_sentence (&start))
8254 gtk_text_iter_backward_sentence_start (&start);
8255 while (!gtk_text_iter_ends_sentence (&start))
8257 if (!gtk_text_iter_backward_char (&start))
8261 gtk_text_iter_backward_sentence_start (&start);
8262 while (!gtk_text_iter_ends_sentence (&start))
8264 if (!gtk_text_iter_backward_char (&start))
8268 case ATK_TEXT_BOUNDARY_LINE_START:
8269 case ATK_TEXT_BOUNDARY_LINE_END:
8271 icon_view = GTK_ICON_VIEW (item->widget);
8272 /* FIXME we probably have to use GailTextCell to salvage this */
8273 gtk_icon_view_update_item_text (icon_view, item->item);
8274 get_pango_text_offsets (icon_view->priv->layout,
8287 *start_offset = gtk_text_iter_get_offset (&start);
8288 *end_offset = gtk_text_iter_get_offset (&end);
8290 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
8294 gtk_icon_view_item_accessible_text_get_text_at_offset (AtkText *text,
8296 AtkTextBoundary boundary_type,
8300 GtkIconViewItemAccessible *item;
8301 GtkTextIter start, end;
8302 GtkTextBuffer *buffer;
8304 GtkIconView *icon_view;
8307 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8309 if (!GTK_IS_ICON_VIEW (item->widget))
8312 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8315 buffer = item->text_buffer;
8317 if (!gtk_text_buffer_get_char_count (buffer))
8321 return g_strdup ("");
8323 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
8327 switch (boundary_type)
8329 case ATK_TEXT_BOUNDARY_CHAR:
8330 gtk_text_iter_forward_char (&end);
8332 case ATK_TEXT_BOUNDARY_WORD_START:
8333 if (!gtk_text_iter_starts_word (&start))
8334 gtk_text_iter_backward_word_start (&start);
8335 if (gtk_text_iter_inside_word (&end))
8336 gtk_text_iter_forward_word_end (&end);
8337 while (!gtk_text_iter_starts_word (&end))
8339 if (!gtk_text_iter_forward_char (&end))
8343 case ATK_TEXT_BOUNDARY_WORD_END:
8344 if (gtk_text_iter_inside_word (&start) &&
8345 !gtk_text_iter_starts_word (&start))
8346 gtk_text_iter_backward_word_start (&start);
8347 while (!gtk_text_iter_ends_word (&start))
8349 if (!gtk_text_iter_backward_char (&start))
8352 gtk_text_iter_forward_word_end (&end);
8354 case ATK_TEXT_BOUNDARY_SENTENCE_START:
8355 if (!gtk_text_iter_starts_sentence (&start))
8356 gtk_text_iter_backward_sentence_start (&start);
8357 if (gtk_text_iter_inside_sentence (&end))
8358 gtk_text_iter_forward_sentence_end (&end);
8359 while (!gtk_text_iter_starts_sentence (&end))
8361 if (!gtk_text_iter_forward_char (&end))
8365 case ATK_TEXT_BOUNDARY_SENTENCE_END:
8366 if (gtk_text_iter_inside_sentence (&start) &&
8367 !gtk_text_iter_starts_sentence (&start))
8368 gtk_text_iter_backward_sentence_start (&start);
8369 while (!gtk_text_iter_ends_sentence (&start))
8371 if (!gtk_text_iter_backward_char (&start))
8374 gtk_text_iter_forward_sentence_end (&end);
8376 case ATK_TEXT_BOUNDARY_LINE_START:
8377 case ATK_TEXT_BOUNDARY_LINE_END:
8379 icon_view = GTK_ICON_VIEW (item->widget);
8380 /* FIXME we probably have to use GailTextCell to salvage this */
8381 gtk_icon_view_update_item_text (icon_view, item->item);
8382 get_pango_text_offsets (icon_view->priv->layout,
8396 *start_offset = gtk_text_iter_get_offset (&start);
8397 *end_offset = gtk_text_iter_get_offset (&end);
8399 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
8403 gtk_icon_view_item_accessible_text_get_text_after_offset (AtkText *text,
8405 AtkTextBoundary boundary_type,
8409 GtkIconViewItemAccessible *item;
8410 GtkTextIter start, end;
8411 GtkTextBuffer *buffer;
8413 GtkIconView *icon_view;
8416 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8418 if (!GTK_IS_ICON_VIEW (item->widget))
8421 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8424 buffer = item->text_buffer;
8426 if (!gtk_text_buffer_get_char_count (buffer))
8430 return g_strdup ("");
8432 gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
8436 switch (boundary_type)
8438 case ATK_TEXT_BOUNDARY_CHAR:
8439 gtk_text_iter_forward_char(&start);
8440 gtk_text_iter_forward_chars(&end, 2);
8442 case ATK_TEXT_BOUNDARY_WORD_START:
8443 if (gtk_text_iter_inside_word (&end))
8444 gtk_text_iter_forward_word_end (&end);
8445 while (!gtk_text_iter_starts_word (&end))
8447 if (!gtk_text_iter_forward_char (&end))
8451 if (!gtk_text_iter_is_end (&end))
8453 gtk_text_iter_forward_word_end (&end);
8454 while (!gtk_text_iter_starts_word (&end))
8456 if (!gtk_text_iter_forward_char (&end))
8461 case ATK_TEXT_BOUNDARY_WORD_END:
8462 gtk_text_iter_forward_word_end (&end);
8464 if (!gtk_text_iter_is_end (&end))
8465 gtk_text_iter_forward_word_end (&end);
8467 case ATK_TEXT_BOUNDARY_SENTENCE_START:
8468 if (gtk_text_iter_inside_sentence (&end))
8469 gtk_text_iter_forward_sentence_end (&end);
8470 while (!gtk_text_iter_starts_sentence (&end))
8472 if (!gtk_text_iter_forward_char (&end))
8476 if (!gtk_text_iter_is_end (&end))
8478 gtk_text_iter_forward_sentence_end (&end);
8479 while (!gtk_text_iter_starts_sentence (&end))
8481 if (!gtk_text_iter_forward_char (&end))
8486 case ATK_TEXT_BOUNDARY_SENTENCE_END:
8487 gtk_text_iter_forward_sentence_end (&end);
8489 if (!gtk_text_iter_is_end (&end))
8490 gtk_text_iter_forward_sentence_end (&end);
8492 case ATK_TEXT_BOUNDARY_LINE_START:
8493 case ATK_TEXT_BOUNDARY_LINE_END:
8495 icon_view = GTK_ICON_VIEW (item->widget);
8496 /* FIXME we probably have to use GailTextCell to salvage this */
8497 gtk_icon_view_update_item_text (icon_view, item->item);
8498 get_pango_text_offsets (icon_view->priv->layout,
8510 *start_offset = gtk_text_iter_get_offset (&start);
8511 *end_offset = gtk_text_iter_get_offset (&end);
8513 return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
8517 gtk_icon_view_item_accessible_text_get_character_count (AtkText *text)
8519 GtkIconViewItemAccessible *item;
8521 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8523 if (!GTK_IS_ICON_VIEW (item->widget))
8526 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8529 return gtk_text_buffer_get_char_count (item->text_buffer);
8533 gtk_icon_view_item_accessible_text_get_character_extents (AtkText *text,
8539 AtkCoordType coord_type)
8541 GtkIconViewItemAccessible *item;
8543 GtkIconView *icon_view;
8544 PangoRectangle char_rect;
8545 const gchar *item_text;
8549 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8551 if (!GTK_IS_ICON_VIEW (item->widget))
8554 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8558 icon_view = GTK_ICON_VIEW (item->widget);
8559 /* FIXME we probably have to use GailTextCell to salvage this */
8560 gtk_icon_view_update_item_text (icon_view, item->item);
8561 item_text = pango_layout_get_text (icon_view->priv->layout);
8562 index = g_utf8_offset_to_pointer (item_text, offset) - item_text;
8563 pango_layout_index_to_pos (icon_view->priv->layout, index, &char_rect);
8565 atk_component_get_position (ATK_COMPONENT (text), x, y, coord_type);
8566 *x += item->item->layout_x - item->item->x + char_rect.x / PANGO_SCALE;
8567 /* Look at gtk_icon_view_paint_item() to see where the text is. */
8568 *x -= ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
8569 *y += item->item->layout_y - item->item->y + char_rect.y / PANGO_SCALE;
8570 *width = char_rect.width / PANGO_SCALE;
8571 *height = char_rect.height / PANGO_SCALE;
8576 gtk_icon_view_item_accessible_text_get_offset_at_point (AtkText *text,
8579 AtkCoordType coord_type)
8581 GtkIconViewItemAccessible *item;
8584 GtkIconView *icon_view;
8585 const gchar *item_text;
8590 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
8592 if (!GTK_IS_ICON_VIEW (item->widget))
8595 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8599 icon_view = GTK_ICON_VIEW (item->widget);
8600 /* FIXME we probably have to use GailTextCell to salvage this */
8601 gtk_icon_view_update_item_text (icon_view, item->item);
8602 atk_component_get_position (ATK_COMPONENT (text), &l_x, &l_y, coord_type);
8603 x -= l_x + item->item->layout_x - item->item->x;
8604 x += ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
8605 y -= l_y + item->item->layout_y - item->item->y;
8606 item_text = pango_layout_get_text (icon_view->priv->layout);
8607 if (!pango_layout_xy_to_index (icon_view->priv->layout,
8618 offset = g_utf8_strlen (item_text, -1);
8620 offset = g_utf8_pointer_to_offset (item_text, item_text + index);
8626 atk_text_item_interface_init (AtkTextIface *iface)
8628 iface->get_text = gtk_icon_view_item_accessible_text_get_text;
8629 iface->get_character_at_offset = gtk_icon_view_item_accessible_text_get_character_at_offset;
8630 iface->get_text_before_offset = gtk_icon_view_item_accessible_text_get_text_before_offset;
8631 iface->get_text_at_offset = gtk_icon_view_item_accessible_text_get_text_at_offset;
8632 iface->get_text_after_offset = gtk_icon_view_item_accessible_text_get_text_after_offset;
8633 iface->get_character_count = gtk_icon_view_item_accessible_text_get_character_count;
8634 iface->get_character_extents = gtk_icon_view_item_accessible_text_get_character_extents;
8635 iface->get_offset_at_point = gtk_icon_view_item_accessible_text_get_offset_at_point;
8639 gtk_icon_view_item_accessible_get_extents (AtkComponent *component,
8644 AtkCoordType coord_type)
8646 GtkIconViewItemAccessible *item;
8647 AtkObject *parent_obj;
8650 g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component));
8652 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
8653 if (!GTK_IS_WIDGET (item->widget))
8656 if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
8659 *width = item->item->width;
8660 *height = item->item->height;
8661 if (gtk_icon_view_item_accessible_is_showing (item))
8663 parent_obj = gtk_widget_get_accessible (item->widget);
8664 atk_component_get_position (ATK_COMPONENT (parent_obj), &l_x, &l_y, coord_type);
8665 *x = l_x + item->item->x;
8666 *y = l_y + item->item->y;
8676 gtk_icon_view_item_accessible_grab_focus (AtkComponent *component)
8678 GtkIconViewItemAccessible *item;
8679 GtkWidget *toplevel;
8681 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component), FALSE);
8683 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
8684 if (!GTK_IS_WIDGET (item->widget))
8687 gtk_widget_grab_focus (item->widget);
8688 gtk_icon_view_set_cursor_item (GTK_ICON_VIEW (item->widget), item->item, -1);
8689 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->widget));
8690 if (gtk_widget_is_toplevel (toplevel))
8691 gtk_window_present (GTK_WINDOW (toplevel));
8697 atk_component_item_interface_init (AtkComponentIface *iface)
8699 iface->get_extents = gtk_icon_view_item_accessible_get_extents;
8700 iface->grab_focus = gtk_icon_view_item_accessible_grab_focus;
8704 gtk_icon_view_item_accessible_add_state (GtkIconViewItemAccessible *item,
8705 AtkStateType state_type,
8706 gboolean emit_signal)
8710 rc = atk_state_set_add_state (item->state_set, state_type);
8712 * The signal should only be generated if the value changed,
8713 * not when the item is set up. So states that are set
8714 * initially should pass FALSE as the emit_signal argument.
8719 atk_object_notify_state_change (ATK_OBJECT (item), state_type, TRUE);
8720 /* If state_type is ATK_STATE_VISIBLE, additional notification */
8721 if (state_type == ATK_STATE_VISIBLE)
8722 g_signal_emit_by_name (item, "visible-data-changed");
8729 gtk_icon_view_item_accessible_remove_state (GtkIconViewItemAccessible *item,
8730 AtkStateType state_type,
8731 gboolean emit_signal)
8733 if (atk_state_set_contains_state (item->state_set, state_type))
8737 rc = atk_state_set_remove_state (item->state_set, state_type);
8739 * The signal should only be generated if the value changed,
8740 * not when the item is set up. So states that are set
8741 * initially should pass FALSE as the emit_signal argument.
8746 atk_object_notify_state_change (ATK_OBJECT (item), state_type, FALSE);
8747 /* If state_type is ATK_STATE_VISIBLE, additional notification */
8748 if (state_type == ATK_STATE_VISIBLE)
8749 g_signal_emit_by_name (item, "visible-data-changed");
8759 gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item)
8761 GtkAllocation allocation;
8762 GtkIconView *icon_view;
8763 GdkRectangle visible_rect;
8764 gboolean is_showing;
8767 * An item is considered "SHOWING" if any part of the item is in the
8768 * visible rectangle.
8771 if (!GTK_IS_ICON_VIEW (item->widget))
8774 if (item->item == NULL)
8777 gtk_widget_get_allocation (item->widget, &allocation);
8779 icon_view = GTK_ICON_VIEW (item->widget);
8781 if (icon_view->priv->hadjustment)
8782 visible_rect.x += icon_view->priv->hadjustment->value;
8784 if (icon_view->priv->hadjustment)
8785 visible_rect.y += icon_view->priv->vadjustment->value;
8786 visible_rect.width = allocation.width;
8787 visible_rect.height = allocation.height;
8789 if (((item->item->x + item->item->width) < visible_rect.x) ||
8790 ((item->item->y + item->item->height) < (visible_rect.y)) ||
8791 (item->item->x > (visible_rect.x + visible_rect.width)) ||
8792 (item->item->y > (visible_rect.y + visible_rect.height)))
8801 gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
8802 gboolean emit_signal)
8804 if (gtk_icon_view_item_accessible_is_showing (item))
8805 return gtk_icon_view_item_accessible_add_state (item, ATK_STATE_SHOWING,
8808 return gtk_icon_view_item_accessible_remove_state (item, ATK_STATE_SHOWING,
8813 gtk_icon_view_item_accessible_object_init (GtkIconViewItemAccessible *item)
8817 item->state_set = atk_state_set_new ();
8819 atk_state_set_add_state (item->state_set, ATK_STATE_ENABLED);
8820 atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSABLE);
8821 atk_state_set_add_state (item->state_set, ATK_STATE_SENSITIVE);
8822 atk_state_set_add_state (item->state_set, ATK_STATE_SELECTABLE);
8823 atk_state_set_add_state (item->state_set, ATK_STATE_VISIBLE);
8825 for (i = 0; i < LAST_ACTION; i++)
8826 item->action_descriptions[i] = NULL;
8828 item->image_description = NULL;
8830 item->action_idle_handler = 0;
8834 gtk_icon_view_item_accessible_finalize (GObject *object)
8836 GtkIconViewItemAccessible *item;
8839 g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (object));
8841 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (object);
8844 g_object_remove_weak_pointer (G_OBJECT (item->widget), (gpointer) &item->widget);
8846 if (item->state_set)
8847 g_object_unref (item->state_set);
8849 if (item->text_buffer)
8850 g_object_unref (item->text_buffer);
8852 for (i = 0; i < LAST_ACTION; i++)
8853 g_free (item->action_descriptions[i]);
8855 g_free (item->image_description);
8857 if (item->action_idle_handler)
8859 g_source_remove (item->action_idle_handler);
8860 item->action_idle_handler = 0;
8863 G_OBJECT_CLASS (accessible_item_parent_class)->finalize (object);
8866 static G_CONST_RETURN gchar*
8867 gtk_icon_view_item_accessible_get_name (AtkObject *obj)
8873 GtkIconViewItemAccessible *item;
8874 GtkTextIter start_iter;
8875 GtkTextIter end_iter;
8877 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
8879 gtk_text_buffer_get_start_iter (item->text_buffer, &start_iter);
8880 gtk_text_buffer_get_end_iter (item->text_buffer, &end_iter);
8882 return gtk_text_buffer_get_text (item->text_buffer, &start_iter, &end_iter, FALSE);
8887 gtk_icon_view_item_accessible_get_parent (AtkObject *obj)
8889 GtkIconViewItemAccessible *item;
8891 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), NULL);
8892 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
8895 return gtk_widget_get_accessible (item->widget);
8901 gtk_icon_view_item_accessible_get_index_in_parent (AtkObject *obj)
8903 GtkIconViewItemAccessible *item;
8905 g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), 0);
8906 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
8908 return item->item->index;
8911 static AtkStateSet *
8912 gtk_icon_view_item_accessible_ref_state_set (AtkObject *obj)
8914 GtkIconViewItemAccessible *item;
8915 GtkIconView *icon_view;
8917 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
8918 g_return_val_if_fail (item->state_set, NULL);
8923 icon_view = GTK_ICON_VIEW (item->widget);
8924 if (icon_view->priv->cursor_item == item->item)
8925 atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSED);
8927 atk_state_set_remove_state (item->state_set, ATK_STATE_FOCUSED);
8928 if (item->item->selected)
8929 atk_state_set_add_state (item->state_set, ATK_STATE_SELECTED);
8931 atk_state_set_remove_state (item->state_set, ATK_STATE_SELECTED);
8933 return g_object_ref (item->state_set);
8937 gtk_icon_view_item_accessible_class_init (AtkObjectClass *klass)
8939 GObjectClass *gobject_class;
8941 accessible_item_parent_class = g_type_class_peek_parent (klass);
8943 gobject_class = (GObjectClass *)klass;
8945 gobject_class->finalize = gtk_icon_view_item_accessible_finalize;
8947 klass->get_index_in_parent = gtk_icon_view_item_accessible_get_index_in_parent;
8948 klass->get_name = gtk_icon_view_item_accessible_get_name;
8949 klass->get_parent = gtk_icon_view_item_accessible_get_parent;
8950 klass->ref_state_set = gtk_icon_view_item_accessible_ref_state_set;
8954 gtk_icon_view_item_accessible_get_type (void)
8956 static GType type = 0;
8960 const GTypeInfo tinfo =
8962 sizeof (GtkIconViewItemAccessibleClass),
8963 (GBaseInitFunc) NULL, /* base init */
8964 (GBaseFinalizeFunc) NULL, /* base finalize */
8965 (GClassInitFunc) gtk_icon_view_item_accessible_class_init, /* class init */
8966 (GClassFinalizeFunc) NULL, /* class finalize */
8967 NULL, /* class data */
8968 sizeof (GtkIconViewItemAccessible), /* instance size */
8969 0, /* nb preallocs */
8970 (GInstanceInitFunc) gtk_icon_view_item_accessible_object_init, /* instance init */
8971 NULL /* value table */
8974 const GInterfaceInfo atk_component_info =
8976 (GInterfaceInitFunc) atk_component_item_interface_init,
8977 (GInterfaceFinalizeFunc) NULL,
8980 const GInterfaceInfo atk_action_info =
8982 (GInterfaceInitFunc) atk_action_item_interface_init,
8983 (GInterfaceFinalizeFunc) NULL,
8986 const GInterfaceInfo atk_image_info =
8988 (GInterfaceInitFunc) atk_image_item_interface_init,
8989 (GInterfaceFinalizeFunc) NULL,
8992 const GInterfaceInfo atk_text_info =
8994 (GInterfaceInitFunc) atk_text_item_interface_init,
8995 (GInterfaceFinalizeFunc) NULL,
8999 type = g_type_register_static (ATK_TYPE_OBJECT,
9000 I_("GtkIconViewItemAccessible"), &tinfo, 0);
9001 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
9002 &atk_component_info);
9003 g_type_add_interface_static (type, ATK_TYPE_ACTION,
9005 g_type_add_interface_static (type, ATK_TYPE_IMAGE,
9007 g_type_add_interface_static (type, ATK_TYPE_TEXT,
9014 #define GTK_TYPE_ICON_VIEW_ACCESSIBLE (gtk_icon_view_accessible_get_type ())
9015 #define GTK_ICON_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE, GtkIconViewAccessible))
9016 #define GTK_IS_ICON_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE))
9018 static GType gtk_icon_view_accessible_get_type (void);
9023 } GtkIconViewAccessible;
9029 } GtkIconViewItemAccessibleInfo;
9035 GtkAdjustment *old_hadj;
9036 GtkAdjustment *old_vadj;
9038 GtkTreeModel *model;
9040 } GtkIconViewAccessiblePrivate;
9042 static GtkIconViewAccessiblePrivate *
9043 gtk_icon_view_accessible_get_priv (AtkObject *accessible)
9045 return g_object_get_qdata (G_OBJECT (accessible),
9046 accessible_private_data_quark);
9050 gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
9054 GtkIconViewItemAccessibleInfo *info;
9055 GtkIconViewItemAccessibleInfo *tmp_info;
9056 GtkIconViewAccessiblePrivate *priv;
9059 info = g_new (GtkIconViewItemAccessibleInfo, 1);
9061 info->index = index;
9063 priv = gtk_icon_view_accessible_get_priv (accessible);
9064 items = priv->items;
9067 tmp_info = items->data;
9068 if (tmp_info->index > index)
9070 items = items->next;
9072 priv->items = g_list_insert_before (priv->items, items, info);
9073 priv->old_hadj = NULL;
9074 priv->old_vadj = NULL;
9078 gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
9080 GtkIconView *icon_view;
9083 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
9087 icon_view = GTK_ICON_VIEW (widget);
9089 return g_list_length (icon_view->priv->items);
9093 gtk_icon_view_accessible_find_child (AtkObject *accessible,
9096 GtkIconViewAccessiblePrivate *priv;
9097 GtkIconViewItemAccessibleInfo *info;
9100 priv = gtk_icon_view_accessible_get_priv (accessible);
9101 items = priv->items;
9106 if (info->index == index)
9108 items = items->next;
9114 gtk_icon_view_accessible_ref_child (AtkObject *accessible,
9117 GtkIconView *icon_view;
9121 GtkIconViewItemAccessible *a11y_item;
9123 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
9127 icon_view = GTK_ICON_VIEW (widget);
9128 icons = g_list_nth (icon_view->priv->items, index);
9132 GtkIconViewItem *item = icons->data;
9134 g_return_val_if_fail (item->index == index, NULL);
9135 obj = gtk_icon_view_accessible_find_child (accessible, index);
9140 obj = g_object_new (gtk_icon_view_item_accessible_get_type (), NULL);
9141 gtk_icon_view_item_accessible_info_new (accessible,
9144 obj->role = ATK_ROLE_ICON;
9145 a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
9146 a11y_item->item = item;
9147 a11y_item->widget = widget;
9148 a11y_item->text_buffer = gtk_text_buffer_new (NULL);
9150 gtk_icon_view_set_cell_data (icon_view, item);
9151 text = get_text (icon_view, item);
9154 gtk_text_buffer_set_text (a11y_item->text_buffer, text, -1);
9158 gtk_icon_view_item_accessible_set_visibility (a11y_item, FALSE);
9159 g_object_add_weak_pointer (G_OBJECT (widget), (gpointer) &(a11y_item->widget));
9167 gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
9170 GtkIconViewAccessiblePrivate *priv;
9171 GtkIconViewItemAccessibleInfo *info;
9172 GtkIconViewItemAccessible *item;
9175 priv = gtk_icon_view_accessible_get_priv (ATK_OBJECT (view));
9179 gboolean act_on_item;
9181 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (view));
9185 items = priv->items;
9187 act_on_item = (list == NULL);
9192 info = (GtkIconViewItemAccessibleInfo *)items->data;
9193 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
9195 if (act_on_item == FALSE && list == items)
9199 gtk_icon_view_item_accessible_set_visibility (item, TRUE);
9201 items = items->next;
9207 gtk_icon_view_accessible_adjustment_changed (GtkAdjustment *adjustment,
9208 GtkIconView *icon_view)
9211 GtkIconViewAccessible *view;
9214 * The scrollbars have changed
9216 obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
9217 view = GTK_ICON_VIEW_ACCESSIBLE (obj);
9219 gtk_icon_view_accessible_traverse_items (view, NULL);
9223 gtk_icon_view_accessible_set_adjustment (GtkIconView *icon_view,
9224 GtkOrientation orientation,
9225 GtkAdjustment *adjustment)
9228 GtkIconViewAccessiblePrivate *priv;
9229 GtkAdjustment **old_adj_ptr;
9231 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
9232 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9234 /* Adjustments are set for the first time in constructor and priv is not
9235 * initialized at that time, so skip this first setting. */
9239 if (orientation == GTK_ORIENTATION_HORIZONTAL)
9241 if (priv->old_hadj == adjustment)
9244 old_adj_ptr = &priv->old_hadj;
9248 if (priv->old_vadj == adjustment)
9251 old_adj_ptr = &priv->old_vadj;
9254 /* Disconnect signal handlers */
9257 g_object_remove_weak_pointer (G_OBJECT (*old_adj_ptr),
9258 (gpointer *)&priv->old_hadj);
9259 g_signal_handlers_disconnect_by_func (*old_adj_ptr,
9260 gtk_icon_view_accessible_adjustment_changed,
9264 /* Connect signal */
9265 *old_adj_ptr = adjustment;
9266 g_object_add_weak_pointer (G_OBJECT (adjustment), (gpointer *)old_adj_ptr);
9267 g_signal_connect (adjustment, "value-changed",
9268 G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
9273 gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
9281 GtkIconView *icon_view;
9282 GtkIconViewItem *item;
9283 GtkIconViewAccessible *a11y_view;
9284 GtkIconViewItemAccessible *a11y_item;
9288 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
9289 a11y_view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
9290 index = gtk_tree_path_get_indices(path)[0];
9291 a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (
9292 gtk_icon_view_accessible_find_child (atk_obj, index));
9296 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_obj));
9297 icon_view = GTK_ICON_VIEW (widget);
9298 item = a11y_item->item;
9300 name = gtk_icon_view_item_accessible_get_name (ATK_OBJECT (a11y_item));
9302 if (!name || strcmp (name, "") == 0)
9304 gtk_icon_view_set_cell_data (icon_view, item);
9305 text = get_text (icon_view, item);
9308 gtk_text_buffer_set_text (a11y_item->text_buffer, text, -1);
9314 g_signal_emit_by_name (atk_obj, "visible-data-changed");
9320 gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
9325 GtkIconViewAccessiblePrivate *priv;
9326 GtkIconViewItemAccessibleInfo *info;
9327 GtkIconViewAccessible *view;
9328 GtkIconViewItemAccessible *item;
9334 index = gtk_tree_path_get_indices(path)[0];
9335 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
9336 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
9337 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9339 items = priv->items;
9344 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
9345 if (info->index != item->item->index)
9347 if (info->index < index)
9348 g_warning ("Unexpected index value on insertion %d %d", index, info->index);
9350 if (tmp_list == NULL)
9353 info->index = item->item->index;
9356 items = items->next;
9358 gtk_icon_view_accessible_traverse_items (view, tmp_list);
9359 g_signal_emit_by_name (atk_obj, "children-changed::add",
9365 gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
9369 GtkIconViewAccessiblePrivate *priv;
9370 GtkIconViewItemAccessibleInfo *info;
9371 GtkIconViewAccessible *view;
9372 GtkIconViewItemAccessible *item;
9375 GList *deleted_item;
9379 index = gtk_tree_path_get_indices(path)[0];
9380 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
9381 view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
9382 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9384 items = priv->items;
9386 deleted_item = NULL;
9391 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
9392 if (info->index == index)
9394 deleted_item = items;
9396 if (info->index != item->item->index)
9398 if (tmp_list == NULL)
9401 info->index = item->item->index;
9404 items = items->next;
9406 gtk_icon_view_accessible_traverse_items (view, tmp_list);
9409 info = deleted_item->data;
9410 gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
9411 g_signal_emit_by_name (atk_obj, "children-changed::remove",
9413 priv->items = g_list_remove_link (priv->items, deleted_item);
9421 gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
9422 GtkIconViewItemAccessibleInfo *i2)
9424 return i1->index - i2->index;
9428 gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
9434 GtkIconViewAccessiblePrivate *priv;
9435 GtkIconViewItemAccessibleInfo *info;
9436 GtkIconView *icon_view;
9437 GtkIconViewItemAccessible *item;
9443 atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
9444 icon_view = GTK_ICON_VIEW (user_data);
9445 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9447 length = gtk_tree_model_iter_n_children (tree_model, NULL);
9449 order = g_new (gint, length);
9450 for (i = 0; i < length; i++)
9451 order [new_order[i]] = i;
9453 items = priv->items;
9457 item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
9458 info->index = order[info->index];
9459 item->item = g_list_nth_data (icon_view->priv->items, info->index);
9460 items = items->next;
9463 priv->items = g_list_sort (priv->items,
9464 (GCompareFunc)gtk_icon_view_accessible_item_compare);
9470 gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
9475 obj = G_OBJECT (model);
9476 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_changed, widget);
9477 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_inserted, widget);
9478 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_deleted, widget);
9479 g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_rows_reordered, widget);
9483 gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
9487 obj = G_OBJECT (icon_view->priv->model);
9488 g_signal_connect_data (obj, "row-changed",
9489 (GCallback) gtk_icon_view_accessible_model_row_changed,
9490 icon_view, NULL, 0);
9491 g_signal_connect_data (obj, "row-inserted",
9492 (GCallback) gtk_icon_view_accessible_model_row_inserted,
9493 icon_view, NULL, G_CONNECT_AFTER);
9494 g_signal_connect_data (obj, "row-deleted",
9495 (GCallback) gtk_icon_view_accessible_model_row_deleted,
9496 icon_view, NULL, G_CONNECT_AFTER);
9497 g_signal_connect_data (obj, "rows-reordered",
9498 (GCallback) gtk_icon_view_accessible_model_rows_reordered,
9499 icon_view, NULL, G_CONNECT_AFTER);
9503 gtk_icon_view_accessible_clear_cache (GtkIconViewAccessiblePrivate *priv)
9505 GtkIconViewItemAccessibleInfo *info;
9508 items = priv->items;
9511 info = (GtkIconViewItemAccessibleInfo *) items->data;
9512 g_object_unref (info->item);
9513 g_free (items->data);
9514 items = items->next;
9516 g_list_free (priv->items);
9521 gtk_icon_view_accessible_notify_gtk (GObject *obj,
9524 GtkIconView *icon_view;
9527 GtkIconViewAccessiblePrivate *priv;
9529 if (strcmp (pspec->name, "model") == 0)
9531 widget = GTK_WIDGET (obj);
9532 atk_obj = gtk_widget_get_accessible (widget);
9533 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9536 g_object_remove_weak_pointer (G_OBJECT (priv->model),
9537 (gpointer *)&priv->model);
9538 gtk_icon_view_accessible_disconnect_model_signals (priv->model, widget);
9540 gtk_icon_view_accessible_clear_cache (priv);
9542 icon_view = GTK_ICON_VIEW (obj);
9543 priv->model = icon_view->priv->model;
9544 /* If there is no model the GtkIconView is probably being destroyed */
9547 g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
9548 gtk_icon_view_accessible_connect_model_signals (icon_view);
9556 gtk_icon_view_accessible_initialize (AtkObject *accessible,
9559 GtkIconViewAccessiblePrivate *priv;
9560 GtkIconView *icon_view;
9562 if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize)
9563 ATK_OBJECT_CLASS (accessible_parent_class)->initialize (accessible, data);
9565 priv = g_new0 (GtkIconViewAccessiblePrivate, 1);
9566 g_object_set_qdata (G_OBJECT (accessible),
9567 accessible_private_data_quark,
9570 icon_view = GTK_ICON_VIEW (data);
9571 if (icon_view->priv->hadjustment)
9572 gtk_icon_view_accessible_set_adjustment (icon_view,
9573 GTK_ORIENTATION_HORIZONTAL,
9574 icon_view->priv->hadjustment);
9575 if (icon_view->priv->vadjustment)
9576 gtk_icon_view_accessible_set_adjustment (icon_view,
9577 GTK_ORIENTATION_VERTICAL,
9578 icon_view->priv->vadjustment);
9579 g_signal_connect (data,
9581 G_CALLBACK (gtk_icon_view_accessible_notify_gtk),
9584 priv->model = icon_view->priv->model;
9587 g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
9588 gtk_icon_view_accessible_connect_model_signals (icon_view);
9591 accessible->role = ATK_ROLE_LAYERED_PANE;
9595 gtk_icon_view_accessible_finalize (GObject *object)
9597 GtkIconViewAccessiblePrivate *priv;
9599 priv = gtk_icon_view_accessible_get_priv (ATK_OBJECT (object));
9600 gtk_icon_view_accessible_clear_cache (priv);
9604 G_OBJECT_CLASS (accessible_parent_class)->finalize (object);
9608 gtk_icon_view_accessible_destroyed (GtkWidget *widget,
9609 GtkAccessible *accessible)
9612 GtkIconViewAccessiblePrivate *priv;
9614 atk_obj = ATK_OBJECT (accessible);
9615 priv = gtk_icon_view_accessible_get_priv (atk_obj);
9618 g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj),
9619 (gpointer *)&priv->old_hadj);
9621 g_signal_handlers_disconnect_by_func (priv->old_hadj,
9622 (gpointer) gtk_icon_view_accessible_adjustment_changed,
9624 priv->old_hadj = NULL;
9628 g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj),
9629 (gpointer *)&priv->old_vadj);
9631 g_signal_handlers_disconnect_by_func (priv->old_vadj,
9632 (gpointer) gtk_icon_view_accessible_adjustment_changed,
9634 priv->old_vadj = NULL;
9639 gtk_icon_view_accessible_connect_widget_destroyed (GtkAccessible *accessible)
9643 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
9646 g_signal_connect_after (widget,
9648 G_CALLBACK (gtk_icon_view_accessible_destroyed),
9651 GTK_ACCESSIBLE_CLASS (accessible_parent_class)->connect_widget_destroyed (accessible);
9655 gtk_icon_view_accessible_class_init (AtkObjectClass *klass)
9657 GObjectClass *gobject_class;
9658 GtkAccessibleClass *accessible_class;
9660 accessible_parent_class = g_type_class_peek_parent (klass);
9662 gobject_class = (GObjectClass *)klass;
9663 accessible_class = (GtkAccessibleClass *)klass;
9665 gobject_class->finalize = gtk_icon_view_accessible_finalize;
9667 klass->get_n_children = gtk_icon_view_accessible_get_n_children;
9668 klass->ref_child = gtk_icon_view_accessible_ref_child;
9669 klass->initialize = gtk_icon_view_accessible_initialize;
9671 accessible_class->connect_widget_destroyed = gtk_icon_view_accessible_connect_widget_destroyed;
9673 accessible_private_data_quark = g_quark_from_static_string ("icon_view-accessible-private-data");
9677 gtk_icon_view_accessible_ref_accessible_at_point (AtkComponent *component,
9680 AtkCoordType coord_type)
9683 GtkIconView *icon_view;
9684 GtkIconViewItem *item;
9687 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (component));
9689 /* State is defunct */
9692 icon_view = GTK_ICON_VIEW (widget);
9693 atk_component_get_extents (component, &x_pos, &y_pos, NULL, NULL, coord_type);
9694 item = gtk_icon_view_get_item_at_coords (icon_view, x - x_pos, y - y_pos, TRUE, NULL);
9696 return gtk_icon_view_accessible_ref_child (ATK_OBJECT (component), item->index);
9702 atk_component_interface_init (AtkComponentIface *iface)
9704 iface->ref_accessible_at_point = gtk_icon_view_accessible_ref_accessible_at_point;
9708 gtk_icon_view_accessible_add_selection (AtkSelection *selection,
9712 GtkIconView *icon_view;
9713 GtkIconViewItem *item;
9715 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9719 icon_view = GTK_ICON_VIEW (widget);
9721 item = g_list_nth_data (icon_view->priv->items, i);
9726 gtk_icon_view_select_item (icon_view, item);
9732 gtk_icon_view_accessible_clear_selection (AtkSelection *selection)
9735 GtkIconView *icon_view;
9737 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9741 icon_view = GTK_ICON_VIEW (widget);
9742 gtk_icon_view_unselect_all (icon_view);
9748 gtk_icon_view_accessible_ref_selection (AtkSelection *selection,
9753 GtkIconView *icon_view;
9754 GtkIconViewItem *item;
9756 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9760 icon_view = GTK_ICON_VIEW (widget);
9762 l = icon_view->priv->items;
9769 return atk_object_ref_accessible_child (gtk_widget_get_accessible (widget), item->index);
9780 gtk_icon_view_accessible_get_selection_count (AtkSelection *selection)
9783 GtkIconView *icon_view;
9784 GtkIconViewItem *item;
9788 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9792 icon_view = GTK_ICON_VIEW (widget);
9794 l = icon_view->priv->items;
9810 gtk_icon_view_accessible_is_child_selected (AtkSelection *selection,
9814 GtkIconView *icon_view;
9815 GtkIconViewItem *item;
9817 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9821 icon_view = GTK_ICON_VIEW (widget);
9823 item = g_list_nth_data (icon_view->priv->items, i);
9827 return item->selected;
9831 gtk_icon_view_accessible_remove_selection (AtkSelection *selection,
9835 GtkIconView *icon_view;
9836 GtkIconViewItem *item;
9840 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9844 icon_view = GTK_ICON_VIEW (widget);
9845 l = icon_view->priv->items;
9854 gtk_icon_view_unselect_item (icon_view, item);
9866 gtk_icon_view_accessible_select_all_selection (AtkSelection *selection)
9869 GtkIconView *icon_view;
9871 widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
9875 icon_view = GTK_ICON_VIEW (widget);
9876 gtk_icon_view_select_all (icon_view);
9881 gtk_icon_view_accessible_selection_interface_init (AtkSelectionIface *iface)
9883 iface->add_selection = gtk_icon_view_accessible_add_selection;
9884 iface->clear_selection = gtk_icon_view_accessible_clear_selection;
9885 iface->ref_selection = gtk_icon_view_accessible_ref_selection;
9886 iface->get_selection_count = gtk_icon_view_accessible_get_selection_count;
9887 iface->is_child_selected = gtk_icon_view_accessible_is_child_selected;
9888 iface->remove_selection = gtk_icon_view_accessible_remove_selection;
9889 iface->select_all_selection = gtk_icon_view_accessible_select_all_selection;
9893 gtk_icon_view_accessible_get_type (void)
9895 static GType type = 0;
9902 (GBaseInitFunc) NULL, /* base init */
9903 (GBaseFinalizeFunc) NULL, /* base finalize */
9904 (GClassInitFunc) gtk_icon_view_accessible_class_init,
9905 (GClassFinalizeFunc) NULL, /* class finalize */
9906 NULL, /* class data */
9907 0, /* instance size */
9908 0, /* nb preallocs */
9909 (GInstanceInitFunc) NULL, /* instance init */
9910 NULL /* value table */
9912 const GInterfaceInfo atk_component_info =
9914 (GInterfaceInitFunc) atk_component_interface_init,
9915 (GInterfaceFinalizeFunc) NULL,
9918 const GInterfaceInfo atk_selection_info =
9920 (GInterfaceInitFunc) gtk_icon_view_accessible_selection_interface_init,
9921 (GInterfaceFinalizeFunc) NULL,
9926 * Figure out the size of the class and instance
9927 * we are deriving from
9929 AtkObjectFactory *factory;
9932 GType derived_atk_type;
9934 derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
9935 factory = atk_registry_get_factory (atk_get_default_registry (),
9937 derived_atk_type = atk_object_factory_get_accessible_type (factory);
9938 g_type_query (derived_atk_type, &query);
9939 tinfo.class_size = query.class_size;
9940 tinfo.instance_size = query.instance_size;
9942 type = g_type_register_static (derived_atk_type,
9943 I_("GtkIconViewAccessible"),
9945 g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
9946 &atk_component_info);
9947 g_type_add_interface_static (type, ATK_TYPE_SELECTION,
9948 &atk_selection_info);
9954 gtk_icon_view_accessible_new (GObject *obj)
9956 AtkObject *accessible;
9958 g_return_val_if_fail (GTK_IS_WIDGET (obj), NULL);
9960 accessible = g_object_new (gtk_icon_view_accessible_get_type (), NULL);
9961 atk_object_initialize (accessible, obj);
9967 gtk_icon_view_accessible_factory_get_accessible_type (void)
9969 return gtk_icon_view_accessible_get_type ();
9973 gtk_icon_view_accessible_factory_create_accessible (GObject *obj)
9975 return gtk_icon_view_accessible_new (obj);
9979 gtk_icon_view_accessible_factory_class_init (AtkObjectFactoryClass *klass)
9981 klass->create_accessible = gtk_icon_view_accessible_factory_create_accessible;
9982 klass->get_accessible_type = gtk_icon_view_accessible_factory_get_accessible_type;
9986 gtk_icon_view_accessible_factory_get_type (void)
9988 static GType type = 0;
9992 const GTypeInfo tinfo =
9994 sizeof (AtkObjectFactoryClass),
9995 NULL, /* base_init */
9996 NULL, /* base_finalize */
9997 (GClassInitFunc) gtk_icon_view_accessible_factory_class_init,
9998 NULL, /* class_finalize */
9999 NULL, /* class_data */
10000 sizeof (AtkObjectFactory),
10001 0, /* n_preallocs */
10005 type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY,
10006 I_("GtkIconViewAccessibleFactory"),
10014 gtk_icon_view_get_accessible (GtkWidget *widget)
10016 static gboolean first_time = TRUE;
10020 AtkObjectFactory *factory;
10021 AtkRegistry *registry;
10022 GType derived_type;
10023 GType derived_atk_type;
10026 * Figure out whether accessibility is enabled by looking at the
10027 * type of the accessible object which would be created for
10028 * the parent type of GtkIconView.
10030 derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
10032 registry = atk_get_default_registry ();
10033 factory = atk_registry_get_factory (registry,
10035 derived_atk_type = atk_object_factory_get_accessible_type (factory);
10036 if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
10037 atk_registry_set_factory_type (registry,
10038 GTK_TYPE_ICON_VIEW,
10039 gtk_icon_view_accessible_factory_get_type ());
10040 first_time = FALSE;
10042 return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->get_accessible (widget);
10046 gtk_icon_view_buildable_custom_tag_start (GtkBuildable *buildable,
10047 GtkBuilder *builder,
10049 const gchar *tagname,
10050 GMarkupParser *parser,
10053 if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
10054 tagname, parser, data))
10057 return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
10058 tagname, parser, data);
10062 gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable,
10063 GtkBuilder *builder,
10065 const gchar *tagname,
10068 if (strcmp (tagname, "attributes") == 0)
10069 _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
10072 parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,