~ubuntu-branches/ubuntu/precise/gtk+2.0/precise-updates

« back to all changes in this revision

Viewing changes to .pc/git_buggy_icon_view_update.patch/gtk/gtkiconview.c

  • Committer: Package Import Robot
  • Author(s): Sebastien Bacher
  • Date: 2011-12-13 19:29:04 UTC
  • mfrom: (72.5.19 sid)
  • Revision ID: package-import@ubuntu.com-20111213192904-3a0r14iwsgdjt5lp
Tags: 2.24.8-2ubuntu1
* debian/patches/git_buggy_icon_view_update.patch:
  - git commit reverting a buggy icon view patch leading to 
    segfaults in lxappearance (lp: #899322)
* Resynchronize on Debian
* debian/libgtk2.0-0.symbols:
  - Add Ubuntu specific symbols
* debian/rules:
  - Use dh_autoreconf
  - Use -XNEWS -Xchangelog.Debian -XREADME to dh_compress calls to 
    workaround a gzip issue leading to different md5sum between builds
* debian/patches/012_ubuntu-set-grab-add.patch
  - Added ubuntu_gtk_widget_set_has_grab so we can grab sliders and 
    things in menus, needed by ido
* debian/patches/043_menu_proxy.patch
  - Add GtkMenuProxy support for remoting menus.
* debian/patches/044_grips.patch:
  - Backport from the gtk3 resize grips to the natty gtk2 version
* debian/patches/061_use_pdf_as_default_printing_standard.patch:
  - dropped, the issue has been fixed upstream differently since
* debian/patches/062_dnd_menubar.patch:
  - Allow click on menubars for dnd
* debian/patches/063_treeview_almost_fixed.patch:
  - Add an ubuntu-almost-fixed-height-mode property, (required for
    software-center)
* debian/patches/065_gir_set_packages.patch
  - Added _gir_PACKAGES for each gir created, to match gir to pkg which is
    needed by vapigen-0.12
* debian/patches/070_mandatory-relibtoolize.patch:
  - Dropped, we are using dh-autoreconf instead
* debian/patches/071_no_offscreen_widgets_grabbing.patch:
  - Don't let offscreen widgets do grabbing
* debian/patches/072_indicator_menu_update.patch:
  - change by Cody Russell to send an update event on menu changes,
    should make the bluetooth indicator refresh correctly
* debian/patches/091_bugzilla_tooltip_refresh.patch:
  - Upstream bugzilla change to have better looking tooltips the gtk theme
    need to set "new-tooltip-style" to use those
* debian/patches/092_default_to_xdg_document_dir.patch:
  - Use $XDG_DOCUMENTS_DIR as default directory rather than the home
    directory for the 'Print to File' function.
* debian/patches/093_gtk3_gtkimage_fallbacks_use.patch:
  - Backported gtk3 patch to add a "use-fallback" property to GtkImage, using 
    it "icon-name and GIcon type of GtkImages can use automatic fallback 
    names.", it will be useful for the indicator stack
* debian/patches/095_git_menus_scrolling.patch:
  - backported gtk3 commit to fix menu scrolling issues
* debian/patches/096_git_gtkprintsettings.patch:
  - upstream git commit backported from the gtk3 serie, don't ignore the 
    gtkprintsettings resolution settings 
* debian/patches/097_statusicon_image_fallback.patch: Make GtkStatusIcon
  images use fallbacks by default if the property is available.
* debian/patches/100_overlay_scrollbar_loading.patch
  - support for dynamically loading overlay scrollbars
* debian/patches/gailitem-set-alt-name.patch: Extend the GailItem object
  so applications can set an alternative textual description for a menu
  item that has an icon, where the icon is used to give the user more
  information about the item in question. This textual description is
  used by assistive technologies such as Orca to label the menu item.
* Dropped changes:
* debian/control.in:
  - don't keep an old conflicts on appmenu-gtk, it was a transitional thing   

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* gtkiconview.c
 
2
 * Copyright (C) 2002, 2004  Anders Carlsson <andersca@gnu.org>
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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.
 
18
 */
 
19
 
 
20
#include "config.h"
 
21
#include <string.h>
 
22
 
 
23
#include <atk/atk.h>
 
24
 
 
25
#include <gdk/gdkkeysyms.h>
 
26
 
 
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"
 
34
#include "gtkdnd.h"
 
35
#include "gtkmain.h"
 
36
#include "gtkintl.h"
 
37
#include "gtkaccessible.h"
 
38
#include "gtkwindow.h"
 
39
#include "gtkentry.h"
 
40
#include "gtkcombobox.h"
 
41
#include "gtktextbuffer.h"
 
42
#include "gtktreednd.h"
 
43
#include "gtkprivate.h"
 
44
#include "gtkalias.h"
 
45
 
 
46
#undef DEBUG_ICON_VIEW
 
47
 
 
48
#define SCROLL_EDGE_SIZE 15
 
49
 
 
50
#define GTK_ICON_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ICON_VIEW, GtkIconViewPrivate))
 
51
 
 
52
typedef struct _GtkIconViewItem GtkIconViewItem;
 
53
struct _GtkIconViewItem
 
54
{
 
55
  GtkTreeIter iter;
 
56
  gint index;
 
57
  
 
58
  gint row, col;
 
59
 
 
60
  /* Bounding box */
 
61
  gint x, y, width, height;
 
62
 
 
63
  /* Individual cells.
 
64
   * box[i] is the actual area occupied by cell i,
 
65
   * before, after are used to calculate the cell 
 
66
   * area relative to the box. 
 
67
   * See gtk_icon_view_get_cell_area().
 
68
   */
 
69
  gint n_cells;
 
70
  GdkRectangle *box;
 
71
  gint *before;
 
72
  gint *after;
 
73
 
 
74
  guint selected : 1;
 
75
  guint selected_before_rubberbanding : 1;
 
76
 
 
77
};
 
78
 
 
79
typedef struct _GtkIconViewCellInfo GtkIconViewCellInfo;
 
80
struct _GtkIconViewCellInfo
 
81
{
 
82
  GtkCellRenderer *cell;
 
83
 
 
84
  guint expand : 1;
 
85
  guint pack : 1;
 
86
  guint editing : 1;
 
87
 
 
88
  gint position;
 
89
 
 
90
  GSList *attributes;
 
91
 
 
92
  GtkCellLayoutDataFunc func;
 
93
  gpointer func_data;
 
94
  GDestroyNotify destroy;
 
95
};
 
96
 
 
97
typedef struct _GtkIconViewChild GtkIconViewChild;
 
98
struct _GtkIconViewChild
 
99
{
 
100
  GtkWidget *widget;
 
101
  GtkIconViewItem *item;
 
102
  gint cell;
 
103
};
 
104
 
 
105
struct _GtkIconViewPrivate
 
106
{
 
107
  gint width, height;
 
108
 
 
109
  GtkSelectionMode selection_mode;
 
110
 
 
111
  GdkWindow *bin_window;
 
112
 
 
113
  GList *children;
 
114
 
 
115
  GtkTreeModel *model;
 
116
  
 
117
  GList *items;
 
118
  
 
119
  GtkAdjustment *hadjustment;
 
120
  GtkAdjustment *vadjustment;
 
121
 
 
122
  guint layout_idle_id;
 
123
  
 
124
  gboolean doing_rubberband;
 
125
  gint rubberband_x1, rubberband_y1;
 
126
  gint rubberband_x2, rubberband_y2;
 
127
 
 
128
  guint scroll_timeout_id;
 
129
  gint scroll_value_diff;
 
130
  gint event_last_x, event_last_y;
 
131
 
 
132
  GtkIconViewItem *anchor_item;
 
133
  GtkIconViewItem *cursor_item;
 
134
  GtkIconViewItem *edited_item;
 
135
  GtkCellEditable *editable;
 
136
 
 
137
  GtkIconViewItem *last_single_clicked;
 
138
 
 
139
  GList *cell_list;
 
140
  guint n_cells;
 
141
 
 
142
  gint cursor_cell;
 
143
 
 
144
  GtkOrientation item_orientation;
 
145
 
 
146
  gint columns;
 
147
  gint item_width;
 
148
  gint spacing;
 
149
  gint row_spacing;
 
150
  gint column_spacing;
 
151
  gint margin;
 
152
  gint item_padding;
 
153
 
 
154
  gint text_column;
 
155
  gint markup_column;
 
156
  gint pixbuf_column;
 
157
 
 
158
  gint pixbuf_cell;
 
159
  gint text_cell;
 
160
 
 
161
  gint tooltip_column;
 
162
 
 
163
  /* Drag-and-drop. */
 
164
  GdkModifierType start_button_mask;
 
165
  gint pressed_button;
 
166
  gint press_start_x;
 
167
  gint press_start_y;
 
168
 
 
169
  GdkDragAction source_actions;
 
170
  GdkDragAction dest_actions;
 
171
 
 
172
  GtkTreeRowReference *dest_item;
 
173
  GtkIconViewDropPosition dest_pos;
 
174
 
 
175
  /* scroll to */
 
176
  GtkTreeRowReference *scroll_to_path;
 
177
  gfloat scroll_to_row_align;
 
178
  gfloat scroll_to_col_align;
 
179
  guint scroll_to_use_align : 1;
 
180
 
 
181
  guint source_set : 1;
 
182
  guint dest_set : 1;
 
183
  guint reorderable : 1;
 
184
  guint empty_view_drop :1;
 
185
 
 
186
  guint modify_selection_pressed : 1;
 
187
  guint extend_selection_pressed : 1;
 
188
 
 
189
  guint draw_focus : 1;
 
190
};
 
191
 
 
192
/* Signals */
 
193
enum
 
194
{
 
195
  ITEM_ACTIVATED,
 
196
  SELECTION_CHANGED,
 
197
  SELECT_ALL,
 
198
  UNSELECT_ALL,
 
199
  SELECT_CURSOR_ITEM,
 
200
  TOGGLE_CURSOR_ITEM,
 
201
  MOVE_CURSOR,
 
202
  ACTIVATE_CURSOR_ITEM,
 
203
  LAST_SIGNAL
 
204
};
 
205
 
 
206
/* Properties */
 
207
enum
 
208
{
 
209
  PROP_0,
 
210
  PROP_PIXBUF_COLUMN,
 
211
  PROP_TEXT_COLUMN,
 
212
  PROP_MARKUP_COLUMN,  
 
213
  PROP_SELECTION_MODE,
 
214
  PROP_ORIENTATION,
 
215
  PROP_ITEM_ORIENTATION,
 
216
  PROP_MODEL,
 
217
  PROP_COLUMNS,
 
218
  PROP_ITEM_WIDTH,
 
219
  PROP_SPACING,
 
220
  PROP_ROW_SPACING,
 
221
  PROP_COLUMN_SPACING,
 
222
  PROP_MARGIN,
 
223
  PROP_REORDERABLE,
 
224
  PROP_TOOLTIP_COLUMN,
 
225
  PROP_ITEM_PADDING
 
226
};
 
227
 
 
228
/* GObject vfuncs */
 
229
static void             gtk_icon_view_cell_layout_init          (GtkCellLayoutIface *iface);
 
230
static void             gtk_icon_view_finalize                  (GObject            *object);
 
231
static void             gtk_icon_view_set_property              (GObject            *object,
 
232
                                                                 guint               prop_id,
 
233
                                                                 const GValue       *value,
 
234
                                                                 GParamSpec         *pspec);
 
235
static void             gtk_icon_view_get_property              (GObject            *object,
 
236
                                                                 guint               prop_id,
 
237
                                                                 GValue             *value,
 
238
                                                                 GParamSpec         *pspec);
 
239
 
 
240
/* GtkObject vfuncs */
 
241
static void             gtk_icon_view_destroy                   (GtkObject          *object);
 
242
 
 
243
/* GtkWidget vfuncs */
 
244
static void             gtk_icon_view_realize                   (GtkWidget          *widget);
 
245
static void             gtk_icon_view_unrealize                 (GtkWidget          *widget);
 
246
static void             gtk_icon_view_style_set                 (GtkWidget        *widget,
 
247
                                                                 GtkStyle         *previous_style);
 
248
static void             gtk_icon_view_state_changed             (GtkWidget        *widget,
 
249
                                                                 GtkStateType      previous_state);
 
250
static void             gtk_icon_view_size_request              (GtkWidget          *widget,
 
251
                                                                 GtkRequisition     *requisition);
 
252
static void             gtk_icon_view_size_allocate             (GtkWidget          *widget,
 
253
                                                                 GtkAllocation      *allocation);
 
254
static gboolean         gtk_icon_view_expose                    (GtkWidget          *widget,
 
255
                                                                 GdkEventExpose     *expose);
 
256
static gboolean         gtk_icon_view_motion                    (GtkWidget          *widget,
 
257
                                                                 GdkEventMotion     *event);
 
258
static gboolean         gtk_icon_view_button_press              (GtkWidget          *widget,
 
259
                                                                 GdkEventButton     *event);
 
260
static gboolean         gtk_icon_view_button_release            (GtkWidget          *widget,
 
261
                                                                 GdkEventButton     *event);
 
262
static gboolean         gtk_icon_view_key_press                 (GtkWidget          *widget,
 
263
                                                                 GdkEventKey        *event);
 
264
static gboolean         gtk_icon_view_key_release               (GtkWidget          *widget,
 
265
                                                                 GdkEventKey        *event);
 
266
static AtkObject       *gtk_icon_view_get_accessible            (GtkWidget          *widget);
 
267
 
 
268
 
 
269
/* GtkContainer vfuncs */
 
270
static void             gtk_icon_view_remove                    (GtkContainer       *container,
 
271
                                                                 GtkWidget          *widget);
 
272
static void             gtk_icon_view_forall                    (GtkContainer       *container,
 
273
                                                                 gboolean            include_internals,
 
274
                                                                 GtkCallback         callback,
 
275
                                                                 gpointer            callback_data);
 
276
 
 
277
/* GtkIconView vfuncs */
 
278
static void             gtk_icon_view_set_adjustments           (GtkIconView        *icon_view,
 
279
                                                                 GtkAdjustment      *hadj,
 
280
                                                                 GtkAdjustment      *vadj);
 
281
static void             gtk_icon_view_real_select_all           (GtkIconView        *icon_view);
 
282
static void             gtk_icon_view_real_unselect_all         (GtkIconView        *icon_view);
 
283
static void             gtk_icon_view_real_select_cursor_item   (GtkIconView        *icon_view);
 
284
static void             gtk_icon_view_real_toggle_cursor_item   (GtkIconView        *icon_view);
 
285
static gboolean         gtk_icon_view_real_activate_cursor_item (GtkIconView        *icon_view);
 
286
 
 
287
 /* Internal functions */
 
288
static void                 gtk_icon_view_adjustment_changed             (GtkAdjustment          *adjustment,
 
289
                                                                          GtkIconView            *icon_view);
 
290
static void                 gtk_icon_view_layout                         (GtkIconView            *icon_view);
 
291
static void                 gtk_icon_view_paint_item                     (GtkIconView            *icon_view,
 
292
                                                                          cairo_t *cr,
 
293
 
 
294
                                                                          GtkIconViewItem        *item,
 
295
                                                                          GdkRectangle           *area,
 
296
                                                                          GdkDrawable *drawable,
 
297
                                                                          gint         x,
 
298
                                                                          gint         y,
 
299
                                                                          gboolean     draw_focus);
 
300
static void                 gtk_icon_view_paint_rubberband               (GtkIconView            *icon_view,
 
301
                                                                          cairo_t *cr,
 
302
                                                                          GdkRectangle           *area);
 
303
static void                 gtk_icon_view_queue_draw_path                (GtkIconView *icon_view,
 
304
                                                                          GtkTreePath *path);
 
305
static void                 gtk_icon_view_queue_draw_item                (GtkIconView            *icon_view,
 
306
                                                                          GtkIconViewItem        *item);
 
307
static void                 gtk_icon_view_queue_layout                   (GtkIconView            *icon_view);
 
308
static void                 gtk_icon_view_set_cursor_item                (GtkIconView            *icon_view,
 
309
                                                                          GtkIconViewItem        *item,
 
310
                                                                          gint                    cursor_cell);
 
311
static void                 gtk_icon_view_start_rubberbanding            (GtkIconView            *icon_view,
 
312
                                                                          gint                    x,
 
313
                                                                          gint                    y);
 
314
static void                 gtk_icon_view_stop_rubberbanding             (GtkIconView            *icon_view);
 
315
static void                 gtk_icon_view_update_rubberband_selection    (GtkIconView            *icon_view);
 
316
static gboolean             gtk_icon_view_item_hit_test                  (GtkIconView            *icon_view,
 
317
                                                                          GtkIconViewItem        *item,
 
318
                                                                          gint                    x,
 
319
                                                                          gint                    y,
 
320
                                                                          gint                    width,
 
321
                                                                          gint                    height);
 
322
static gboolean             gtk_icon_view_unselect_all_internal          (GtkIconView            *icon_view);
 
323
static void                 gtk_icon_view_calculate_item_size            (GtkIconView            *icon_view,
 
324
                                                                          GtkIconViewItem        *item);
 
325
static void                 gtk_icon_view_calculate_item_size2           (GtkIconView            *icon_view,
 
326
                                                                          GtkIconViewItem        *item,
 
327
                                                                          gint                   *max_height);
 
328
static void                 gtk_icon_view_update_rubberband              (gpointer                data);
 
329
static void                 gtk_icon_view_item_invalidate_size           (GtkIconViewItem        *item);
 
330
static void                 gtk_icon_view_invalidate_sizes               (GtkIconView            *icon_view);
 
331
static void                 gtk_icon_view_add_move_binding               (GtkBindingSet          *binding_set,
 
332
                                                                          guint                   keyval,
 
333
                                                                          guint                   modmask,
 
334
                                                                          GtkMovementStep         step,
 
335
                                                                          gint                    count);
 
336
static gboolean             gtk_icon_view_real_move_cursor               (GtkIconView            *icon_view,
 
337
                                                                          GtkMovementStep         step,
 
338
                                                                          gint                    count);
 
339
static void                 gtk_icon_view_move_cursor_up_down            (GtkIconView            *icon_view,
 
340
                                                                          gint                    count);
 
341
static void                 gtk_icon_view_move_cursor_page_up_down       (GtkIconView            *icon_view,
 
342
                                                                          gint                    count);
 
343
static void                 gtk_icon_view_move_cursor_left_right         (GtkIconView            *icon_view,
 
344
                                                                          gint                    count);
 
345
static void                 gtk_icon_view_move_cursor_start_end          (GtkIconView            *icon_view,
 
346
                                                                          gint                    count);
 
347
static void                 gtk_icon_view_scroll_to_item                 (GtkIconView            *icon_view,
 
348
                                                                          GtkIconViewItem        *item);
 
349
static void                 gtk_icon_view_select_item                    (GtkIconView            *icon_view,
 
350
                                                                          GtkIconViewItem        *item);
 
351
static void                 gtk_icon_view_unselect_item                  (GtkIconView            *icon_view,
 
352
                                                                          GtkIconViewItem        *item);
 
353
static gboolean             gtk_icon_view_select_all_between             (GtkIconView            *icon_view,
 
354
                                                                          GtkIconViewItem        *anchor,
 
355
                                                                          GtkIconViewItem        *cursor);
 
356
static GtkIconViewItem *    gtk_icon_view_get_item_at_coords             (GtkIconView            *icon_view,
 
357
                                                                          gint                    x,
 
358
                                                                          gint                    y,
 
359
                                                                          gboolean                only_in_cell,
 
360
                                                                          GtkIconViewCellInfo   **cell_at_pos);
 
361
static void                 gtk_icon_view_get_cell_area                  (GtkIconView            *icon_view,
 
362
                                                                          GtkIconViewItem        *item,
 
363
                                                                          GtkIconViewCellInfo    *cell_info,
 
364
                                                                          GdkRectangle           *cell_area);
 
365
static void                 gtk_icon_view_get_cell_box                   (GtkIconView            *icon_view,
 
366
                                                                          GtkIconViewItem        *item,
 
367
                                                                          GtkIconViewCellInfo    *info,
 
368
                                                                          GdkRectangle           *box);
 
369
static GtkIconViewCellInfo *gtk_icon_view_get_cell_info                  (GtkIconView            *icon_view,
 
370
                                                                          GtkCellRenderer        *renderer);
 
371
static void                 gtk_icon_view_set_cell_data                  (GtkIconView            *icon_view,
 
372
                                                                          GtkIconViewItem        *item);
 
373
static void                 gtk_icon_view_cell_layout_pack_start         (GtkCellLayout          *layout,
 
374
                                                                          GtkCellRenderer        *renderer,
 
375
                                                                          gboolean                expand);
 
376
static void                 gtk_icon_view_cell_layout_pack_end           (GtkCellLayout          *layout,
 
377
                                                                          GtkCellRenderer        *renderer,
 
378
                                                                          gboolean                expand);
 
379
static void                 gtk_icon_view_cell_layout_add_attribute      (GtkCellLayout          *layout,
 
380
                                                                          GtkCellRenderer        *renderer,
 
381
                                                                          const gchar            *attribute,
 
382
                                                                          gint                    column);
 
383
static void                 gtk_icon_view_cell_layout_clear              (GtkCellLayout          *layout);
 
384
static void                 gtk_icon_view_cell_layout_clear_attributes   (GtkCellLayout          *layout,
 
385
                                                                          GtkCellRenderer        *renderer);
 
386
static void                 gtk_icon_view_cell_layout_set_cell_data_func (GtkCellLayout          *layout,
 
387
                                                                          GtkCellRenderer        *cell,
 
388
                                                                          GtkCellLayoutDataFunc   func,
 
389
                                                                          gpointer                func_data,
 
390
                                                                          GDestroyNotify          destroy);
 
391
static void                 gtk_icon_view_cell_layout_reorder            (GtkCellLayout          *layout,
 
392
                                                                          GtkCellRenderer        *cell,
 
393
                                                                          gint                    position);
 
394
static GList *              gtk_icon_view_cell_layout_get_cells          (GtkCellLayout          *layout);
 
395
 
 
396
static void                 gtk_icon_view_item_activate_cell             (GtkIconView            *icon_view,
 
397
                                                                          GtkIconViewItem        *item,
 
398
                                                                          GtkIconViewCellInfo    *cell_info,
 
399
                                                                          GdkEvent               *event);
 
400
static void                 gtk_icon_view_item_selected_changed          (GtkIconView            *icon_view,
 
401
                                                                          GtkIconViewItem        *item);
 
402
static void                 gtk_icon_view_put                            (GtkIconView            *icon_view,
 
403
                                                                          GtkWidget              *widget,
 
404
                                                                          GtkIconViewItem        *item,
 
405
                                                                          gint                    cell);
 
406
static void                 gtk_icon_view_remove_widget                  (GtkCellEditable        *editable,
 
407
                                                                          GtkIconView            *icon_view);
 
408
static void                 gtk_icon_view_start_editing                  (GtkIconView            *icon_view,
 
409
                                                                          GtkIconViewItem        *item,
 
410
                                                                          GtkIconViewCellInfo    *cell_info,
 
411
                                                                          GdkEvent               *event);
 
412
static void                 gtk_icon_view_stop_editing                   (GtkIconView            *icon_view,
 
413
                                                                          gboolean                cancel_editing);
 
414
 
 
415
/* Source side drag signals */
 
416
static void gtk_icon_view_drag_begin       (GtkWidget        *widget,
 
417
                                            GdkDragContext   *context);
 
418
static void gtk_icon_view_drag_end         (GtkWidget        *widget,
 
419
                                            GdkDragContext   *context);
 
420
static void gtk_icon_view_drag_data_get    (GtkWidget        *widget,
 
421
                                            GdkDragContext   *context,
 
422
                                            GtkSelectionData *selection_data,
 
423
                                            guint             info,
 
424
                                            guint             time);
 
425
static void gtk_icon_view_drag_data_delete (GtkWidget        *widget,
 
426
                                            GdkDragContext   *context);
 
427
 
 
428
/* Target side drag signals */
 
429
static void     gtk_icon_view_drag_leave         (GtkWidget        *widget,
 
430
                                                  GdkDragContext   *context,
 
431
                                                  guint             time);
 
432
static gboolean gtk_icon_view_drag_motion        (GtkWidget        *widget,
 
433
                                                  GdkDragContext   *context,
 
434
                                                  gint              x,
 
435
                                                  gint              y,
 
436
                                                  guint             time);
 
437
static gboolean gtk_icon_view_drag_drop          (GtkWidget        *widget,
 
438
                                                  GdkDragContext   *context,
 
439
                                                  gint              x,
 
440
                                                  gint              y,
 
441
                                                  guint             time);
 
442
static void     gtk_icon_view_drag_data_received (GtkWidget        *widget,
 
443
                                                  GdkDragContext   *context,
 
444
                                                  gint              x,
 
445
                                                  gint              y,
 
446
                                                  GtkSelectionData *selection_data,
 
447
                                                  guint             info,
 
448
                                                  guint             time);
 
449
static gboolean gtk_icon_view_maybe_begin_drag   (GtkIconView             *icon_view,
 
450
                                                  GdkEventMotion          *event);
 
451
 
 
452
static void     remove_scroll_timeout            (GtkIconView *icon_view);
 
453
 
 
454
static void     adjust_wrap_width                (GtkIconView     *icon_view,
 
455
                                                  GtkIconViewItem *item);
 
456
 
 
457
/* GtkBuildable */
 
458
static GtkBuildableIface *parent_buildable_iface;
 
459
static void     gtk_icon_view_buildable_init             (GtkBuildableIface *iface);
 
460
static gboolean gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
 
461
                                                          GtkBuilder    *builder,
 
462
                                                          GObject       *child,
 
463
                                                          const gchar   *tagname,
 
464
                                                          GMarkupParser *parser,
 
465
                                                          gpointer      *data);
 
466
static void     gtk_icon_view_buildable_custom_tag_end   (GtkBuildable  *buildable,
 
467
                                                          GtkBuilder    *builder,
 
468
                                                          GObject       *child,
 
469
                                                          const gchar   *tagname,
 
470
                                                          gpointer      *data);
 
471
 
 
472
static guint icon_view_signals[LAST_SIGNAL] = { 0 };
 
473
 
 
474
G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
 
475
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
 
476
                                                gtk_icon_view_cell_layout_init)
 
477
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
 
478
                                                gtk_icon_view_buildable_init))
 
479
 
 
480
static void
 
481
gtk_icon_view_class_init (GtkIconViewClass *klass)
 
482
{
 
483
  GObjectClass *gobject_class;
 
484
  GtkObjectClass *object_class;
 
485
  GtkWidgetClass *widget_class;
 
486
  GtkContainerClass *container_class;
 
487
  GtkBindingSet *binding_set;
 
488
  
 
489
  binding_set = gtk_binding_set_by_class (klass);
 
490
 
 
491
  g_type_class_add_private (klass, sizeof (GtkIconViewPrivate));
 
492
 
 
493
  gobject_class = (GObjectClass *) klass;
 
494
  object_class = (GtkObjectClass *) klass;
 
495
  widget_class = (GtkWidgetClass *) klass;
 
496
  container_class = (GtkContainerClass *) klass;
 
497
 
 
498
  gobject_class->finalize = gtk_icon_view_finalize;
 
499
  gobject_class->set_property = gtk_icon_view_set_property;
 
500
  gobject_class->get_property = gtk_icon_view_get_property;
 
501
 
 
502
  object_class->destroy = gtk_icon_view_destroy;
 
503
  
 
504
  widget_class->realize = gtk_icon_view_realize;
 
505
  widget_class->unrealize = gtk_icon_view_unrealize;
 
506
  widget_class->style_set = gtk_icon_view_style_set;
 
507
  widget_class->get_accessible = gtk_icon_view_get_accessible;
 
508
  widget_class->size_request = gtk_icon_view_size_request;
 
509
  widget_class->size_allocate = gtk_icon_view_size_allocate;
 
510
  widget_class->expose_event = gtk_icon_view_expose;
 
511
  widget_class->motion_notify_event = gtk_icon_view_motion;
 
512
  widget_class->button_press_event = gtk_icon_view_button_press;
 
513
  widget_class->button_release_event = gtk_icon_view_button_release;
 
514
  widget_class->key_press_event = gtk_icon_view_key_press;
 
515
  widget_class->key_release_event = gtk_icon_view_key_release;
 
516
  widget_class->drag_begin = gtk_icon_view_drag_begin;
 
517
  widget_class->drag_end = gtk_icon_view_drag_end;
 
518
  widget_class->drag_data_get = gtk_icon_view_drag_data_get;
 
519
  widget_class->drag_data_delete = gtk_icon_view_drag_data_delete;
 
520
  widget_class->drag_leave = gtk_icon_view_drag_leave;
 
521
  widget_class->drag_motion = gtk_icon_view_drag_motion;
 
522
  widget_class->drag_drop = gtk_icon_view_drag_drop;
 
523
  widget_class->drag_data_received = gtk_icon_view_drag_data_received;
 
524
  widget_class->state_changed = gtk_icon_view_state_changed;
 
525
 
 
526
  container_class->remove = gtk_icon_view_remove;
 
527
  container_class->forall = gtk_icon_view_forall;
 
528
 
 
529
  klass->set_scroll_adjustments = gtk_icon_view_set_adjustments;
 
530
  klass->select_all = gtk_icon_view_real_select_all;
 
531
  klass->unselect_all = gtk_icon_view_real_unselect_all;
 
532
  klass->select_cursor_item = gtk_icon_view_real_select_cursor_item;
 
533
  klass->toggle_cursor_item = gtk_icon_view_real_toggle_cursor_item;
 
534
  klass->activate_cursor_item = gtk_icon_view_real_activate_cursor_item;  
 
535
  klass->move_cursor = gtk_icon_view_real_move_cursor;
 
536
  
 
537
  /* Properties */
 
538
  /**
 
539
   * GtkIconView:selection-mode:
 
540
   * 
 
541
   * The ::selection-mode property specifies the selection mode of
 
542
   * icon view. If the mode is #GTK_SELECTION_MULTIPLE, rubberband selection
 
543
   * is enabled, for the other modes, only keyboard selection is possible.
 
544
   *
 
545
   * Since: 2.6
 
546
   */
 
547
  g_object_class_install_property (gobject_class,
 
548
                                   PROP_SELECTION_MODE,
 
549
                                   g_param_spec_enum ("selection-mode",
 
550
                                                      P_("Selection mode"),
 
551
                                                      P_("The selection mode"),
 
552
                                                      GTK_TYPE_SELECTION_MODE,
 
553
                                                      GTK_SELECTION_SINGLE,
 
554
                                                      GTK_PARAM_READWRITE));
 
555
 
 
556
  /**
 
557
   * GtkIconView:pixbuf-column:
 
558
   *
 
559
   * The ::pixbuf-column property contains the number of the model column
 
560
   * containing the pixbufs which are displayed. The pixbuf column must be 
 
561
   * of type #GDK_TYPE_PIXBUF. Setting this property to -1 turns off the
 
562
   * display of pixbufs.
 
563
   *
 
564
   * Since: 2.6
 
565
   */
 
566
  g_object_class_install_property (gobject_class,
 
567
                                   PROP_PIXBUF_COLUMN,
 
568
                                   g_param_spec_int ("pixbuf-column",
 
569
                                                     P_("Pixbuf column"),
 
570
                                                     P_("Model column used to retrieve the icon pixbuf from"),
 
571
                                                     -1, G_MAXINT, -1,
 
572
                                                     GTK_PARAM_READWRITE));
 
573
 
 
574
  /**
 
575
   * GtkIconView:text-column:
 
576
   *
 
577
   * The ::text-column property contains the number of the model column
 
578
   * containing the texts which are displayed. The text column must be 
 
579
   * of type #G_TYPE_STRING. If this property and the :markup-column 
 
580
   * property are both set to -1, no texts are displayed.   
 
581
   *
 
582
   * Since: 2.6
 
583
   */
 
584
  g_object_class_install_property (gobject_class,
 
585
                                   PROP_TEXT_COLUMN,
 
586
                                   g_param_spec_int ("text-column",
 
587
                                                     P_("Text column"),
 
588
                                                     P_("Model column used to retrieve the text from"),
 
589
                                                     -1, G_MAXINT, -1,
 
590
                                                     GTK_PARAM_READWRITE));
 
591
 
 
592
  
 
593
  /**
 
594
   * GtkIconView:markup-column:
 
595
   *
 
596
   * The ::markup-column property contains the number of the model column
 
597
   * containing markup information to be displayed. The markup column must be 
 
598
   * of type #G_TYPE_STRING. If this property and the :text-column property 
 
599
   * are both set to column numbers, it overrides the text column.
 
600
   * If both are set to -1, no texts are displayed.   
 
601
   *
 
602
   * Since: 2.6
 
603
   */
 
604
  g_object_class_install_property (gobject_class,
 
605
                                   PROP_MARKUP_COLUMN,
 
606
                                   g_param_spec_int ("markup-column",
 
607
                                                     P_("Markup column"),
 
608
                                                     P_("Model column used to retrieve the text if using Pango markup"),
 
609
                                                     -1, G_MAXINT, -1,
 
610
                                                     GTK_PARAM_READWRITE));
 
611
  
 
612
  g_object_class_install_property (gobject_class,
 
613
                                   PROP_MODEL,
 
614
                                   g_param_spec_object ("model",
 
615
                                                        P_("Icon View Model"),
 
616
                                                        P_("The model for the icon view"),
 
617
                                                        GTK_TYPE_TREE_MODEL,
 
618
                                                        GTK_PARAM_READWRITE));
 
619
  
 
620
  /**
 
621
   * GtkIconView:columns:
 
622
   *
 
623
   * The columns property contains the number of the columns in which the
 
624
   * items should be displayed. If it is -1, the number of columns will
 
625
   * be chosen automatically to fill the available area.
 
626
   *
 
627
   * Since: 2.6
 
628
   */
 
629
  g_object_class_install_property (gobject_class,
 
630
                                   PROP_COLUMNS,
 
631
                                   g_param_spec_int ("columns",
 
632
                                                     P_("Number of columns"),
 
633
                                                     P_("Number of columns to display"),
 
634
                                                     -1, G_MAXINT, -1,
 
635
                                                     GTK_PARAM_READWRITE));
 
636
  
 
637
 
 
638
  /**
 
639
   * GtkIconView:item-width:
 
640
   *
 
641
   * The item-width property specifies the width to use for each item. 
 
642
   * If it is set to -1, the icon view will automatically determine a 
 
643
   * suitable item size.
 
644
   *
 
645
   * Since: 2.6
 
646
   */
 
647
  g_object_class_install_property (gobject_class,
 
648
                                   PROP_ITEM_WIDTH,
 
649
                                   g_param_spec_int ("item-width",
 
650
                                                     P_("Width for each item"),
 
651
                                                     P_("The width used for each item"),
 
652
                                                     -1, G_MAXINT, -1,
 
653
                                                     GTK_PARAM_READWRITE));  
 
654
 
 
655
  /**
 
656
   * GtkIconView:spacing:
 
657
   *
 
658
   * The spacing property specifies the space which is inserted between
 
659
   * the cells (i.e. the icon and the text) of an item.
 
660
   *
 
661
   * Since: 2.6
 
662
   */
 
663
  g_object_class_install_property (gobject_class,
 
664
                                   PROP_SPACING,
 
665
                                   g_param_spec_int ("spacing",
 
666
                                                     P_("Spacing"),
 
667
                                                     P_("Space which is inserted between cells of an item"),
 
668
                                                     0, G_MAXINT, 0,
 
669
                                                     GTK_PARAM_READWRITE));
 
670
 
 
671
  /**
 
672
   * GtkIconView:row-spacing:
 
673
   *
 
674
   * The row-spacing property specifies the space which is inserted between
 
675
   * the rows of the icon view.
 
676
   *
 
677
   * Since: 2.6
 
678
   */
 
679
  g_object_class_install_property (gobject_class,
 
680
                                   PROP_ROW_SPACING,
 
681
                                   g_param_spec_int ("row-spacing",
 
682
                                                     P_("Row Spacing"),
 
683
                                                     P_("Space which is inserted between grid rows"),
 
684
                                                     0, G_MAXINT, 6,
 
685
                                                     GTK_PARAM_READWRITE));
 
686
 
 
687
  /**
 
688
   * GtkIconView:column-spacing:
 
689
   *
 
690
   * The column-spacing property specifies the space which is inserted between
 
691
   * the columns of the icon view.
 
692
   *
 
693
   * Since: 2.6
 
694
   */
 
695
  g_object_class_install_property (gobject_class,
 
696
                                   PROP_COLUMN_SPACING,
 
697
                                   g_param_spec_int ("column-spacing",
 
698
                                                     P_("Column Spacing"),
 
699
                                                     P_("Space which is inserted between grid columns"),
 
700
                                                     0, G_MAXINT, 6,
 
701
                                                     GTK_PARAM_READWRITE));
 
702
 
 
703
  /**
 
704
   * GtkIconView:margin:
 
705
   *
 
706
   * The margin property specifies the space which is inserted 
 
707
   * at the edges of the icon view.
 
708
   *
 
709
   * Since: 2.6
 
710
   */
 
711
  g_object_class_install_property (gobject_class,
 
712
                                   PROP_MARGIN,
 
713
                                   g_param_spec_int ("margin",
 
714
                                                     P_("Margin"),
 
715
                                                     P_("Space which is inserted at the edges of the icon view"),
 
716
                                                     0, G_MAXINT, 6,
 
717
                                                     GTK_PARAM_READWRITE));
 
718
 
 
719
  /**
 
720
   * GtkIconView:orientation:
 
721
   *
 
722
   * The orientation property specifies how the cells (i.e. the icon and 
 
723
   * the text) of the item are positioned relative to each other.
 
724
   *
 
725
   * Since: 2.6
 
726
   *
 
727
   * Deprecated: 2.22: Use the #GtkIconView::item-orientation property
 
728
   */
 
729
  g_object_class_install_property (gobject_class,
 
730
                                   PROP_ORIENTATION,
 
731
                                   g_param_spec_enum ("orientation",
 
732
                                                      P_("Orientation"),
 
733
                                                      P_("How the text and icon of each item are positioned relative to each other"),
 
734
                                                      GTK_TYPE_ORIENTATION,
 
735
                                                      GTK_ORIENTATION_VERTICAL,
 
736
                                                      GTK_PARAM_READWRITE | G_PARAM_DEPRECATED));
 
737
 
 
738
  /**
 
739
   * GtkIconView:item-orientation:
 
740
   *
 
741
   * The item-orientation property specifies how the cells (i.e. the icon and
 
742
   * the text) of the item are positioned relative to each other.
 
743
   *
 
744
   * Since: 2.22
 
745
   */
 
746
  g_object_class_install_property (gobject_class,
 
747
                                   PROP_ITEM_ORIENTATION,
 
748
                                   g_param_spec_enum ("item-orientation",
 
749
                                                      P_("Item Orientation"),
 
750
                                                      P_("How the text and icon of each item are positioned relative to each other"),
 
751
                                                      GTK_TYPE_ORIENTATION,
 
752
                                                      GTK_ORIENTATION_VERTICAL,
 
753
                                                      GTK_PARAM_READWRITE));
 
754
 
 
755
  /**
 
756
   * GtkIconView:reorderable:
 
757
   *
 
758
   * The reorderable property specifies if the items can be reordered
 
759
   * by DND.
 
760
   *
 
761
   * Since: 2.8
 
762
   */
 
763
  g_object_class_install_property (gobject_class,
 
764
                                   PROP_REORDERABLE,
 
765
                                   g_param_spec_boolean ("reorderable",
 
766
                                                         P_("Reorderable"),
 
767
                                                         P_("View is reorderable"),
 
768
                                                         FALSE,
 
769
                                                         G_PARAM_READWRITE));
 
770
 
 
771
    g_object_class_install_property (gobject_class,
 
772
                                     PROP_TOOLTIP_COLUMN,
 
773
                                     g_param_spec_int ("tooltip-column",
 
774
                                                       P_("Tooltip Column"),
 
775
                                                       P_("The column in the model containing the tooltip texts for the items"),
 
776
                                                       -1,
 
777
                                                       G_MAXINT,
 
778
                                                       -1,
 
779
                                                       GTK_PARAM_READWRITE));
 
780
 
 
781
  /**
 
782
   * GtkIconView:item-padding:
 
783
   *
 
784
   * The item-padding property specifies the padding around each
 
785
   * of the icon view's item.
 
786
   *
 
787
   * Since: 2.18
 
788
   */
 
789
  g_object_class_install_property (gobject_class,
 
790
                                   PROP_ITEM_PADDING,
 
791
                                   g_param_spec_int ("item-padding",
 
792
                                                     P_("Item Padding"),
 
793
                                                     P_("Padding around icon view items"),
 
794
                                                     0, G_MAXINT, 6,
 
795
                                                     GTK_PARAM_READWRITE));
 
796
 
 
797
 
 
798
 
 
799
  /* Style properties */
 
800
  gtk_widget_class_install_style_property (widget_class,
 
801
                                           g_param_spec_boxed ("selection-box-color",
 
802
                                                               P_("Selection Box Color"),
 
803
                                                               P_("Color of the selection box"),
 
804
                                                               GDK_TYPE_COLOR,
 
805
                                                               GTK_PARAM_READABLE));
 
806
 
 
807
  gtk_widget_class_install_style_property (widget_class,
 
808
                                           g_param_spec_uchar ("selection-box-alpha",
 
809
                                                               P_("Selection Box Alpha"),
 
810
                                                               P_("Opacity of the selection box"),
 
811
                                                               0, 0xff,
 
812
                                                               0x40,
 
813
                                                               GTK_PARAM_READABLE));
 
814
 
 
815
  /* Signals */
 
816
  /**
 
817
   * GtkIconView::set-scroll-adjustments
 
818
   * @horizontal: the horizontal #GtkAdjustment
 
819
   * @vertical: the vertical #GtkAdjustment
 
820
   *
 
821
   * Set the scroll adjustments for the icon view. Usually scrolled containers
 
822
   * like #GtkScrolledWindow will emit this signal to connect two instances
 
823
   * of #GtkScrollbar to the scroll directions of the #GtkIconView.
 
824
   */
 
825
  widget_class->set_scroll_adjustments_signal =
 
826
    g_signal_new (I_("set-scroll-adjustments"),
 
827
                  G_TYPE_FROM_CLASS (gobject_class),
 
828
                  G_SIGNAL_RUN_LAST,
 
829
                  G_STRUCT_OFFSET (GtkIconViewClass, set_scroll_adjustments),
 
830
                  NULL, NULL, 
 
831
                  _gtk_marshal_VOID__OBJECT_OBJECT,
 
832
                  G_TYPE_NONE, 2,
 
833
                  GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
 
834
 
 
835
  /**
 
836
   * GtkIconView::item-activated:
 
837
   * @iconview: the object on which the signal is emitted
 
838
   * @path: the #GtkTreePath for the activated item
 
839
   *
 
840
   * The ::item-activated signal is emitted when the method
 
841
   * gtk_icon_view_item_activated() is called or the user double 
 
842
   * clicks an item. It is also emitted when a non-editable item
 
843
   * is selected and one of the keys: Space, Return or Enter is
 
844
   * pressed.
 
845
   */
 
846
  icon_view_signals[ITEM_ACTIVATED] =
 
847
    g_signal_new (I_("item-activated"),
 
848
                  G_TYPE_FROM_CLASS (gobject_class),
 
849
                  G_SIGNAL_RUN_LAST,
 
850
                  G_STRUCT_OFFSET (GtkIconViewClass, item_activated),
 
851
                  NULL, NULL,
 
852
                  g_cclosure_marshal_VOID__BOXED,
 
853
                  G_TYPE_NONE, 1,
 
854
                  GTK_TYPE_TREE_PATH);
 
855
 
 
856
  /**
 
857
   * GtkIconView::selection-changed:
 
858
   * @iconview: the object on which the signal is emitted
 
859
   *
 
860
   * The ::selection-changed signal is emitted when the selection
 
861
   * (i.e. the set of selected items) changes.
 
862
   */
 
863
  icon_view_signals[SELECTION_CHANGED] =
 
864
    g_signal_new (I_("selection-changed"),
 
865
                  G_TYPE_FROM_CLASS (gobject_class),
 
866
                  G_SIGNAL_RUN_FIRST,
 
867
                  G_STRUCT_OFFSET (GtkIconViewClass, selection_changed),
 
868
                  NULL, NULL,
 
869
                  g_cclosure_marshal_VOID__VOID,
 
870
                  G_TYPE_NONE, 0);
 
871
  
 
872
  /**
 
873
   * GtkIconView::select-all:
 
874
   * @iconview: the object on which the signal is emitted
 
875
   *
 
876
   * A <link linkend="keybinding-signals">keybinding signal</link>
 
877
   * which gets emitted when the user selects all items.
 
878
   *
 
879
   * Applications should not connect to it, but may emit it with
 
880
   * g_signal_emit_by_name() if they need to control selection
 
881
   * programmatically.
 
882
   * 
 
883
   * The default binding for this signal is Ctrl-a.
 
884
   */
 
885
  icon_view_signals[SELECT_ALL] =
 
886
    g_signal_new (I_("select-all"),
 
887
                  G_TYPE_FROM_CLASS (gobject_class),
 
888
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
889
                  G_STRUCT_OFFSET (GtkIconViewClass, select_all),
 
890
                  NULL, NULL,
 
891
                  g_cclosure_marshal_VOID__VOID,
 
892
                  G_TYPE_NONE, 0);
 
893
  
 
894
  /**
 
895
   * GtkIconView::unselect-all:
 
896
   * @iconview: the object on which the signal is emitted
 
897
   *
 
898
   * A <link linkend="keybinding-signals">keybinding signal</link>
 
899
   * which gets emitted when the user unselects all items.
 
900
   *
 
901
   * Applications should not connect to it, but may emit it with
 
902
   * g_signal_emit_by_name() if they need to control selection
 
903
   * programmatically.
 
904
   * 
 
905
   * The default binding for this signal is Ctrl-Shift-a. 
 
906
   */
 
907
  icon_view_signals[UNSELECT_ALL] =
 
908
    g_signal_new (I_("unselect-all"),
 
909
                  G_TYPE_FROM_CLASS (gobject_class),
 
910
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
911
                  G_STRUCT_OFFSET (GtkIconViewClass, unselect_all),
 
912
                  NULL, NULL,
 
913
                  g_cclosure_marshal_VOID__VOID,
 
914
                  G_TYPE_NONE, 0);
 
915
 
 
916
  /**
 
917
   * GtkIconView::select-cursor-item:
 
918
   * @iconview: the object on which the signal is emitted
 
919
   *
 
920
   * A <link linkend="keybinding-signals">keybinding signal</link>
 
921
   * which gets emitted when the user selects the item that is currently
 
922
   * focused.
 
923
   *
 
924
   * Applications should not connect to it, but may emit it with
 
925
   * g_signal_emit_by_name() if they need to control selection
 
926
   * programmatically.
 
927
   * 
 
928
   * There is no default binding for this signal.
 
929
   */
 
930
  icon_view_signals[SELECT_CURSOR_ITEM] =
 
931
    g_signal_new (I_("select-cursor-item"),
 
932
                  G_TYPE_FROM_CLASS (gobject_class),
 
933
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
934
                  G_STRUCT_OFFSET (GtkIconViewClass, select_cursor_item),
 
935
                  NULL, NULL,
 
936
                  g_cclosure_marshal_VOID__VOID,
 
937
                  G_TYPE_NONE, 0);
 
938
 
 
939
  /**
 
940
   * GtkIconView::toggle-cursor-item:
 
941
   * @iconview: the object on which the signal is emitted
 
942
   *
 
943
   * A <link linkend="keybinding-signals">keybinding signal</link>
 
944
   * which gets emitted when the user toggles whether the currently
 
945
   * focused item is selected or not. The exact effect of this 
 
946
   * depend on the selection mode.
 
947
   *
 
948
   * Applications should not connect to it, but may emit it with
 
949
   * g_signal_emit_by_name() if they need to control selection
 
950
   * programmatically.
 
951
   * 
 
952
   * There is no default binding for this signal is Ctrl-Space.
 
953
   */
 
954
  icon_view_signals[TOGGLE_CURSOR_ITEM] =
 
955
    g_signal_new (I_("toggle-cursor-item"),
 
956
                  G_TYPE_FROM_CLASS (gobject_class),
 
957
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
958
                  G_STRUCT_OFFSET (GtkIconViewClass, toggle_cursor_item),
 
959
                  NULL, NULL,
 
960
                  g_cclosure_marshal_VOID__VOID,
 
961
                  G_TYPE_NONE, 0);
 
962
 
 
963
  /**
 
964
   * GtkIconView::activate-cursor-item:
 
965
   * @iconview: the object on which the signal is emitted
 
966
   *
 
967
   * A <link linkend="keybinding-signals">keybinding signal</link>
 
968
   * which gets emitted when the user activates the currently 
 
969
   * focused item. 
 
970
   *
 
971
   * Applications should not connect to it, but may emit it with
 
972
   * g_signal_emit_by_name() if they need to control activation
 
973
   * programmatically.
 
974
   * 
 
975
   * The default bindings for this signal are Space, Return and Enter.
 
976
   */
 
977
  icon_view_signals[ACTIVATE_CURSOR_ITEM] =
 
978
    g_signal_new (I_("activate-cursor-item"),
 
979
                  G_TYPE_FROM_CLASS (gobject_class),
 
980
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
981
                  G_STRUCT_OFFSET (GtkIconViewClass, activate_cursor_item),
 
982
                  NULL, NULL,
 
983
                  _gtk_marshal_BOOLEAN__VOID,
 
984
                  G_TYPE_BOOLEAN, 0);
 
985
  
 
986
  /**
 
987
   * GtkIconView::move-cursor:
 
988
   * @iconview: the object which received the signal
 
989
   * @step: the granularity of the move, as a #GtkMovementStep
 
990
   * @count: the number of @step units to move
 
991
   *
 
992
   * The ::move-cursor signal is a
 
993
   * <link linkend="keybinding-signals">keybinding signal</link>
 
994
   * which gets emitted when the user initiates a cursor movement.
 
995
   *
 
996
   * Applications should not connect to it, but may emit it with
 
997
   * g_signal_emit_by_name() if they need to control the cursor
 
998
   * programmatically.
 
999
   *
 
1000
   * The default bindings for this signal include
 
1001
   * <itemizedlist>
 
1002
   * <listitem>Arrow keys which move by individual steps</listitem>
 
1003
   * <listitem>Home/End keys which move to the first/last item</listitem>
 
1004
   * <listitem>PageUp/PageDown which move by "pages"</listitem>
 
1005
   * </itemizedlist>
 
1006
   *
 
1007
   * All of these will extend the selection when combined with
 
1008
   * the Shift modifier.
 
1009
   */
 
1010
  icon_view_signals[MOVE_CURSOR] =
 
1011
    g_signal_new (I_("move-cursor"),
 
1012
                  G_TYPE_FROM_CLASS (gobject_class),
 
1013
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
1014
                  G_STRUCT_OFFSET (GtkIconViewClass, move_cursor),
 
1015
                  NULL, NULL,
 
1016
                  _gtk_marshal_BOOLEAN__ENUM_INT,
 
1017
                  G_TYPE_BOOLEAN, 2,
 
1018
                  GTK_TYPE_MOVEMENT_STEP,
 
1019
                  G_TYPE_INT);
 
1020
 
 
1021
  /* Key bindings */
 
1022
  gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK, 
 
1023
                                "select-all", 0);
 
1024
  gtk_binding_entry_add_signal (binding_set, GDK_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK, 
 
1025
                                "unselect-all", 0);
 
1026
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK, 
 
1027
                                "toggle-cursor-item", 0);
 
1028
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
 
1029
                                "toggle-cursor-item", 0);
 
1030
 
 
1031
  gtk_binding_entry_add_signal (binding_set, GDK_space, 0, 
 
1032
                                "activate-cursor-item", 0);
 
1033
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
 
1034
                                "activate-cursor-item", 0);
 
1035
  gtk_binding_entry_add_signal (binding_set, GDK_Return, 0, 
 
1036
                                "activate-cursor-item", 0);
 
1037
  gtk_binding_entry_add_signal (binding_set, GDK_ISO_Enter, 0, 
 
1038
                                "activate-cursor-item", 0);
 
1039
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Enter, 0, 
 
1040
                                "activate-cursor-item", 0);
 
1041
 
 
1042
  gtk_icon_view_add_move_binding (binding_set, GDK_Up, 0,
 
1043
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
1044
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Up, 0,
 
1045
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
1046
 
 
1047
  gtk_icon_view_add_move_binding (binding_set, GDK_Down, 0,
 
1048
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
1049
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Down, 0,
 
1050
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
1051
 
 
1052
  gtk_icon_view_add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
 
1053
                                  GTK_MOVEMENT_DISPLAY_LINES, -1);
 
1054
 
 
1055
  gtk_icon_view_add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
 
1056
                                  GTK_MOVEMENT_DISPLAY_LINES, 1);
 
1057
 
 
1058
  gtk_icon_view_add_move_binding (binding_set, GDK_Home, 0,
 
1059
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
 
1060
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Home, 0,
 
1061
                                  GTK_MOVEMENT_BUFFER_ENDS, -1);
 
1062
 
 
1063
  gtk_icon_view_add_move_binding (binding_set, GDK_End, 0,
 
1064
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
 
1065
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_End, 0,
 
1066
                                  GTK_MOVEMENT_BUFFER_ENDS, 1);
 
1067
 
 
1068
  gtk_icon_view_add_move_binding (binding_set, GDK_Page_Up, 0,
 
1069
                                  GTK_MOVEMENT_PAGES, -1);
 
1070
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Up, 0,
 
1071
                                  GTK_MOVEMENT_PAGES, -1);
 
1072
 
 
1073
  gtk_icon_view_add_move_binding (binding_set, GDK_Page_Down, 0,
 
1074
                                  GTK_MOVEMENT_PAGES, 1);
 
1075
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Page_Down, 0,
 
1076
                                  GTK_MOVEMENT_PAGES, 1);
 
1077
 
 
1078
  gtk_icon_view_add_move_binding (binding_set, GDK_Right, 0, 
 
1079
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
 
1080
  gtk_icon_view_add_move_binding (binding_set, GDK_Left, 0, 
 
1081
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
1082
 
 
1083
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Right, 0, 
 
1084
                                  GTK_MOVEMENT_VISUAL_POSITIONS, 1);
 
1085
  gtk_icon_view_add_move_binding (binding_set, GDK_KP_Left, 0, 
 
1086
                                  GTK_MOVEMENT_VISUAL_POSITIONS, -1);
 
1087
}
 
1088
 
 
1089
static void
 
1090
gtk_icon_view_buildable_init (GtkBuildableIface *iface)
 
1091
{
 
1092
  parent_buildable_iface = g_type_interface_peek_parent (iface);
 
1093
  iface->add_child = _gtk_cell_layout_buildable_add_child;
 
1094
  iface->custom_tag_start = gtk_icon_view_buildable_custom_tag_start;
 
1095
  iface->custom_tag_end = gtk_icon_view_buildable_custom_tag_end;
 
1096
}
 
1097
 
 
1098
static void
 
1099
gtk_icon_view_cell_layout_init (GtkCellLayoutIface *iface)
 
1100
{
 
1101
  iface->pack_start = gtk_icon_view_cell_layout_pack_start;
 
1102
  iface->pack_end = gtk_icon_view_cell_layout_pack_end;
 
1103
  iface->clear = gtk_icon_view_cell_layout_clear;
 
1104
  iface->add_attribute = gtk_icon_view_cell_layout_add_attribute;
 
1105
  iface->set_cell_data_func = gtk_icon_view_cell_layout_set_cell_data_func;
 
1106
  iface->clear_attributes = gtk_icon_view_cell_layout_clear_attributes;
 
1107
  iface->reorder = gtk_icon_view_cell_layout_reorder;
 
1108
  iface->get_cells = gtk_icon_view_cell_layout_get_cells;
 
1109
}
 
1110
 
 
1111
static void
 
1112
gtk_icon_view_init (GtkIconView *icon_view)
 
1113
{
 
1114
  icon_view->priv = GTK_ICON_VIEW_GET_PRIVATE (icon_view);
 
1115
  
 
1116
  icon_view->priv->width = 0;
 
1117
  icon_view->priv->height = 0;
 
1118
  icon_view->priv->selection_mode = GTK_SELECTION_SINGLE;
 
1119
  icon_view->priv->pressed_button = -1;
 
1120
  icon_view->priv->press_start_x = -1;
 
1121
  icon_view->priv->press_start_y = -1;
 
1122
  icon_view->priv->text_column = -1;
 
1123
  icon_view->priv->markup_column = -1;  
 
1124
  icon_view->priv->pixbuf_column = -1;
 
1125
  icon_view->priv->text_cell = -1;
 
1126
  icon_view->priv->pixbuf_cell = -1;  
 
1127
  icon_view->priv->tooltip_column = -1;  
 
1128
 
 
1129
  gtk_widget_set_can_focus (GTK_WIDGET (icon_view), TRUE);
 
1130
  
 
1131
  gtk_icon_view_set_adjustments (icon_view, NULL, NULL);
 
1132
 
 
1133
  icon_view->priv->cell_list = NULL;
 
1134
  icon_view->priv->n_cells = 0;
 
1135
  icon_view->priv->cursor_cell = -1;
 
1136
 
 
1137
  icon_view->priv->item_orientation = GTK_ORIENTATION_VERTICAL;
 
1138
 
 
1139
  icon_view->priv->columns = -1;
 
1140
  icon_view->priv->item_width = -1;
 
1141
  icon_view->priv->spacing = 0;
 
1142
  icon_view->priv->row_spacing = 6;
 
1143
  icon_view->priv->column_spacing = 6;
 
1144
  icon_view->priv->margin = 6;
 
1145
  icon_view->priv->item_padding = 6;
 
1146
 
 
1147
  icon_view->priv->draw_focus = TRUE;
 
1148
}
 
1149
 
 
1150
static void
 
1151
gtk_icon_view_destroy (GtkObject *object)
 
1152
{
 
1153
  GtkIconView *icon_view;
 
1154
 
 
1155
  icon_view = GTK_ICON_VIEW (object);
 
1156
  
 
1157
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
1158
 
 
1159
  gtk_icon_view_set_model (icon_view, NULL);
 
1160
  
 
1161
  if (icon_view->priv->layout_idle_id != 0)
 
1162
    {
 
1163
      g_source_remove (icon_view->priv->layout_idle_id);
 
1164
      icon_view->priv->layout_idle_id = 0;
 
1165
    }
 
1166
 
 
1167
  if (icon_view->priv->scroll_to_path != NULL)
 
1168
    {
 
1169
      gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
 
1170
      icon_view->priv->scroll_to_path = NULL;
 
1171
    }
 
1172
 
 
1173
  remove_scroll_timeout (icon_view);
 
1174
 
 
1175
  if (icon_view->priv->hadjustment != NULL)
 
1176
    {
 
1177
      g_object_unref (icon_view->priv->hadjustment);
 
1178
      icon_view->priv->hadjustment = NULL;
 
1179
    }
 
1180
 
 
1181
  if (icon_view->priv->vadjustment != NULL)
 
1182
    {
 
1183
      g_object_unref (icon_view->priv->vadjustment);
 
1184
      icon_view->priv->vadjustment = NULL;
 
1185
    }
 
1186
  
 
1187
  GTK_OBJECT_CLASS (gtk_icon_view_parent_class)->destroy (object);
 
1188
}
 
1189
 
 
1190
/* GObject methods */
 
1191
static void
 
1192
gtk_icon_view_finalize (GObject *object)
 
1193
{
 
1194
  gtk_icon_view_cell_layout_clear (GTK_CELL_LAYOUT (object));
 
1195
 
 
1196
  G_OBJECT_CLASS (gtk_icon_view_parent_class)->finalize (object);
 
1197
}
 
1198
 
 
1199
 
 
1200
static void
 
1201
gtk_icon_view_set_property (GObject      *object,
 
1202
                            guint         prop_id,
 
1203
                            const GValue *value,
 
1204
                            GParamSpec   *pspec)
 
1205
{
 
1206
  GtkIconView *icon_view;
 
1207
 
 
1208
  icon_view = GTK_ICON_VIEW (object);
 
1209
 
 
1210
  switch (prop_id)
 
1211
    {
 
1212
    case PROP_SELECTION_MODE:
 
1213
      gtk_icon_view_set_selection_mode (icon_view, g_value_get_enum (value));
 
1214
      break;
 
1215
    case PROP_PIXBUF_COLUMN:
 
1216
      gtk_icon_view_set_pixbuf_column (icon_view, g_value_get_int (value));
 
1217
      break;
 
1218
    case PROP_TEXT_COLUMN:
 
1219
      gtk_icon_view_set_text_column (icon_view, g_value_get_int (value));
 
1220
      break;
 
1221
    case PROP_MARKUP_COLUMN:
 
1222
      gtk_icon_view_set_markup_column (icon_view, g_value_get_int (value));
 
1223
      break;
 
1224
    case PROP_MODEL:
 
1225
      gtk_icon_view_set_model (icon_view, g_value_get_object (value));
 
1226
      break;
 
1227
    case PROP_ORIENTATION:
 
1228
    case PROP_ITEM_ORIENTATION:
 
1229
      gtk_icon_view_set_item_orientation (icon_view, g_value_get_enum (value));
 
1230
      break;
 
1231
    case PROP_COLUMNS:
 
1232
      gtk_icon_view_set_columns (icon_view, g_value_get_int (value));
 
1233
      break;
 
1234
    case PROP_ITEM_WIDTH:
 
1235
      gtk_icon_view_set_item_width (icon_view, g_value_get_int (value));
 
1236
      break;
 
1237
    case PROP_SPACING:
 
1238
      gtk_icon_view_set_spacing (icon_view, g_value_get_int (value));
 
1239
      break;
 
1240
    case PROP_ROW_SPACING:
 
1241
      gtk_icon_view_set_row_spacing (icon_view, g_value_get_int (value));
 
1242
      break;
 
1243
    case PROP_COLUMN_SPACING:
 
1244
      gtk_icon_view_set_column_spacing (icon_view, g_value_get_int (value));
 
1245
      break;
 
1246
    case PROP_MARGIN:
 
1247
      gtk_icon_view_set_margin (icon_view, g_value_get_int (value));
 
1248
      break;
 
1249
    case PROP_REORDERABLE:
 
1250
      gtk_icon_view_set_reorderable (icon_view, g_value_get_boolean (value));
 
1251
      break;
 
1252
      
 
1253
    case PROP_TOOLTIP_COLUMN:
 
1254
      gtk_icon_view_set_tooltip_column (icon_view, g_value_get_int (value));
 
1255
      break;
 
1256
 
 
1257
    case PROP_ITEM_PADDING:
 
1258
      gtk_icon_view_set_item_padding (icon_view, g_value_get_int (value));
 
1259
      break;
 
1260
 
 
1261
    default:
 
1262
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
1263
      break;
 
1264
    }
 
1265
}
 
1266
 
 
1267
static void
 
1268
gtk_icon_view_get_property (GObject      *object,
 
1269
                            guint         prop_id,
 
1270
                            GValue       *value,
 
1271
                            GParamSpec   *pspec)
 
1272
{
 
1273
  GtkIconView *icon_view;
 
1274
 
 
1275
  icon_view = GTK_ICON_VIEW (object);
 
1276
 
 
1277
  switch (prop_id)
 
1278
    {
 
1279
    case PROP_SELECTION_MODE:
 
1280
      g_value_set_enum (value, icon_view->priv->selection_mode);
 
1281
      break;
 
1282
    case PROP_PIXBUF_COLUMN:
 
1283
      g_value_set_int (value, icon_view->priv->pixbuf_column);
 
1284
      break;
 
1285
    case PROP_TEXT_COLUMN:
 
1286
      g_value_set_int (value, icon_view->priv->text_column);
 
1287
      break;
 
1288
    case PROP_MARKUP_COLUMN:
 
1289
      g_value_set_int (value, icon_view->priv->markup_column);
 
1290
      break;
 
1291
    case PROP_MODEL:
 
1292
      g_value_set_object (value, icon_view->priv->model);
 
1293
      break;
 
1294
    case PROP_ORIENTATION:
 
1295
    case PROP_ITEM_ORIENTATION:
 
1296
      g_value_set_enum (value, icon_view->priv->item_orientation);
 
1297
      break;
 
1298
    case PROP_COLUMNS:
 
1299
      g_value_set_int (value, icon_view->priv->columns);
 
1300
      break;
 
1301
    case PROP_ITEM_WIDTH:
 
1302
      g_value_set_int (value, icon_view->priv->item_width);
 
1303
      break;
 
1304
    case PROP_SPACING:
 
1305
      g_value_set_int (value, icon_view->priv->spacing);
 
1306
      break;
 
1307
    case PROP_ROW_SPACING:
 
1308
      g_value_set_int (value, icon_view->priv->row_spacing);
 
1309
      break;
 
1310
    case PROP_COLUMN_SPACING:
 
1311
      g_value_set_int (value, icon_view->priv->column_spacing);
 
1312
      break;
 
1313
    case PROP_MARGIN:
 
1314
      g_value_set_int (value, icon_view->priv->margin);
 
1315
      break;
 
1316
    case PROP_REORDERABLE:
 
1317
      g_value_set_boolean (value, icon_view->priv->reorderable);
 
1318
      break;
 
1319
    case PROP_TOOLTIP_COLUMN:
 
1320
      g_value_set_int (value, icon_view->priv->tooltip_column);
 
1321
      break;
 
1322
 
 
1323
    case PROP_ITEM_PADDING:
 
1324
      g_value_set_int (value, icon_view->priv->item_padding);
 
1325
      break;
 
1326
 
 
1327
    default:
 
1328
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
1329
      break;
 
1330
    }
 
1331
}
 
1332
 
 
1333
/* GtkWidget signals */
 
1334
static void
 
1335
gtk_icon_view_realize (GtkWidget *widget)
 
1336
{
 
1337
  GtkIconView *icon_view;
 
1338
  GdkWindowAttr attributes;
 
1339
  gint attributes_mask;
 
1340
  
 
1341
  icon_view = GTK_ICON_VIEW (widget);
 
1342
 
 
1343
  gtk_widget_set_realized (widget, TRUE);
 
1344
 
 
1345
  /* Make the main, clipping window */
 
1346
  attributes.window_type = GDK_WINDOW_CHILD;
 
1347
  attributes.x = widget->allocation.x;
 
1348
  attributes.y = widget->allocation.y;
 
1349
  attributes.width = widget->allocation.width;
 
1350
  attributes.height = widget->allocation.height;
 
1351
  attributes.wclass = GDK_INPUT_OUTPUT;
 
1352
  attributes.visual = gtk_widget_get_visual (widget);
 
1353
  attributes.colormap = gtk_widget_get_colormap (widget);
 
1354
  attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
 
1355
 
 
1356
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
1357
 
 
1358
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
 
1359
                                   &attributes, attributes_mask);
 
1360
  gdk_window_set_back_pixmap (widget->window, NULL, FALSE);
 
1361
  gdk_window_set_user_data (widget->window, widget);
 
1362
 
 
1363
  /* Make the window for the icon view */
 
1364
  attributes.x = 0;
 
1365
  attributes.y = 0;
 
1366
  attributes.width = MAX (icon_view->priv->width, widget->allocation.width);
 
1367
  attributes.height = MAX (icon_view->priv->height, widget->allocation.height);
 
1368
  attributes.event_mask = (GDK_EXPOSURE_MASK |
 
1369
                           GDK_SCROLL_MASK |
 
1370
                           GDK_POINTER_MOTION_MASK |
 
1371
                           GDK_BUTTON_PRESS_MASK |
 
1372
                           GDK_BUTTON_RELEASE_MASK |
 
1373
                           GDK_KEY_PRESS_MASK |
 
1374
                           GDK_KEY_RELEASE_MASK) |
 
1375
    gtk_widget_get_events (widget);
 
1376
  
 
1377
  icon_view->priv->bin_window = gdk_window_new (widget->window,
 
1378
                                                &attributes, attributes_mask);
 
1379
  gdk_window_set_user_data (icon_view->priv->bin_window, widget);
 
1380
 
 
1381
  widget->style = gtk_style_attach (widget->style, widget->window);
 
1382
  gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]);
 
1383
 
 
1384
  gdk_window_show (icon_view->priv->bin_window);
 
1385
}
 
1386
 
 
1387
static void
 
1388
gtk_icon_view_unrealize (GtkWidget *widget)
 
1389
{
 
1390
  GtkIconView *icon_view;
 
1391
 
 
1392
  icon_view = GTK_ICON_VIEW (widget);
 
1393
 
 
1394
  gdk_window_set_user_data (icon_view->priv->bin_window, NULL);
 
1395
  gdk_window_destroy (icon_view->priv->bin_window);
 
1396
  icon_view->priv->bin_window = NULL;
 
1397
 
 
1398
  GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->unrealize (widget);
 
1399
}
 
1400
 
 
1401
static void
 
1402
gtk_icon_view_state_changed (GtkWidget      *widget,
 
1403
                             GtkStateType    previous_state)
 
1404
{
 
1405
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
1406
 
 
1407
  if (gtk_widget_get_realized (widget))
 
1408
    {
 
1409
      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
 
1410
      gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]);
 
1411
    }
 
1412
 
 
1413
  gtk_widget_queue_draw (widget);
 
1414
}
 
1415
 
 
1416
static void
 
1417
gtk_icon_view_style_set (GtkWidget *widget,
 
1418
                         GtkStyle *previous_style)
 
1419
{
 
1420
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
1421
 
 
1422
  if (gtk_widget_get_realized (widget))
 
1423
    {
 
1424
      gdk_window_set_background (widget->window, &widget->style->base[widget->state]);
 
1425
      gdk_window_set_background (icon_view->priv->bin_window, &widget->style->base[widget->state]);
 
1426
    }
 
1427
 
 
1428
  gtk_widget_queue_resize (widget);
 
1429
}
 
1430
 
 
1431
static void
 
1432
gtk_icon_view_size_request (GtkWidget      *widget,
 
1433
                            GtkRequisition *requisition)
 
1434
{
 
1435
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
1436
  GList *tmp_list;
 
1437
 
 
1438
  requisition->width = icon_view->priv->width;
 
1439
  requisition->height = icon_view->priv->height;
 
1440
 
 
1441
  tmp_list = icon_view->priv->children;
 
1442
 
 
1443
  while (tmp_list)
 
1444
    {
 
1445
      GtkIconViewChild *child = tmp_list->data;
 
1446
      GtkRequisition child_requisition;
 
1447
 
 
1448
      tmp_list = tmp_list->next;
 
1449
 
 
1450
      if (gtk_widget_get_visible (child->widget))
 
1451
        gtk_widget_size_request (child->widget, &child_requisition);
 
1452
    }  
 
1453
}
 
1454
 
 
1455
static void
 
1456
gtk_icon_view_allocate_children (GtkIconView *icon_view)
 
1457
{
 
1458
  GList *list;
 
1459
 
 
1460
  for (list = icon_view->priv->children; list; list = list->next)
 
1461
    {
 
1462
      GtkIconViewChild *child = list->data;
 
1463
      GtkAllocation allocation;
 
1464
 
 
1465
      /* totally ignore our child's requisition */
 
1466
      if (child->cell < 0)
 
1467
        {
 
1468
          allocation.x = child->item->x + icon_view->priv->item_padding;
 
1469
          allocation.y = child->item->y + icon_view->priv->item_padding;
 
1470
          allocation.width = child->item->width - icon_view->priv->item_padding * 2;
 
1471
          allocation.height = child->item->height - icon_view->priv->item_padding * 2;
 
1472
        }
 
1473
      else
 
1474
        {
 
1475
          GdkRectangle *box = &child->item->box[child->cell];
 
1476
 
 
1477
          allocation.x = box->x;
 
1478
          allocation.y = box->y;
 
1479
          allocation.width = box->width;
 
1480
          allocation.height = box->height;
 
1481
        }
 
1482
 
 
1483
      gtk_widget_size_allocate (child->widget, &allocation);
 
1484
    }
 
1485
}
 
1486
 
 
1487
static void
 
1488
gtk_icon_view_size_allocate (GtkWidget      *widget,
 
1489
                             GtkAllocation  *allocation)
 
1490
{
 
1491
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
1492
 
 
1493
  GtkAdjustment *hadjustment, *vadjustment;
 
1494
 
 
1495
  widget->allocation = *allocation;
 
1496
  
 
1497
  if (gtk_widget_get_realized (widget))
 
1498
    {
 
1499
      gdk_window_move_resize (widget->window,
 
1500
                              allocation->x, allocation->y,
 
1501
                              allocation->width, allocation->height);
 
1502
      gdk_window_resize (icon_view->priv->bin_window,
 
1503
                         MAX (icon_view->priv->width, allocation->width),
 
1504
                         MAX (icon_view->priv->height, allocation->height));
 
1505
    }
 
1506
 
 
1507
  gtk_icon_view_layout (icon_view);
 
1508
  
 
1509
  gtk_icon_view_allocate_children (icon_view);
 
1510
 
 
1511
  hadjustment = icon_view->priv->hadjustment;
 
1512
  vadjustment = icon_view->priv->vadjustment;
 
1513
 
 
1514
  hadjustment->page_size = allocation->width;
 
1515
  hadjustment->page_increment = allocation->width * 0.9;
 
1516
  hadjustment->step_increment = allocation->width * 0.1;
 
1517
  hadjustment->lower = 0;
 
1518
  hadjustment->upper = MAX (allocation->width, icon_view->priv->width);
 
1519
 
 
1520
  if (hadjustment->value > hadjustment->upper - hadjustment->page_size)
 
1521
    gtk_adjustment_set_value (hadjustment, MAX (0, hadjustment->upper - hadjustment->page_size));
 
1522
 
 
1523
  vadjustment->page_size = allocation->height;
 
1524
  vadjustment->page_increment = allocation->height * 0.9;
 
1525
  vadjustment->step_increment = allocation->height * 0.1;
 
1526
  vadjustment->lower = 0;
 
1527
  vadjustment->upper = MAX (allocation->height, icon_view->priv->height);
 
1528
 
 
1529
  if (vadjustment->value > vadjustment->upper - vadjustment->page_size)
 
1530
    gtk_adjustment_set_value (vadjustment, MAX (0, vadjustment->upper - vadjustment->page_size));
 
1531
 
 
1532
  if (gtk_widget_get_realized (widget) &&
 
1533
      icon_view->priv->scroll_to_path)
 
1534
    {
 
1535
      GtkTreePath *path;
 
1536
      path = gtk_tree_row_reference_get_path (icon_view->priv->scroll_to_path);
 
1537
      gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
 
1538
      icon_view->priv->scroll_to_path = NULL;
 
1539
 
 
1540
      gtk_icon_view_scroll_to_path (icon_view, path,
 
1541
                                    icon_view->priv->scroll_to_use_align,
 
1542
                                    icon_view->priv->scroll_to_row_align,
 
1543
                                    icon_view->priv->scroll_to_col_align);
 
1544
      gtk_tree_path_free (path);
 
1545
    }
 
1546
  else
 
1547
    {
 
1548
      gtk_adjustment_changed (hadjustment);
 
1549
      gtk_adjustment_changed (vadjustment);
 
1550
    }
 
1551
}
 
1552
 
 
1553
static gboolean
 
1554
gtk_icon_view_expose (GtkWidget *widget,
 
1555
                      GdkEventExpose *expose)
 
1556
{
 
1557
  GtkIconView *icon_view;
 
1558
  GList *icons;
 
1559
  cairo_t *cr;
 
1560
  GtkTreePath *path;
 
1561
  gint dest_index;
 
1562
  GtkIconViewDropPosition dest_pos;
 
1563
  GtkIconViewItem *dest_item = NULL;
 
1564
 
 
1565
  icon_view = GTK_ICON_VIEW (widget);
 
1566
 
 
1567
  if (expose->window != icon_view->priv->bin_window)
 
1568
    return FALSE;
 
1569
 
 
1570
  /* If a layout has been scheduled, do it now so that all
 
1571
   * cell view items have valid sizes before we proceed. */
 
1572
  if (icon_view->priv->layout_idle_id != 0)
 
1573
    gtk_icon_view_layout (icon_view);
 
1574
 
 
1575
  cr = gdk_cairo_create (icon_view->priv->bin_window);
 
1576
  cairo_set_line_width (cr, 1.);
 
1577
 
 
1578
  gtk_icon_view_get_drag_dest_item (icon_view, &path, &dest_pos);
 
1579
 
 
1580
  if (path)
 
1581
    {
 
1582
      dest_index = gtk_tree_path_get_indices (path)[0];
 
1583
      gtk_tree_path_free (path);
 
1584
    }
 
1585
  else
 
1586
    dest_index = -1;
 
1587
 
 
1588
  for (icons = icon_view->priv->items; icons; icons = icons->next) 
 
1589
    {
 
1590
      GtkIconViewItem *item = icons->data;
 
1591
      GdkRectangle area;
 
1592
      
 
1593
      area.x = item->x;
 
1594
      area.y = item->y;
 
1595
      area.width = item->width;
 
1596
      area.height = item->height;
 
1597
        
 
1598
      if (gdk_region_rect_in (expose->region, &area) == GDK_OVERLAP_RECTANGLE_OUT)
 
1599
        continue;
 
1600
      
 
1601
      gtk_icon_view_paint_item (icon_view, cr, item, &expose->area, 
 
1602
                                icon_view->priv->bin_window,
 
1603
                                item->x, item->y,
 
1604
                                icon_view->priv->draw_focus); 
 
1605
 
 
1606
      if (dest_index == item->index)
 
1607
        dest_item = item;
 
1608
    }
 
1609
 
 
1610
  if (dest_item)
 
1611
    {
 
1612
      switch (dest_pos)
 
1613
        {
 
1614
        case GTK_ICON_VIEW_DROP_INTO:
 
1615
          gtk_paint_focus (widget->style,
 
1616
                           icon_view->priv->bin_window,
 
1617
                           gtk_widget_get_state (widget),
 
1618
                           NULL,
 
1619
                           widget,
 
1620
                           "iconview-drop-indicator",
 
1621
                           dest_item->x, dest_item->y,
 
1622
                           dest_item->width, dest_item->height);
 
1623
          break;
 
1624
        case GTK_ICON_VIEW_DROP_ABOVE:
 
1625
          gtk_paint_focus (widget->style,
 
1626
                           icon_view->priv->bin_window,
 
1627
                           gtk_widget_get_state (widget),
 
1628
                           NULL,
 
1629
                           widget,
 
1630
                           "iconview-drop-indicator",
 
1631
                           dest_item->x, dest_item->y - 1,
 
1632
                           dest_item->width, 2);
 
1633
          break;
 
1634
        case GTK_ICON_VIEW_DROP_LEFT:
 
1635
          gtk_paint_focus (widget->style,
 
1636
                           icon_view->priv->bin_window,
 
1637
                           gtk_widget_get_state (widget),
 
1638
                           NULL,
 
1639
                           widget,
 
1640
                           "iconview-drop-indicator",
 
1641
                           dest_item->x - 1, dest_item->y,
 
1642
                           2, dest_item->height);
 
1643
          break;
 
1644
        case GTK_ICON_VIEW_DROP_BELOW:
 
1645
          gtk_paint_focus (widget->style,
 
1646
                           icon_view->priv->bin_window,
 
1647
                           gtk_widget_get_state (widget),
 
1648
                           NULL,
 
1649
                           widget,
 
1650
                           "iconview-drop-indicator",
 
1651
                           dest_item->x, dest_item->y + dest_item->height - 1,
 
1652
                           dest_item->width, 2);
 
1653
          break;
 
1654
        case GTK_ICON_VIEW_DROP_RIGHT:
 
1655
          gtk_paint_focus (widget->style,
 
1656
                           icon_view->priv->bin_window,
 
1657
                           gtk_widget_get_state (widget),
 
1658
                           NULL,
 
1659
                           widget,
 
1660
                           "iconview-drop-indicator",
 
1661
                           dest_item->x + dest_item->width - 1, dest_item->y,
 
1662
                           2, dest_item->height);
 
1663
        case GTK_ICON_VIEW_NO_DROP: ;
 
1664
          break;
 
1665
        }
 
1666
    }
 
1667
  
 
1668
  if (icon_view->priv->doing_rubberband)
 
1669
    {
 
1670
      GdkRectangle *rectangles;
 
1671
      gint n_rectangles;
 
1672
      
 
1673
      gdk_region_get_rectangles (expose->region,
 
1674
                                 &rectangles,
 
1675
                                 &n_rectangles);
 
1676
      
 
1677
      while (n_rectangles--)
 
1678
        gtk_icon_view_paint_rubberband (icon_view, cr, &rectangles[n_rectangles]);
 
1679
 
 
1680
      g_free (rectangles);
 
1681
    }
 
1682
 
 
1683
  cairo_destroy (cr);
 
1684
 
 
1685
  GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->expose_event (widget, expose);
 
1686
 
 
1687
  return TRUE;
 
1688
}
 
1689
 
 
1690
static gboolean
 
1691
rubberband_scroll_timeout (gpointer data)
 
1692
{
 
1693
  GtkIconView *icon_view;
 
1694
  gdouble value;
 
1695
 
 
1696
  icon_view = data;
 
1697
 
 
1698
  value = MIN (icon_view->priv->vadjustment->value +
 
1699
               icon_view->priv->scroll_value_diff,
 
1700
               icon_view->priv->vadjustment->upper -
 
1701
               icon_view->priv->vadjustment->page_size);
 
1702
 
 
1703
  gtk_adjustment_set_value (icon_view->priv->vadjustment, value);
 
1704
 
 
1705
  gtk_icon_view_update_rubberband (icon_view);
 
1706
  
 
1707
  return TRUE;
 
1708
}
 
1709
 
 
1710
static gboolean
 
1711
gtk_icon_view_motion (GtkWidget      *widget,
 
1712
                      GdkEventMotion *event)
 
1713
{
 
1714
  GtkIconView *icon_view;
 
1715
  gint abs_y;
 
1716
  
 
1717
  icon_view = GTK_ICON_VIEW (widget);
 
1718
 
 
1719
  gtk_icon_view_maybe_begin_drag (icon_view, event);
 
1720
 
 
1721
  if (icon_view->priv->doing_rubberband)
 
1722
    {
 
1723
      gtk_icon_view_update_rubberband (widget);
 
1724
      
 
1725
      abs_y = event->y - icon_view->priv->height *
 
1726
        (icon_view->priv->vadjustment->value /
 
1727
         (icon_view->priv->vadjustment->upper -
 
1728
          icon_view->priv->vadjustment->lower));
 
1729
 
 
1730
      if (abs_y < 0 || abs_y > widget->allocation.height)
 
1731
        {
 
1732
          if (abs_y < 0)
 
1733
            icon_view->priv->scroll_value_diff = abs_y;
 
1734
          else
 
1735
            icon_view->priv->scroll_value_diff = abs_y - widget->allocation.height;
 
1736
 
 
1737
          icon_view->priv->event_last_x = event->x;
 
1738
          icon_view->priv->event_last_y = event->y;
 
1739
 
 
1740
          if (icon_view->priv->scroll_timeout_id == 0)
 
1741
            icon_view->priv->scroll_timeout_id = gdk_threads_add_timeout (30, rubberband_scroll_timeout, 
 
1742
                                                                icon_view);
 
1743
        }
 
1744
      else 
 
1745
        remove_scroll_timeout (icon_view);
 
1746
    }
 
1747
  
 
1748
  return TRUE;
 
1749
}
 
1750
 
 
1751
static void
 
1752
gtk_icon_view_remove (GtkContainer *container,
 
1753
                      GtkWidget    *widget)
 
1754
{
 
1755
  GtkIconView *icon_view;
 
1756
  GtkIconViewChild *child = NULL;
 
1757
  GList *tmp_list;
 
1758
 
 
1759
  icon_view = GTK_ICON_VIEW (container);
 
1760
  
 
1761
  tmp_list = icon_view->priv->children;
 
1762
  while (tmp_list)
 
1763
    {
 
1764
      child = tmp_list->data;
 
1765
      if (child->widget == widget)
 
1766
        {
 
1767
          gtk_widget_unparent (widget);
 
1768
 
 
1769
          icon_view->priv->children = g_list_remove_link (icon_view->priv->children, tmp_list);
 
1770
          g_list_free_1 (tmp_list);
 
1771
          g_free (child);
 
1772
          return;
 
1773
        }
 
1774
 
 
1775
      tmp_list = tmp_list->next;
 
1776
    }
 
1777
}
 
1778
 
 
1779
static void
 
1780
gtk_icon_view_forall (GtkContainer *container,
 
1781
                      gboolean      include_internals,
 
1782
                      GtkCallback   callback,
 
1783
                      gpointer      callback_data)
 
1784
{
 
1785
  GtkIconView *icon_view;
 
1786
  GtkIconViewChild *child = NULL;
 
1787
  GList *tmp_list;
 
1788
 
 
1789
  icon_view = GTK_ICON_VIEW (container);
 
1790
 
 
1791
  tmp_list = icon_view->priv->children;
 
1792
  while (tmp_list)
 
1793
    {
 
1794
      child = tmp_list->data;
 
1795
      tmp_list = tmp_list->next;
 
1796
 
 
1797
      (* callback) (child->widget, callback_data);
 
1798
    }
 
1799
}
 
1800
 
 
1801
static void
 
1802
gtk_icon_view_item_activate_cell (GtkIconView         *icon_view, 
 
1803
                                  GtkIconViewItem     *item, 
 
1804
                                  GtkIconViewCellInfo *info,
 
1805
                                  GdkEvent            *event)
 
1806
{
 
1807
  GtkTreePath *path;  
 
1808
  gchar *path_string;
 
1809
  GdkRectangle cell_area;
 
1810
  gboolean visible, mode;
 
1811
 
 
1812
  gtk_icon_view_set_cell_data (icon_view, item);
 
1813
 
 
1814
  g_object_get (info->cell,
 
1815
                "visible", &visible,
 
1816
                "mode", &mode,
 
1817
                NULL);
 
1818
 
 
1819
  if (visible && mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
 
1820
    {
 
1821
      gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
 
1822
 
 
1823
      path = gtk_tree_path_new_from_indices (item->index, -1);
 
1824
      path_string = gtk_tree_path_to_string (path);
 
1825
      gtk_tree_path_free (path);
 
1826
 
 
1827
      gtk_cell_renderer_activate (info->cell, 
 
1828
                                  event, 
 
1829
                                  GTK_WIDGET (icon_view),
 
1830
                                  path_string, 
 
1831
                                  &cell_area, 
 
1832
                                  &cell_area, 
 
1833
                                  0);
 
1834
 
 
1835
      g_free (path_string);      
 
1836
    }
 
1837
}
 
1838
 
 
1839
static void 
 
1840
gtk_icon_view_item_selected_changed (GtkIconView      *icon_view,
 
1841
                                     GtkIconViewItem  *item)
 
1842
{
 
1843
  AtkObject *obj;
 
1844
  AtkObject *item_obj;
 
1845
 
 
1846
  obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
 
1847
  if (obj != NULL)
 
1848
    {
 
1849
      item_obj = atk_object_ref_accessible_child (obj, item->index);
 
1850
      if (item_obj != NULL)
 
1851
        {
 
1852
          atk_object_notify_state_change (item_obj, ATK_STATE_SELECTED, item->selected);
 
1853
          g_object_unref (item_obj);
 
1854
        }
 
1855
    }
 
1856
}
 
1857
 
 
1858
static void 
 
1859
gtk_icon_view_put (GtkIconView     *icon_view,
 
1860
                   GtkWidget       *widget,
 
1861
                   GtkIconViewItem *item,
 
1862
                   gint             cell)
 
1863
{
 
1864
  GtkIconViewChild *child;
 
1865
  
 
1866
  child = g_new (GtkIconViewChild, 1);
 
1867
  
 
1868
  child->widget = widget;
 
1869
  child->item = item;
 
1870
  child->cell = cell;
 
1871
 
 
1872
  icon_view->priv->children = g_list_append (icon_view->priv->children, child);
 
1873
 
 
1874
  if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
 
1875
    gtk_widget_set_parent_window (child->widget, icon_view->priv->bin_window);
 
1876
  
 
1877
  gtk_widget_set_parent (widget, GTK_WIDGET (icon_view));
 
1878
}
 
1879
 
 
1880
static void
 
1881
gtk_icon_view_remove_widget (GtkCellEditable *editable,
 
1882
                             GtkIconView     *icon_view)
 
1883
{
 
1884
  GList *l;
 
1885
  GtkIconViewItem *item;
 
1886
 
 
1887
  if (icon_view->priv->edited_item == NULL)
 
1888
    return;
 
1889
 
 
1890
  item = icon_view->priv->edited_item;
 
1891
  icon_view->priv->edited_item = NULL;
 
1892
  icon_view->priv->editable = NULL;
 
1893
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
1894
    {
 
1895
      GtkIconViewCellInfo *info = l->data;
 
1896
 
 
1897
      info->editing = FALSE;
 
1898
    }
 
1899
 
 
1900
  if (gtk_widget_has_focus (GTK_WIDGET (editable)))
 
1901
    gtk_widget_grab_focus (GTK_WIDGET (icon_view));
 
1902
  
 
1903
  g_signal_handlers_disconnect_by_func (editable,
 
1904
                                        gtk_icon_view_remove_widget,
 
1905
                                        icon_view);
 
1906
 
 
1907
  gtk_container_remove (GTK_CONTAINER (icon_view),
 
1908
                        GTK_WIDGET (editable));  
 
1909
 
 
1910
  gtk_icon_view_queue_draw_item (icon_view, item);
 
1911
}
 
1912
 
 
1913
 
 
1914
static void
 
1915
gtk_icon_view_start_editing (GtkIconView         *icon_view, 
 
1916
                             GtkIconViewItem     *item, 
 
1917
                             GtkIconViewCellInfo *info,
 
1918
                             GdkEvent            *event)
 
1919
{
 
1920
  GtkTreePath *path;  
 
1921
  gchar *path_string;
 
1922
  GdkRectangle cell_area;
 
1923
  gboolean visible, mode;
 
1924
  GtkCellEditable *editable;
 
1925
 
 
1926
  gtk_icon_view_set_cell_data (icon_view, item);
 
1927
 
 
1928
  g_object_get (info->cell,
 
1929
                "visible", &visible,
 
1930
                "mode", &mode,
 
1931
                NULL);
 
1932
  if (visible && mode == GTK_CELL_RENDERER_MODE_EDITABLE)
 
1933
    {
 
1934
      gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
 
1935
 
 
1936
      path = gtk_tree_path_new_from_indices (item->index, -1);
 
1937
      path_string = gtk_tree_path_to_string (path);
 
1938
      gtk_tree_path_free (path);
 
1939
 
 
1940
      editable = gtk_cell_renderer_start_editing (info->cell, 
 
1941
                                                  event, 
 
1942
                                                  GTK_WIDGET (icon_view),
 
1943
                                                  path_string, 
 
1944
                                                  &cell_area, 
 
1945
                                                  &cell_area, 
 
1946
                                                  0);
 
1947
      g_free (path_string);      
 
1948
 
 
1949
      /* the rest corresponds to tree_view_real_start_editing... */
 
1950
      icon_view->priv->edited_item = item;
 
1951
      icon_view->priv->editable = editable;
 
1952
      info->editing = TRUE;
 
1953
 
 
1954
      gtk_icon_view_put (icon_view, GTK_WIDGET (editable), item, 
 
1955
                         info->position);
 
1956
      gtk_cell_editable_start_editing (GTK_CELL_EDITABLE (editable), 
 
1957
                                       (GdkEvent *)event);
 
1958
      gtk_widget_grab_focus (GTK_WIDGET (editable));
 
1959
      g_signal_connect (editable, "remove-widget",
 
1960
                        G_CALLBACK (gtk_icon_view_remove_widget), 
 
1961
                        icon_view);
 
1962
 
 
1963
    }
 
1964
}
 
1965
 
 
1966
static void
 
1967
gtk_icon_view_stop_editing (GtkIconView *icon_view,
 
1968
                            gboolean     cancel_editing)
 
1969
{
 
1970
  GtkCellRenderer *cell = NULL;
 
1971
  GtkIconViewItem *item;
 
1972
  GList *l;
 
1973
 
 
1974
  if (icon_view->priv->edited_item == NULL)
 
1975
    return;
 
1976
 
 
1977
  /*
 
1978
   * This is very evil. We need to do this, because
 
1979
   * gtk_cell_editable_editing_done may trigger gtk_icon_view_row_changed
 
1980
   * later on. If gtk_icon_view_row_changed notices
 
1981
   * icon_view->priv->edited_item != NULL, it'll call
 
1982
   * gtk_icon_view_stop_editing again. Bad things will happen then.
 
1983
   *
 
1984
   * Please read that again if you intend to modify anything here.
 
1985
   */
 
1986
 
 
1987
  item = icon_view->priv->edited_item;
 
1988
  icon_view->priv->edited_item = NULL;
 
1989
 
 
1990
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
1991
    {
 
1992
      GtkIconViewCellInfo *info = l->data;
 
1993
 
 
1994
      if (info->editing)
 
1995
        {
 
1996
          cell = info->cell;
 
1997
          break;
 
1998
        }
 
1999
    }
 
2000
 
 
2001
  if (cell == NULL)
 
2002
    return;
 
2003
 
 
2004
  gtk_cell_renderer_stop_editing (cell, cancel_editing);
 
2005
  if (!cancel_editing)
 
2006
    gtk_cell_editable_editing_done (icon_view->priv->editable);
 
2007
 
 
2008
  icon_view->priv->edited_item = item;
 
2009
 
 
2010
  gtk_cell_editable_remove_widget (icon_view->priv->editable);
 
2011
}
 
2012
 
 
2013
/**
 
2014
 * gtk_icon_view_set_cursor:
 
2015
 * @icon_view: A #GtkIconView
 
2016
 * @path: A #GtkTreePath
 
2017
 * @cell: (allow-none): One of the cell renderers of @icon_view, or %NULL
 
2018
 * @start_editing: %TRUE if the specified cell should start being edited.
 
2019
 *
 
2020
 * Sets the current keyboard focus to be at @path, and selects it.  This is
 
2021
 * useful when you want to focus the user's attention on a particular item.
 
2022
 * If @cell is not %NULL, then focus is given to the cell specified by 
 
2023
 * it. Additionally, if @start_editing is %TRUE, then editing should be 
 
2024
 * started in the specified cell.  
 
2025
 *
 
2026
 * This function is often followed by <literal>gtk_widget_grab_focus 
 
2027
 * (icon_view)</literal> in order to give keyboard focus to the widget.  
 
2028
 * Please note that editing can only happen when the widget is realized.
 
2029
 *
 
2030
 * Since: 2.8
 
2031
 **/
 
2032
void
 
2033
gtk_icon_view_set_cursor (GtkIconView     *icon_view,
 
2034
                          GtkTreePath     *path,
 
2035
                          GtkCellRenderer *cell,
 
2036
                          gboolean         start_editing)
 
2037
{
 
2038
  GtkIconViewItem *item = NULL;
 
2039
  GtkIconViewCellInfo *info =  NULL;
 
2040
  GList *l;
 
2041
  gint i, cell_pos;
 
2042
 
 
2043
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
2044
  g_return_if_fail (path != NULL);
 
2045
  g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
 
2046
 
 
2047
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
2048
 
 
2049
  if (gtk_tree_path_get_depth (path) == 1)
 
2050
    item = g_list_nth_data (icon_view->priv->items,
 
2051
                            gtk_tree_path_get_indices(path)[0]);
 
2052
  
 
2053
  if (!item)
 
2054
    return;
 
2055
 
 
2056
  cell_pos = -1;
 
2057
  for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
2058
    {
 
2059
      info = l->data;
 
2060
      
 
2061
      if (info->cell == cell)
 
2062
        {
 
2063
          cell_pos = i;
 
2064
          break;
 
2065
        }
 
2066
          
 
2067
      info = NULL;
 
2068
    }
 
2069
  
 
2070
  g_return_if_fail (cell == NULL || info != NULL);
 
2071
 
 
2072
  gtk_icon_view_set_cursor_item (icon_view, item, cell_pos);
 
2073
  gtk_icon_view_scroll_to_path (icon_view, path, FALSE, 0.0, 0.0);
 
2074
  
 
2075
  if (info && start_editing)
 
2076
    gtk_icon_view_start_editing (icon_view, item, info, NULL);
 
2077
}
 
2078
 
 
2079
/**
 
2080
 * gtk_icon_view_get_cursor:
 
2081
 * @icon_view: A #GtkIconView
 
2082
 * @path: (allow-none): Return location for the current cursor path, or %NULL
 
2083
 * @cell: (allow-none): Return location the current focus cell, or %NULL
 
2084
 *
 
2085
 * Fills in @path and @cell with the current cursor path and cell. 
 
2086
 * If the cursor isn't currently set, then *@path will be %NULL.  
 
2087
 * If no cell currently has focus, then *@cell will be %NULL.
 
2088
 *
 
2089
 * The returned #GtkTreePath must be freed with gtk_tree_path_free().
 
2090
 *
 
2091
 * Return value: %TRUE if the cursor is set.
 
2092
 *
 
2093
 * Since: 2.8
 
2094
 **/
 
2095
gboolean
 
2096
gtk_icon_view_get_cursor (GtkIconView      *icon_view,
 
2097
                          GtkTreePath     **path,
 
2098
                          GtkCellRenderer **cell)
 
2099
{
 
2100
  GtkIconViewItem *item;
 
2101
  GtkIconViewCellInfo *info;
 
2102
 
 
2103
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
2104
 
 
2105
  item = icon_view->priv->cursor_item;
 
2106
  if (icon_view->priv->cursor_cell < 0)
 
2107
    info = NULL;
 
2108
  else
 
2109
    info = g_list_nth_data (icon_view->priv->cell_list, 
 
2110
                            icon_view->priv->cursor_cell);
 
2111
 
 
2112
  if (path != NULL)
 
2113
    {
 
2114
      if (item != NULL)
 
2115
        *path = gtk_tree_path_new_from_indices (item->index, -1);
 
2116
      else
 
2117
        *path = NULL;
 
2118
    }
 
2119
 
 
2120
  if (cell != NULL)
 
2121
    {
 
2122
      if (info != NULL)
 
2123
        *cell = info->cell;
 
2124
      else 
 
2125
        *cell = NULL;
 
2126
    }
 
2127
 
 
2128
  return (item != NULL);
 
2129
}
 
2130
 
 
2131
static gboolean
 
2132
gtk_icon_view_button_press (GtkWidget      *widget,
 
2133
                            GdkEventButton *event)
 
2134
{
 
2135
  GtkIconView *icon_view;
 
2136
  GtkIconViewItem *item;
 
2137
  GtkIconViewCellInfo *info = NULL;
 
2138
  gboolean dirty = FALSE;
 
2139
  GtkCellRendererMode mode;
 
2140
  gint cursor_cell = -1;
 
2141
 
 
2142
  icon_view = GTK_ICON_VIEW (widget);
 
2143
 
 
2144
  if (event->window != icon_view->priv->bin_window)
 
2145
    return FALSE;
 
2146
 
 
2147
  if (!gtk_widget_has_focus (widget))
 
2148
    gtk_widget_grab_focus (widget);
 
2149
 
 
2150
  if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
 
2151
    {
 
2152
      item = gtk_icon_view_get_item_at_coords (icon_view, 
 
2153
                                               event->x, event->y,
 
2154
                                               FALSE,
 
2155
                                               &info);    
 
2156
 
 
2157
      /*
 
2158
       * We consider only the the cells' area as the item area if the
 
2159
       * item is not selected, but if it *is* selected, the complete
 
2160
       * selection rectangle is considered to be part of the item.
 
2161
       */
 
2162
      if (item != NULL && (info != NULL || item->selected))
 
2163
        {
 
2164
          if (info != NULL)
 
2165
            {
 
2166
              g_object_get (info->cell, "mode", &mode, NULL);
 
2167
 
 
2168
              if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE ||
 
2169
                  mode == GTK_CELL_RENDERER_MODE_EDITABLE)
 
2170
                cursor_cell = g_list_index (icon_view->priv->cell_list, info);
 
2171
            }
 
2172
 
 
2173
          gtk_icon_view_scroll_to_item (icon_view, item);
 
2174
          
 
2175
          if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
 
2176
            {
 
2177
              gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
 
2178
            }
 
2179
          else if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE &&
 
2180
                   (event->state & GTK_EXTEND_SELECTION_MOD_MASK))
 
2181
            {
 
2182
              gtk_icon_view_unselect_all_internal (icon_view);
 
2183
 
 
2184
              gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
 
2185
              if (!icon_view->priv->anchor_item)
 
2186
                icon_view->priv->anchor_item = item;
 
2187
              else 
 
2188
                gtk_icon_view_select_all_between (icon_view,
 
2189
                                                  icon_view->priv->anchor_item,
 
2190
                                                  item);
 
2191
              dirty = TRUE;
 
2192
            }
 
2193
          else 
 
2194
            {
 
2195
              if ((icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE ||
 
2196
                  ((icon_view->priv->selection_mode == GTK_SELECTION_SINGLE) && item->selected)) &&
 
2197
                  (event->state & GTK_MODIFY_SELECTION_MOD_MASK))
 
2198
                {
 
2199
                  item->selected = !item->selected;
 
2200
                  gtk_icon_view_queue_draw_item (icon_view, item);
 
2201
                  dirty = TRUE;
 
2202
                }
 
2203
              else
 
2204
                {
 
2205
                  gtk_icon_view_unselect_all_internal (icon_view);
 
2206
 
 
2207
                  item->selected = TRUE;
 
2208
                  gtk_icon_view_queue_draw_item (icon_view, item);
 
2209
                  dirty = TRUE;
 
2210
                }
 
2211
              gtk_icon_view_set_cursor_item (icon_view, item, cursor_cell);
 
2212
              icon_view->priv->anchor_item = item;
 
2213
            }
 
2214
 
 
2215
          /* Save press to possibly begin a drag */
 
2216
          if (icon_view->priv->pressed_button < 0)
 
2217
            {
 
2218
              icon_view->priv->pressed_button = event->button;
 
2219
              icon_view->priv->press_start_x = event->x;
 
2220
              icon_view->priv->press_start_y = event->y;
 
2221
            }
 
2222
 
 
2223
          if (!icon_view->priv->last_single_clicked)
 
2224
            icon_view->priv->last_single_clicked = item;
 
2225
 
 
2226
          /* cancel the current editing, if it exists */
 
2227
          gtk_icon_view_stop_editing (icon_view, TRUE);
 
2228
 
 
2229
          if (info != NULL)
 
2230
            {
 
2231
              if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
 
2232
                gtk_icon_view_item_activate_cell (icon_view, item, info, 
 
2233
                                                  (GdkEvent *)event);
 
2234
              else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
 
2235
                gtk_icon_view_start_editing (icon_view, item, info, 
 
2236
                                             (GdkEvent *)event);
 
2237
            }
 
2238
        }
 
2239
      else
 
2240
        {
 
2241
          if (icon_view->priv->selection_mode != GTK_SELECTION_BROWSE &&
 
2242
              !(event->state & GTK_MODIFY_SELECTION_MOD_MASK))
 
2243
            {
 
2244
              dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
2245
            }
 
2246
          
 
2247
          if (icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
 
2248
            gtk_icon_view_start_rubberbanding (icon_view, event->x, event->y);
 
2249
        }
 
2250
 
 
2251
      /* don't draw keyboard focus around an clicked-on item */
 
2252
      icon_view->priv->draw_focus = FALSE;
 
2253
    }
 
2254
 
 
2255
  if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
 
2256
    {
 
2257
      item = gtk_icon_view_get_item_at_coords (icon_view,
 
2258
                                               event->x, event->y,
 
2259
                                               FALSE,
 
2260
                                               NULL);
 
2261
 
 
2262
      if (item && item == icon_view->priv->last_single_clicked)
 
2263
        {
 
2264
          GtkTreePath *path;
 
2265
 
 
2266
          path = gtk_tree_path_new_from_indices (item->index, -1);
 
2267
          gtk_icon_view_item_activated (icon_view, path);
 
2268
          gtk_tree_path_free (path);
 
2269
        }
 
2270
 
 
2271
      icon_view->priv->last_single_clicked = NULL;
 
2272
      icon_view->priv->pressed_button = -1;
 
2273
    }
 
2274
  
 
2275
  if (dirty)
 
2276
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
2277
 
 
2278
  return event->button == 1;
 
2279
}
 
2280
 
 
2281
static gboolean
 
2282
gtk_icon_view_button_release (GtkWidget      *widget,
 
2283
                              GdkEventButton *event)
 
2284
{
 
2285
  GtkIconView *icon_view;
 
2286
 
 
2287
  icon_view = GTK_ICON_VIEW (widget);
 
2288
  
 
2289
  if (icon_view->priv->pressed_button == event->button)
 
2290
    icon_view->priv->pressed_button = -1;
 
2291
 
 
2292
  gtk_icon_view_stop_rubberbanding (icon_view);
 
2293
 
 
2294
  remove_scroll_timeout (icon_view);
 
2295
 
 
2296
  return TRUE;
 
2297
}
 
2298
 
 
2299
static gboolean
 
2300
gtk_icon_view_key_press (GtkWidget      *widget,
 
2301
                         GdkEventKey    *event)
 
2302
{
 
2303
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
2304
 
 
2305
  if (icon_view->priv->doing_rubberband)
 
2306
    {
 
2307
      if (event->keyval == GDK_Escape)
 
2308
        gtk_icon_view_stop_rubberbanding (icon_view);
 
2309
 
 
2310
      return TRUE;
 
2311
    }
 
2312
 
 
2313
  return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->key_press_event (widget, event);
 
2314
}
 
2315
 
 
2316
static gboolean
 
2317
gtk_icon_view_key_release (GtkWidget      *widget,
 
2318
                           GdkEventKey    *event)
 
2319
{
 
2320
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
2321
 
 
2322
  if (icon_view->priv->doing_rubberband)
 
2323
    return TRUE;
 
2324
 
 
2325
  return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->key_press_event (widget, event);
 
2326
}
 
2327
 
 
2328
static void
 
2329
gtk_icon_view_update_rubberband (gpointer data)
 
2330
{
 
2331
  GtkIconView *icon_view;
 
2332
  gint x, y;
 
2333
  GdkRectangle old_area;
 
2334
  GdkRectangle new_area;
 
2335
  GdkRectangle common;
 
2336
  GdkRegion *invalid_region;
 
2337
  
 
2338
  icon_view = GTK_ICON_VIEW (data);
 
2339
 
 
2340
  gdk_window_get_pointer (icon_view->priv->bin_window, &x, &y, NULL);
 
2341
 
 
2342
  x = MAX (x, 0);
 
2343
  y = MAX (y, 0);
 
2344
 
 
2345
  old_area.x = MIN (icon_view->priv->rubberband_x1,
 
2346
                    icon_view->priv->rubberband_x2);
 
2347
  old_area.y = MIN (icon_view->priv->rubberband_y1,
 
2348
                    icon_view->priv->rubberband_y2);
 
2349
  old_area.width = ABS (icon_view->priv->rubberband_x2 -
 
2350
                        icon_view->priv->rubberband_x1) + 1;
 
2351
  old_area.height = ABS (icon_view->priv->rubberband_y2 -
 
2352
                         icon_view->priv->rubberband_y1) + 1;
 
2353
  
 
2354
  new_area.x = MIN (icon_view->priv->rubberband_x1, x);
 
2355
  new_area.y = MIN (icon_view->priv->rubberband_y1, y);
 
2356
  new_area.width = ABS (x - icon_view->priv->rubberband_x1) + 1;
 
2357
  new_area.height = ABS (y - icon_view->priv->rubberband_y1) + 1;
 
2358
 
 
2359
  invalid_region = gdk_region_rectangle (&old_area);
 
2360
  gdk_region_union_with_rect (invalid_region, &new_area);
 
2361
 
 
2362
  gdk_rectangle_intersect (&old_area, &new_area, &common);
 
2363
  if (common.width > 2 && common.height > 2)
 
2364
    {
 
2365
      GdkRegion *common_region;
 
2366
 
 
2367
      /* make sure the border is invalidated */
 
2368
      common.x += 1;
 
2369
      common.y += 1;
 
2370
      common.width -= 2;
 
2371
      common.height -= 2;
 
2372
      
 
2373
      common_region = gdk_region_rectangle (&common);
 
2374
 
 
2375
      gdk_region_subtract (invalid_region, common_region);
 
2376
      gdk_region_destroy (common_region);
 
2377
    }
 
2378
  
 
2379
  gdk_window_invalidate_region (icon_view->priv->bin_window, invalid_region, TRUE);
 
2380
    
 
2381
  gdk_region_destroy (invalid_region);
 
2382
 
 
2383
  icon_view->priv->rubberband_x2 = x;
 
2384
  icon_view->priv->rubberband_y2 = y;  
 
2385
 
 
2386
  gtk_icon_view_update_rubberband_selection (icon_view);
 
2387
}
 
2388
 
 
2389
static void
 
2390
gtk_icon_view_start_rubberbanding (GtkIconView  *icon_view,
 
2391
                                   gint          x,
 
2392
                                   gint          y)
 
2393
{
 
2394
  GList *items;
 
2395
 
 
2396
  g_assert (!icon_view->priv->doing_rubberband);
 
2397
 
 
2398
  for (items = icon_view->priv->items; items; items = items->next)
 
2399
    {
 
2400
      GtkIconViewItem *item = items->data;
 
2401
 
 
2402
      item->selected_before_rubberbanding = item->selected;
 
2403
    }
 
2404
  
 
2405
  icon_view->priv->rubberband_x1 = x;
 
2406
  icon_view->priv->rubberband_y1 = y;
 
2407
  icon_view->priv->rubberband_x2 = x;
 
2408
  icon_view->priv->rubberband_y2 = y;
 
2409
 
 
2410
  icon_view->priv->doing_rubberband = TRUE;
 
2411
 
 
2412
  gtk_grab_add (GTK_WIDGET (icon_view));
 
2413
}
 
2414
 
 
2415
static void
 
2416
gtk_icon_view_stop_rubberbanding (GtkIconView *icon_view)
 
2417
{
 
2418
  if (!icon_view->priv->doing_rubberband)
 
2419
    return;
 
2420
 
 
2421
  icon_view->priv->doing_rubberband = FALSE;
 
2422
 
 
2423
  gtk_grab_remove (GTK_WIDGET (icon_view));
 
2424
  
 
2425
  gtk_widget_queue_draw (GTK_WIDGET (icon_view));
 
2426
}
 
2427
 
 
2428
static void
 
2429
gtk_icon_view_update_rubberband_selection (GtkIconView *icon_view)
 
2430
{
 
2431
  GList *items;
 
2432
  gint x, y, width, height;
 
2433
  gboolean dirty = FALSE;
 
2434
  
 
2435
  x = MIN (icon_view->priv->rubberband_x1,
 
2436
           icon_view->priv->rubberband_x2);
 
2437
  y = MIN (icon_view->priv->rubberband_y1,
 
2438
           icon_view->priv->rubberband_y2);
 
2439
  width = ABS (icon_view->priv->rubberband_x1 - 
 
2440
               icon_view->priv->rubberband_x2);
 
2441
  height = ABS (icon_view->priv->rubberband_y1 - 
 
2442
                icon_view->priv->rubberband_y2);
 
2443
  
 
2444
  for (items = icon_view->priv->items; items; items = items->next)
 
2445
    {
 
2446
      GtkIconViewItem *item = items->data;
 
2447
      gboolean is_in;
 
2448
      gboolean selected;
 
2449
      
 
2450
      is_in = gtk_icon_view_item_hit_test (icon_view, item, 
 
2451
                                           x, y, width, height);
 
2452
 
 
2453
      selected = is_in ^ item->selected_before_rubberbanding;
 
2454
 
 
2455
      if (item->selected != selected)
 
2456
        {
 
2457
          item->selected = selected;
 
2458
          dirty = TRUE;
 
2459
          gtk_icon_view_queue_draw_item (icon_view, item);
 
2460
        }
 
2461
    }
 
2462
 
 
2463
  if (dirty)
 
2464
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
2465
}
 
2466
 
 
2467
static gboolean
 
2468
gtk_icon_view_item_hit_test (GtkIconView      *icon_view,
 
2469
                             GtkIconViewItem  *item,
 
2470
                             gint              x,
 
2471
                             gint              y,
 
2472
                             gint              width,
 
2473
                             gint              height)
 
2474
{
 
2475
  GList *l;
 
2476
  GdkRectangle box;
 
2477
 
 
2478
  if (MIN (x + width, item->x + item->width) - MAX (x, item->x) <= 0 ||
 
2479
      MIN (y + height, item->y + item->height) - MAX (y, item->y) <= 0)
 
2480
    return FALSE;
 
2481
 
 
2482
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
2483
    {
 
2484
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
2485
      
 
2486
      if (!info->cell->visible)
 
2487
        continue;
 
2488
      
 
2489
      gtk_icon_view_get_cell_box (icon_view, item, info, &box);
 
2490
 
 
2491
      if (MIN (x + width, box.x + box.width) - MAX (x, box.x) > 0 &&
 
2492
        MIN (y + height, box.y + box.height) - MAX (y, box.y) > 0)
 
2493
        return TRUE;
 
2494
    }
 
2495
 
 
2496
  return FALSE;
 
2497
}
 
2498
 
 
2499
static gboolean
 
2500
gtk_icon_view_unselect_all_internal (GtkIconView  *icon_view)
 
2501
{
 
2502
  gboolean dirty = FALSE;
 
2503
  GList *items;
 
2504
 
 
2505
  if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
 
2506
    return FALSE;
 
2507
 
 
2508
  for (items = icon_view->priv->items; items; items = items->next)
 
2509
    {
 
2510
      GtkIconViewItem *item = items->data;
 
2511
 
 
2512
      if (item->selected)
 
2513
        {
 
2514
          item->selected = FALSE;
 
2515
          dirty = TRUE;
 
2516
          gtk_icon_view_queue_draw_item (icon_view, item);
 
2517
          gtk_icon_view_item_selected_changed (icon_view, item);
 
2518
        }
 
2519
    }
 
2520
 
 
2521
  return dirty;
 
2522
}
 
2523
 
 
2524
 
 
2525
/* GtkIconView signals */
 
2526
static void
 
2527
gtk_icon_view_set_adjustments (GtkIconView   *icon_view,
 
2528
                               GtkAdjustment *hadj,
 
2529
                               GtkAdjustment *vadj)
 
2530
{
 
2531
  gboolean need_adjust = FALSE;
 
2532
 
 
2533
  if (hadj)
 
2534
    g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
 
2535
  else
 
2536
    hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
 
2537
  if (vadj)
 
2538
    g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
 
2539
  else
 
2540
    vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
 
2541
 
 
2542
  if (icon_view->priv->hadjustment && (icon_view->priv->hadjustment != hadj))
 
2543
    {
 
2544
      g_signal_handlers_disconnect_matched (icon_view->priv->hadjustment, G_SIGNAL_MATCH_DATA,
 
2545
                                           0, 0, NULL, NULL, icon_view);
 
2546
      g_object_unref (icon_view->priv->hadjustment);
 
2547
    }
 
2548
 
 
2549
  if (icon_view->priv->vadjustment && (icon_view->priv->vadjustment != vadj))
 
2550
    {
 
2551
      g_signal_handlers_disconnect_matched (icon_view->priv->vadjustment, G_SIGNAL_MATCH_DATA,
 
2552
                                            0, 0, NULL, NULL, icon_view);
 
2553
      g_object_unref (icon_view->priv->vadjustment);
 
2554
    }
 
2555
 
 
2556
  if (icon_view->priv->hadjustment != hadj)
 
2557
    {
 
2558
      icon_view->priv->hadjustment = hadj;
 
2559
      g_object_ref_sink (icon_view->priv->hadjustment);
 
2560
 
 
2561
      g_signal_connect (icon_view->priv->hadjustment, "value-changed",
 
2562
                        G_CALLBACK (gtk_icon_view_adjustment_changed),
 
2563
                        icon_view);
 
2564
      need_adjust = TRUE;
 
2565
    }
 
2566
 
 
2567
  if (icon_view->priv->vadjustment != vadj)
 
2568
    {
 
2569
      icon_view->priv->vadjustment = vadj;
 
2570
      g_object_ref_sink (icon_view->priv->vadjustment);
 
2571
 
 
2572
      g_signal_connect (icon_view->priv->vadjustment, "value-changed",
 
2573
                        G_CALLBACK (gtk_icon_view_adjustment_changed),
 
2574
                        icon_view);
 
2575
      need_adjust = TRUE;
 
2576
    }
 
2577
 
 
2578
  if (need_adjust)
 
2579
    gtk_icon_view_adjustment_changed (NULL, icon_view);
 
2580
}
 
2581
 
 
2582
static void
 
2583
gtk_icon_view_real_select_all (GtkIconView *icon_view)
 
2584
{
 
2585
  gtk_icon_view_select_all (icon_view);
 
2586
}
 
2587
 
 
2588
static void
 
2589
gtk_icon_view_real_unselect_all (GtkIconView *icon_view)
 
2590
{
 
2591
  gtk_icon_view_unselect_all (icon_view);
 
2592
}
 
2593
 
 
2594
static void
 
2595
gtk_icon_view_real_select_cursor_item (GtkIconView *icon_view)
 
2596
{
 
2597
  gtk_icon_view_unselect_all (icon_view);
 
2598
  
 
2599
  if (icon_view->priv->cursor_item != NULL)
 
2600
    gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
 
2601
}
 
2602
 
 
2603
static gboolean
 
2604
gtk_icon_view_real_activate_cursor_item (GtkIconView *icon_view)
 
2605
{
 
2606
  GtkTreePath *path;
 
2607
  GtkCellRendererMode mode;
 
2608
  GtkIconViewCellInfo *info = NULL;
 
2609
  
 
2610
  if (!icon_view->priv->cursor_item)
 
2611
    return FALSE;
 
2612
 
 
2613
  info = g_list_nth_data (icon_view->priv->cell_list, 
 
2614
                          icon_view->priv->cursor_cell);
 
2615
 
 
2616
  if (info) 
 
2617
    {  
 
2618
      g_object_get (info->cell, "mode", &mode, NULL);
 
2619
 
 
2620
      if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
 
2621
        {
 
2622
          gtk_icon_view_item_activate_cell (icon_view, 
 
2623
                                            icon_view->priv->cursor_item, 
 
2624
                                            info, NULL);
 
2625
          return TRUE;
 
2626
        }
 
2627
      else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
 
2628
        {
 
2629
          gtk_icon_view_start_editing (icon_view, 
 
2630
                                       icon_view->priv->cursor_item, 
 
2631
                                       info, NULL);
 
2632
          return TRUE;
 
2633
        }
 
2634
    }
 
2635
  
 
2636
  path = gtk_tree_path_new_from_indices (icon_view->priv->cursor_item->index, -1);
 
2637
  gtk_icon_view_item_activated (icon_view, path);
 
2638
  gtk_tree_path_free (path);
 
2639
 
 
2640
  return TRUE;
 
2641
}
 
2642
 
 
2643
static void
 
2644
gtk_icon_view_real_toggle_cursor_item (GtkIconView *icon_view)
 
2645
{
 
2646
  if (!icon_view->priv->cursor_item)
 
2647
    return;
 
2648
 
 
2649
  switch (icon_view->priv->selection_mode)
 
2650
    {
 
2651
    case GTK_SELECTION_NONE:
 
2652
      break;
 
2653
    case GTK_SELECTION_BROWSE:
 
2654
      gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
 
2655
      break;
 
2656
    case GTK_SELECTION_SINGLE:
 
2657
      if (icon_view->priv->cursor_item->selected)
 
2658
        gtk_icon_view_unselect_item (icon_view, icon_view->priv->cursor_item);
 
2659
      else
 
2660
        gtk_icon_view_select_item (icon_view, icon_view->priv->cursor_item);
 
2661
      break;
 
2662
    case GTK_SELECTION_MULTIPLE:
 
2663
      icon_view->priv->cursor_item->selected = !icon_view->priv->cursor_item->selected;
 
2664
      g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0); 
 
2665
      
 
2666
      gtk_icon_view_item_selected_changed (icon_view, icon_view->priv->cursor_item);      
 
2667
      gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
 
2668
      break;
 
2669
    }
 
2670
}
 
2671
 
 
2672
/* Internal functions */
 
2673
static void
 
2674
gtk_icon_view_adjustment_changed (GtkAdjustment *adjustment,
 
2675
                                  GtkIconView   *icon_view)
 
2676
{
 
2677
  if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
 
2678
    {
 
2679
      gdk_window_move (icon_view->priv->bin_window,
 
2680
                       - icon_view->priv->hadjustment->value,
 
2681
                       - icon_view->priv->vadjustment->value);
 
2682
 
 
2683
      if (icon_view->priv->doing_rubberband)
 
2684
        gtk_icon_view_update_rubberband (GTK_WIDGET (icon_view));
 
2685
 
 
2686
      gdk_window_process_updates (icon_view->priv->bin_window, TRUE);
 
2687
    }
 
2688
}
 
2689
 
 
2690
static GList *
 
2691
gtk_icon_view_layout_single_row (GtkIconView *icon_view, 
 
2692
                                 GList       *first_item, 
 
2693
                                 gint         item_width,
 
2694
                                 gint         row,
 
2695
                                 gint        *y, 
 
2696
                                 gint        *maximum_width)
 
2697
{
 
2698
  gint focus_width;
 
2699
  gint x, current_width;
 
2700
  GList *items, *last_item;
 
2701
  gint col;
 
2702
  gint colspan;
 
2703
  gint *max_height;
 
2704
  gint i;
 
2705
  gboolean rtl;
 
2706
 
 
2707
  rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL;
 
2708
  max_height = g_new0 (gint, icon_view->priv->n_cells);
 
2709
 
 
2710
  x = 0;
 
2711
  col = 0;
 
2712
  items = first_item;
 
2713
  current_width = 0;
 
2714
 
 
2715
  gtk_widget_style_get (GTK_WIDGET (icon_view),
 
2716
                        "focus-line-width", &focus_width,
 
2717
                        NULL);
 
2718
 
 
2719
  x += icon_view->priv->margin + focus_width;
 
2720
  current_width += 2 * (icon_view->priv->margin + focus_width);
 
2721
 
 
2722
  items = first_item;
 
2723
  while (items)
 
2724
    {
 
2725
      GtkIconViewItem *item = items->data;
 
2726
 
 
2727
      gtk_icon_view_calculate_item_size (icon_view, item);
 
2728
      colspan = 1 + (item->width - 1) / (item_width + icon_view->priv->column_spacing);
 
2729
 
 
2730
      item->width = colspan * item_width + (colspan - 1) * icon_view->priv->column_spacing;
 
2731
 
 
2732
      current_width += item->width;
 
2733
 
 
2734
      if (items != first_item)
 
2735
        {
 
2736
          if ((icon_view->priv->columns <= 0 && current_width > GTK_WIDGET (icon_view)->allocation.width) ||
 
2737
              (icon_view->priv->columns > 0 && col >= icon_view->priv->columns))
 
2738
            break;
 
2739
        }
 
2740
 
 
2741
      current_width += icon_view->priv->column_spacing + 2 * focus_width;
 
2742
 
 
2743
      item->y = *y + focus_width;
 
2744
      item->x = x;
 
2745
 
 
2746
      x = current_width - (icon_view->priv->margin + focus_width); 
 
2747
 
 
2748
      for (i = 0; i < icon_view->priv->n_cells; i++)
 
2749
        max_height[i] = MAX (max_height[i], item->box[i].height);
 
2750
              
 
2751
      if (current_width > *maximum_width)
 
2752
        *maximum_width = current_width;
 
2753
 
 
2754
      item->row = row;
 
2755
      item->col = col;
 
2756
 
 
2757
      col += colspan;
 
2758
      items = items->next;
 
2759
    }
 
2760
 
 
2761
  last_item = items;
 
2762
 
 
2763
  /* Now go through the row again and align the icons */
 
2764
  for (items = first_item; items != last_item; items = items->next)
 
2765
    {
 
2766
      GtkIconViewItem *item = items->data;
 
2767
 
 
2768
      if (rtl)
 
2769
        {
 
2770
          item->x = *maximum_width - item->width - item->x;
 
2771
          item->col = col - 1 - item->col;
 
2772
        }
 
2773
 
 
2774
      gtk_icon_view_calculate_item_size2 (icon_view, item, max_height);
 
2775
 
 
2776
      /* We may want to readjust the new y coordinate. */
 
2777
      if (item->y + item->height + focus_width + icon_view->priv->row_spacing > *y)
 
2778
        *y = item->y + item->height + focus_width + icon_view->priv->row_spacing;
 
2779
    }
 
2780
 
 
2781
  g_free (max_height);
 
2782
  
 
2783
  return last_item;
 
2784
}
 
2785
 
 
2786
static void
 
2787
gtk_icon_view_set_adjustment_upper (GtkAdjustment *adj,
 
2788
                                    gdouble        upper)
 
2789
{
 
2790
  if (upper != adj->upper)
 
2791
    {
 
2792
      gdouble min = MAX (0.0, upper - adj->page_size);
 
2793
      gboolean value_changed = FALSE;
 
2794
      
 
2795
      adj->upper = upper;
 
2796
 
 
2797
      if (adj->value > min)
 
2798
        {
 
2799
          adj->value = min;
 
2800
          value_changed = TRUE;
 
2801
        }
 
2802
      
 
2803
      gtk_adjustment_changed (adj);
 
2804
      
 
2805
      if (value_changed)
 
2806
        gtk_adjustment_value_changed (adj);
 
2807
    }
 
2808
}
 
2809
 
 
2810
static void
 
2811
gtk_icon_view_layout (GtkIconView *icon_view)
 
2812
{
 
2813
  gint y = 0, maximum_width = 0;
 
2814
  GList *icons;
 
2815
  GtkWidget *widget;
 
2816
  gint row;
 
2817
  gint item_width;
 
2818
 
 
2819
  if (icon_view->priv->layout_idle_id != 0)
 
2820
    {
 
2821
      g_source_remove (icon_view->priv->layout_idle_id);
 
2822
      icon_view->priv->layout_idle_id = 0;
 
2823
    }
 
2824
  
 
2825
  if (icon_view->priv->model == NULL)
 
2826
    return;
 
2827
 
 
2828
  widget = GTK_WIDGET (icon_view);
 
2829
 
 
2830
  item_width = icon_view->priv->item_width;
 
2831
 
 
2832
  if (item_width < 0)
 
2833
    {
 
2834
      for (icons = icon_view->priv->items; icons; icons = icons->next)
 
2835
        {
 
2836
          GtkIconViewItem *item = icons->data;
 
2837
          gtk_icon_view_calculate_item_size (icon_view, item);
 
2838
          item_width = MAX (item_width, item->width);
 
2839
        }
 
2840
    }
 
2841
 
 
2842
 
 
2843
  icons = icon_view->priv->items;
 
2844
  y += icon_view->priv->margin;
 
2845
  row = 0;
 
2846
 
 
2847
  if (icons)
 
2848
    {
 
2849
      gtk_icon_view_set_cell_data (icon_view, icons->data);
 
2850
      adjust_wrap_width (icon_view, icons->data);
 
2851
    }
 
2852
  
 
2853
  do
 
2854
    {
 
2855
      icons = gtk_icon_view_layout_single_row (icon_view, icons, 
 
2856
                                               item_width, row,
 
2857
                                               &y, &maximum_width);
 
2858
      row++;
 
2859
    }
 
2860
  while (icons != NULL);
 
2861
 
 
2862
  if (maximum_width != icon_view->priv->width)
 
2863
    icon_view->priv->width = maximum_width;
 
2864
 
 
2865
  y += icon_view->priv->margin;
 
2866
  
 
2867
  if (y != icon_view->priv->height)
 
2868
    icon_view->priv->height = y;
 
2869
 
 
2870
  gtk_icon_view_set_adjustment_upper (icon_view->priv->hadjustment, 
 
2871
                                      icon_view->priv->width);
 
2872
  gtk_icon_view_set_adjustment_upper (icon_view->priv->vadjustment, 
 
2873
                                      icon_view->priv->height);
 
2874
 
 
2875
  if (icon_view->priv->width != widget->requisition.width ||
 
2876
      icon_view->priv->height != widget->requisition.height)
 
2877
    gtk_widget_queue_resize_no_redraw (widget);
 
2878
 
 
2879
  if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
 
2880
    gdk_window_resize (icon_view->priv->bin_window,
 
2881
                       MAX (icon_view->priv->width, widget->allocation.width),
 
2882
                       MAX (icon_view->priv->height, widget->allocation.height));
 
2883
 
 
2884
  if (icon_view->priv->scroll_to_path)
 
2885
    {
 
2886
      GtkTreePath *path;
 
2887
 
 
2888
      path = gtk_tree_row_reference_get_path (icon_view->priv->scroll_to_path);
 
2889
      gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
 
2890
      icon_view->priv->scroll_to_path = NULL;
 
2891
      
 
2892
      gtk_icon_view_scroll_to_path (icon_view, path,
 
2893
                                    icon_view->priv->scroll_to_use_align,
 
2894
                                    icon_view->priv->scroll_to_row_align,
 
2895
                                    icon_view->priv->scroll_to_col_align);
 
2896
      gtk_tree_path_free (path);
 
2897
    }
 
2898
  
 
2899
  gtk_widget_queue_draw (widget);
 
2900
}
 
2901
 
 
2902
static void 
 
2903
gtk_icon_view_get_cell_area (GtkIconView         *icon_view,
 
2904
                             GtkIconViewItem     *item,
 
2905
                             GtkIconViewCellInfo *info,
 
2906
                             GdkRectangle        *cell_area)
 
2907
{
 
2908
  g_return_if_fail (info->position < item->n_cells);
 
2909
 
 
2910
  if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
2911
    {
 
2912
      cell_area->x = item->box[info->position].x - item->before[info->position];
 
2913
      cell_area->y = item->y + icon_view->priv->item_padding;
 
2914
      cell_area->width = item->box[info->position].width + 
 
2915
        item->before[info->position] + item->after[info->position];
 
2916
      cell_area->height = item->height - icon_view->priv->item_padding * 2;
 
2917
    }
 
2918
  else
 
2919
    {
 
2920
      cell_area->x = item->x + icon_view->priv->item_padding;
 
2921
      cell_area->y = item->box[info->position].y - item->before[info->position];
 
2922
      cell_area->width = item->width - icon_view->priv->item_padding * 2;
 
2923
      cell_area->height = item->box[info->position].height + 
 
2924
        item->before[info->position] + item->after[info->position];
 
2925
    }
 
2926
}
 
2927
 
 
2928
static void 
 
2929
gtk_icon_view_get_cell_box (GtkIconView         *icon_view,
 
2930
                            GtkIconViewItem     *item,
 
2931
                            GtkIconViewCellInfo *info,
 
2932
                            GdkRectangle        *box)
 
2933
{
 
2934
  g_return_if_fail (info->position < item->n_cells);
 
2935
 
 
2936
  *box = item->box[info->position];
 
2937
}
 
2938
 
 
2939
/* try to guess a reasonable wrap width for an implicit text cell renderer
 
2940
 */
 
2941
static void
 
2942
adjust_wrap_width (GtkIconView     *icon_view,
 
2943
                   GtkIconViewItem *item)
 
2944
{
 
2945
  GtkIconViewCellInfo *text_info;
 
2946
  GtkIconViewCellInfo *pixbuf_info;
 
2947
  gint pixbuf_width, wrap_width;
 
2948
      
 
2949
  if (icon_view->priv->text_cell != -1 &&
 
2950
      icon_view->priv->pixbuf_cell != -1)
 
2951
    {
 
2952
      gint item_width;
 
2953
 
 
2954
      text_info = g_list_nth_data (icon_view->priv->cell_list,
 
2955
                                   icon_view->priv->text_cell);
 
2956
      pixbuf_info = g_list_nth_data (icon_view->priv->cell_list,
 
2957
                                     icon_view->priv->pixbuf_cell);
 
2958
      
 
2959
      gtk_cell_renderer_get_size (pixbuf_info->cell, 
 
2960
                                  GTK_WIDGET (icon_view), 
 
2961
                                  NULL, NULL, NULL,
 
2962
                                  &pixbuf_width, 
 
2963
                                  NULL);
 
2964
          
 
2965
 
 
2966
      if (icon_view->priv->item_width > 0)
 
2967
        item_width = icon_view->priv->item_width;
 
2968
      else
 
2969
        item_width = item->width;
 
2970
 
 
2971
      if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
 
2972
        wrap_width = item_width;
 
2973
      else {
 
2974
        if (item->width == -1 && item_width <= 0)
 
2975
          wrap_width = MAX (2 * pixbuf_width, 50);
 
2976
        else
 
2977
          wrap_width = item_width - pixbuf_width - icon_view->priv->spacing;
 
2978
        }
 
2979
 
 
2980
      wrap_width -= icon_view->priv->item_padding * 2;
 
2981
 
 
2982
      g_object_set (text_info->cell, "wrap-width", wrap_width, NULL);
 
2983
      g_object_set (text_info->cell, "width", wrap_width, NULL);
 
2984
    }
 
2985
}
 
2986
 
 
2987
static void
 
2988
gtk_icon_view_calculate_item_size (GtkIconView     *icon_view,
 
2989
                                   GtkIconViewItem *item)
 
2990
{
 
2991
  gint spacing;
 
2992
  GList *l;
 
2993
 
 
2994
  if (item->width != -1 && item->height != -1) 
 
2995
    return;
 
2996
 
 
2997
  if (item->n_cells != icon_view->priv->n_cells)
 
2998
    {
 
2999
      g_free (item->before);
 
3000
      g_free (item->after);
 
3001
      g_free (item->box);
 
3002
      
 
3003
      item->before = g_new0 (gint, icon_view->priv->n_cells);
 
3004
      item->after = g_new0 (gint, icon_view->priv->n_cells);
 
3005
      item->box = g_new0 (GdkRectangle, icon_view->priv->n_cells);
 
3006
 
 
3007
      item->n_cells = icon_view->priv->n_cells;
 
3008
    }
 
3009
 
 
3010
  gtk_icon_view_set_cell_data (icon_view, item);
 
3011
 
 
3012
  spacing = icon_view->priv->spacing;
 
3013
 
 
3014
  item->width = 0;
 
3015
  item->height = 0;
 
3016
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
3017
    {
 
3018
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3019
      
 
3020
      if (!info->cell->visible)
 
3021
        continue;
 
3022
      
 
3023
      gtk_cell_renderer_get_size (info->cell, GTK_WIDGET (icon_view), 
 
3024
                                  NULL, NULL, NULL,
 
3025
                                  &item->box[info->position].width, 
 
3026
                                  &item->box[info->position].height);
 
3027
 
 
3028
      if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
3029
        {
 
3030
          item->width += item->box[info->position].width 
 
3031
            + (info->position > 0 ? spacing : 0);
 
3032
          item->height = MAX (item->height, item->box[info->position].height);
 
3033
        }
 
3034
      else
 
3035
        {
 
3036
          item->width = MAX (item->width, item->box[info->position].width);
 
3037
          item->height += item->box[info->position].height + (info->position > 0 ? spacing : 0);
 
3038
        }
 
3039
    }
 
3040
 
 
3041
  item->width += icon_view->priv->item_padding * 2;
 
3042
  item->height += icon_view->priv->item_padding * 2;
 
3043
}
 
3044
 
 
3045
static void
 
3046
gtk_icon_view_calculate_item_size2 (GtkIconView     *icon_view,
 
3047
                                    GtkIconViewItem *item,
 
3048
                                    gint            *max_height)
 
3049
{
 
3050
  GdkRectangle cell_area;
 
3051
  gint spacing;
 
3052
  GList *l;
 
3053
  gint i, k;
 
3054
  gboolean rtl;
 
3055
 
 
3056
  rtl = gtk_widget_get_direction (GTK_WIDGET (icon_view)) == GTK_TEXT_DIR_RTL;
 
3057
 
 
3058
  gtk_icon_view_set_cell_data (icon_view, item);
 
3059
 
 
3060
  spacing = icon_view->priv->spacing;
 
3061
 
 
3062
  item->height = 0;
 
3063
  for (i = 0; i < icon_view->priv->n_cells; i++)
 
3064
    {
 
3065
      if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
3066
        item->height = MAX (item->height, max_height[i]);
 
3067
      else
 
3068
        item->height += max_height[i] + (i > 0 ? spacing : 0);
 
3069
    }
 
3070
 
 
3071
  cell_area.x = item->x + icon_view->priv->item_padding;
 
3072
  cell_area.y = item->y + icon_view->priv->item_padding;
 
3073
      
 
3074
  for (k = 0; k < 2; k++)
 
3075
    for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
3076
      {
 
3077
        GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3078
        
 
3079
        if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END))
 
3080
          continue;
 
3081
 
 
3082
        if (!info->cell->visible)
 
3083
          continue;
 
3084
 
 
3085
        if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
3086
          {
 
3087
            /* We should not subtract icon_view->priv->item_padding from item->height,
 
3088
             * because item->height is recalculated above using
 
3089
             * max_height which does not contain item padding.
 
3090
             */
 
3091
            cell_area.width = item->box[info->position].width;
 
3092
            cell_area.height = item->height;
 
3093
          }
 
3094
        else
 
3095
          {
 
3096
            /* item->width is not recalculated and thus needs to be
 
3097
             * corrected for the padding.
 
3098
             */
 
3099
            cell_area.width = item->width - 2 * icon_view->priv->item_padding;
 
3100
            cell_area.height = max_height[i];
 
3101
          }
 
3102
        
 
3103
        gtk_cell_renderer_get_size (info->cell, GTK_WIDGET (icon_view), 
 
3104
                                    &cell_area,
 
3105
                                    &item->box[info->position].x, &item->box[info->position].y,
 
3106
                                    &item->box[info->position].width, &item->box[info->position].height);
 
3107
        
 
3108
        item->box[info->position].x += cell_area.x;
 
3109
        item->box[info->position].y += cell_area.y;
 
3110
        if (icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
3111
          {
 
3112
            item->before[info->position] = item->box[info->position].x - cell_area.x;
 
3113
            item->after[info->position] = cell_area.width - item->box[info->position].width - item->before[info->position];
 
3114
            cell_area.x += cell_area.width + spacing;
 
3115
          }
 
3116
        else
 
3117
          {
 
3118
            if (item->box[info->position].width > item->width - icon_view->priv->item_padding * 2)
 
3119
              {
 
3120
                item->width = item->box[info->position].width + icon_view->priv->item_padding * 2;
 
3121
                cell_area.width = item->width;
 
3122
              }
 
3123
            item->before[info->position] = item->box[info->position].y - cell_area.y;
 
3124
            item->after[info->position] = cell_area.height - item->box[info->position].height - item->before[info->position];
 
3125
            cell_area.y += cell_area.height + spacing;
 
3126
          }
 
3127
      }
 
3128
  
 
3129
  if (rtl && icon_view->priv->item_orientation == GTK_ORIENTATION_HORIZONTAL)
 
3130
    {
 
3131
      for (i = 0; i < icon_view->priv->n_cells; i++)
 
3132
        {
 
3133
          item->box[i].x = item->x + item->width - 
 
3134
            (item->box[i].x + item->box[i].width - item->x);
 
3135
        }      
 
3136
    }
 
3137
 
 
3138
  item->height += icon_view->priv->item_padding * 2;
 
3139
}
 
3140
 
 
3141
static void
 
3142
gtk_icon_view_invalidate_sizes (GtkIconView *icon_view)
 
3143
{
 
3144
  g_list_foreach (icon_view->priv->items,
 
3145
                  (GFunc)gtk_icon_view_item_invalidate_size, NULL);
 
3146
}
 
3147
 
 
3148
static void
 
3149
gtk_icon_view_item_invalidate_size (GtkIconViewItem *item)
 
3150
{
 
3151
  item->width = -1;
 
3152
  item->height = -1;
 
3153
}
 
3154
 
 
3155
static void
 
3156
gtk_icon_view_paint_item (GtkIconView     *icon_view,
 
3157
                          cairo_t         *cr,
 
3158
                          GtkIconViewItem *item,
 
3159
                          GdkRectangle    *area,
 
3160
                          GdkDrawable     *drawable,
 
3161
                          gint             x,
 
3162
                          gint             y,
 
3163
                          gboolean         draw_focus)
 
3164
{
 
3165
  gint focus_width;
 
3166
  gint padding;
 
3167
  GdkRectangle cell_area, box;
 
3168
  GList *l;
 
3169
  gint i;
 
3170
  GtkStateType state;
 
3171
  GtkCellRendererState flags;
 
3172
      
 
3173
  if (icon_view->priv->model == NULL)
 
3174
    return;
 
3175
  
 
3176
  gtk_icon_view_set_cell_data (icon_view, item);
 
3177
 
 
3178
  gtk_widget_style_get (GTK_WIDGET (icon_view),
 
3179
                        "focus-line-width", &focus_width,
 
3180
                        NULL);
 
3181
  
 
3182
  padding = focus_width; 
 
3183
  
 
3184
  if (item->selected)
 
3185
    {
 
3186
      flags = GTK_CELL_RENDERER_SELECTED;
 
3187
      if (gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
3188
        state = GTK_STATE_SELECTED;
 
3189
      else
 
3190
        state = GTK_STATE_ACTIVE;
 
3191
    }
 
3192
  else
 
3193
    {
 
3194
      flags = 0;
 
3195
      state = GTK_STATE_NORMAL;
 
3196
    }
 
3197
  
 
3198
#ifdef DEBUG_ICON_VIEW
 
3199
  gdk_draw_rectangle (drawable,
 
3200
                      GTK_WIDGET (icon_view)->style->black_gc,
 
3201
                      FALSE,
 
3202
                      x, y, 
 
3203
                      item->width, item->height);
 
3204
#endif
 
3205
 
 
3206
  if (item->selected)
 
3207
    {
 
3208
      gtk_paint_flat_box (GTK_WIDGET (icon_view)->style,
 
3209
                          (GdkWindow *) drawable,
 
3210
                          GTK_STATE_SELECTED,
 
3211
                          GTK_SHADOW_NONE,
 
3212
                          area,
 
3213
                          GTK_WIDGET (icon_view),
 
3214
                          "icon_view_item",
 
3215
                          x, y,
 
3216
                          item->width, item->height);
 
3217
    }
 
3218
  
 
3219
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
3220
    {
 
3221
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3222
      
 
3223
      if (!info->cell->visible)
 
3224
        continue;
 
3225
      
 
3226
      gtk_icon_view_get_cell_area (icon_view, item, info, &cell_area);
 
3227
      
 
3228
#ifdef DEBUG_ICON_VIEW
 
3229
      gdk_draw_rectangle (drawable,
 
3230
                          GTK_WIDGET (icon_view)->style->black_gc,
 
3231
                          FALSE,
 
3232
                          x - item->x + cell_area.x, 
 
3233
                          y - item->y + cell_area.y, 
 
3234
                          cell_area.width, cell_area.height);
 
3235
 
 
3236
      gtk_icon_view_get_cell_box (icon_view, item, info, &box);
 
3237
          
 
3238
      gdk_draw_rectangle (drawable,
 
3239
                          GTK_WIDGET (icon_view)->style->black_gc,
 
3240
                          FALSE,
 
3241
                          x - item->x + box.x, 
 
3242
                          y - item->y + box.y, 
 
3243
                          box.width, box.height);
 
3244
#endif
 
3245
 
 
3246
      cell_area.x = x - item->x + cell_area.x;
 
3247
      cell_area.y = y - item->y + cell_area.y;
 
3248
 
 
3249
      gtk_cell_renderer_render (info->cell,
 
3250
                                drawable,
 
3251
                                GTK_WIDGET (icon_view),
 
3252
                                &cell_area, &cell_area, area, flags);
 
3253
    }
 
3254
 
 
3255
  if (draw_focus &&
 
3256
      gtk_widget_has_focus (GTK_WIDGET (icon_view)) &&
 
3257
      item == icon_view->priv->cursor_item)
 
3258
    {
 
3259
      for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
3260
        {
 
3261
          GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3262
 
 
3263
          if (!info->cell->visible)
 
3264
            continue;
 
3265
 
 
3266
          /* If found a editable/activatable cell, draw focus on it. */
 
3267
          if (icon_view->priv->cursor_cell < 0 &&
 
3268
              info->cell->mode != GTK_CELL_RENDERER_MODE_INERT)
 
3269
            icon_view->priv->cursor_cell = i;
 
3270
 
 
3271
          gtk_icon_view_get_cell_box (icon_view, item, info, &box);
 
3272
 
 
3273
          if (i == icon_view->priv->cursor_cell)
 
3274
            {
 
3275
              gtk_paint_focus (GTK_WIDGET (icon_view)->style,
 
3276
                               drawable,
 
3277
                               GTK_STATE_NORMAL,
 
3278
                               area,
 
3279
                               GTK_WIDGET (icon_view),
 
3280
                               "icon_view",
 
3281
                               x - item->x + box.x - padding,
 
3282
                               y - item->y + box.y - padding,
 
3283
                               box.width + 2 * padding,
 
3284
                               box.height + 2 * padding);
 
3285
              break;
 
3286
            }
 
3287
        }
 
3288
 
 
3289
      /* If there are no editable/activatable cells, draw focus 
 
3290
       * around the whole item.
 
3291
       */
 
3292
      if (icon_view->priv->cursor_cell < 0)
 
3293
        gtk_paint_focus (GTK_WIDGET (icon_view)->style,
 
3294
                         drawable,
 
3295
                         GTK_STATE_NORMAL,
 
3296
                         area,
 
3297
                         GTK_WIDGET (icon_view),
 
3298
                         "icon_view",
 
3299
                         x - padding,
 
3300
                         y - padding,
 
3301
                         item->width + 2 * padding,
 
3302
                         item->height + 2 * padding);
 
3303
    }
 
3304
}
 
3305
 
 
3306
static void
 
3307
gtk_icon_view_paint_rubberband (GtkIconView     *icon_view,
 
3308
                                cairo_t         *cr,
 
3309
                                GdkRectangle    *area)
 
3310
{
 
3311
  GdkRectangle rect;
 
3312
  GdkRectangle rubber_rect;
 
3313
  GdkColor *fill_color_gdk;
 
3314
  guchar fill_color_alpha;
 
3315
 
 
3316
  rubber_rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2);
 
3317
  rubber_rect.y = MIN (icon_view->priv->rubberband_y1, icon_view->priv->rubberband_y2);
 
3318
  rubber_rect.width = ABS (icon_view->priv->rubberband_x1 - icon_view->priv->rubberband_x2) + 1;
 
3319
  rubber_rect.height = ABS (icon_view->priv->rubberband_y1 - icon_view->priv->rubberband_y2) + 1;
 
3320
 
 
3321
  if (!gdk_rectangle_intersect (&rubber_rect, area, &rect))
 
3322
    return;
 
3323
 
 
3324
  gtk_widget_style_get (GTK_WIDGET (icon_view),
 
3325
                        "selection-box-color", &fill_color_gdk,
 
3326
                        "selection-box-alpha", &fill_color_alpha,
 
3327
                        NULL);
 
3328
 
 
3329
  if (!fill_color_gdk)
 
3330
    fill_color_gdk = gdk_color_copy (&GTK_WIDGET (icon_view)->style->base[GTK_STATE_SELECTED]);
 
3331
 
 
3332
  cairo_set_source_rgba (cr,
 
3333
                         fill_color_gdk->red / 65535.,
 
3334
                         fill_color_gdk->green / 65535.,
 
3335
                         fill_color_gdk->blue / 65535.,
 
3336
                         fill_color_alpha / 255.);
 
3337
 
 
3338
  cairo_save (cr);
 
3339
  gdk_cairo_rectangle (cr, &rect);
 
3340
  cairo_clip (cr);
 
3341
  cairo_paint (cr);
 
3342
 
 
3343
  /* Draw the border without alpha */
 
3344
  cairo_set_source_rgb (cr,
 
3345
                        fill_color_gdk->red / 65535.,
 
3346
                        fill_color_gdk->green / 65535.,
 
3347
                        fill_color_gdk->blue / 65535.);
 
3348
  cairo_rectangle (cr, 
 
3349
                   rubber_rect.x + 0.5, rubber_rect.y + 0.5,
 
3350
                   rubber_rect.width - 1, rubber_rect.height - 1);
 
3351
  cairo_stroke (cr);
 
3352
  cairo_restore (cr);
 
3353
 
 
3354
  gdk_color_free (fill_color_gdk);
 
3355
}
 
3356
 
 
3357
static void
 
3358
gtk_icon_view_queue_draw_path (GtkIconView *icon_view,
 
3359
                               GtkTreePath *path)
 
3360
{
 
3361
  GList *l;
 
3362
  gint index;
 
3363
 
 
3364
  index = gtk_tree_path_get_indices (path)[0];
 
3365
 
 
3366
  for (l = icon_view->priv->items; l; l = l->next) 
 
3367
    {
 
3368
      GtkIconViewItem *item = l->data;
 
3369
 
 
3370
      if (item->index == index)
 
3371
        {
 
3372
          gtk_icon_view_queue_draw_item (icon_view, item);
 
3373
          break;
 
3374
        }
 
3375
    }
 
3376
}
 
3377
 
 
3378
static void
 
3379
gtk_icon_view_queue_draw_item (GtkIconView     *icon_view,
 
3380
                               GtkIconViewItem *item)
 
3381
{
 
3382
  gint focus_width;
 
3383
  GdkRectangle rect;
 
3384
 
 
3385
  gtk_widget_style_get (GTK_WIDGET (icon_view),
 
3386
                        "focus-line-width", &focus_width,
 
3387
                        NULL);
 
3388
 
 
3389
  rect.x = item->x - focus_width;
 
3390
  rect.y = item->y - focus_width;
 
3391
  rect.width = item->width + 2 * focus_width;
 
3392
  rect.height = item->height + 2 * focus_width;
 
3393
 
 
3394
  if (icon_view->priv->bin_window)
 
3395
    gdk_window_invalidate_rect (icon_view->priv->bin_window, &rect, TRUE);
 
3396
}
 
3397
 
 
3398
static gboolean
 
3399
layout_callback (gpointer user_data)
 
3400
{
 
3401
  GtkIconView *icon_view;
 
3402
 
 
3403
  icon_view = GTK_ICON_VIEW (user_data);
 
3404
  
 
3405
  icon_view->priv->layout_idle_id = 0;
 
3406
 
 
3407
  gtk_icon_view_layout (icon_view);
 
3408
  
 
3409
  return FALSE;
 
3410
}
 
3411
 
 
3412
static void
 
3413
gtk_icon_view_queue_layout (GtkIconView *icon_view)
 
3414
{
 
3415
  if (icon_view->priv->layout_idle_id != 0)
 
3416
    return;
 
3417
 
 
3418
  icon_view->priv->layout_idle_id = gdk_threads_add_idle (layout_callback, icon_view);
 
3419
}
 
3420
 
 
3421
static void
 
3422
gtk_icon_view_set_cursor_item (GtkIconView     *icon_view,
 
3423
                               GtkIconViewItem *item,
 
3424
                               gint             cursor_cell)
 
3425
{
 
3426
  AtkObject *obj;
 
3427
  AtkObject *item_obj;
 
3428
  AtkObject *cursor_item_obj;
 
3429
 
 
3430
  if (icon_view->priv->cursor_item == item &&
 
3431
      (cursor_cell < 0 || cursor_cell == icon_view->priv->cursor_cell))
 
3432
    return;
 
3433
 
 
3434
  obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
 
3435
  if (icon_view->priv->cursor_item != NULL)
 
3436
    {
 
3437
      gtk_icon_view_queue_draw_item (icon_view, icon_view->priv->cursor_item);
 
3438
      if (obj != NULL)
 
3439
        {
 
3440
          cursor_item_obj = atk_object_ref_accessible_child (obj, icon_view->priv->cursor_item->index);
 
3441
          if (cursor_item_obj != NULL)
 
3442
            atk_object_notify_state_change (cursor_item_obj, ATK_STATE_FOCUSED, FALSE);
 
3443
        }
 
3444
    }
 
3445
  icon_view->priv->cursor_item = item;
 
3446
  if (cursor_cell >= 0)
 
3447
    icon_view->priv->cursor_cell = cursor_cell;
 
3448
 
 
3449
  gtk_icon_view_queue_draw_item (icon_view, item);
 
3450
  
 
3451
  /* Notify that accessible focus object has changed */
 
3452
  item_obj = atk_object_ref_accessible_child (obj, item->index);
 
3453
 
 
3454
  if (item_obj != NULL)
 
3455
    {
 
3456
      atk_focus_tracker_notify (item_obj);
 
3457
      atk_object_notify_state_change (item_obj, ATK_STATE_FOCUSED, TRUE);
 
3458
      g_object_unref (item_obj); 
 
3459
    }
 
3460
}
 
3461
 
 
3462
 
 
3463
static GtkIconViewItem *
 
3464
gtk_icon_view_item_new (void)
 
3465
{
 
3466
  GtkIconViewItem *item;
 
3467
 
 
3468
  item = g_new0 (GtkIconViewItem, 1);
 
3469
 
 
3470
  item->width = -1;
 
3471
  item->height = -1;
 
3472
  
 
3473
  return item;
 
3474
}
 
3475
 
 
3476
static void
 
3477
gtk_icon_view_item_free (GtkIconViewItem *item)
 
3478
{
 
3479
  g_return_if_fail (item != NULL);
 
3480
 
 
3481
  g_free (item->before);
 
3482
  g_free (item->after);
 
3483
  g_free (item->box);
 
3484
 
 
3485
  g_free (item);
 
3486
}
 
3487
 
 
3488
 
 
3489
static GtkIconViewItem *
 
3490
gtk_icon_view_get_item_at_coords (GtkIconView          *icon_view,
 
3491
                                  gint                  x,
 
3492
                                  gint                  y,
 
3493
                                  gboolean              only_in_cell,
 
3494
                                  GtkIconViewCellInfo **cell_at_pos)
 
3495
{
 
3496
  GList *items, *l;
 
3497
  GdkRectangle box;
 
3498
 
 
3499
  if (cell_at_pos)
 
3500
    *cell_at_pos = NULL;
 
3501
 
 
3502
  for (items = icon_view->priv->items; items; items = items->next)
 
3503
    {
 
3504
      GtkIconViewItem *item = items->data;
 
3505
 
 
3506
      if (x >= item->x - icon_view->priv->column_spacing/2 && x <= item->x + item->width + icon_view->priv->column_spacing/2 &&
 
3507
          y >= item->y - icon_view->priv->row_spacing/2 && y <= item->y + item->height + icon_view->priv->row_spacing/2)
 
3508
        {
 
3509
          if (only_in_cell || cell_at_pos)
 
3510
            {
 
3511
              gtk_icon_view_set_cell_data (icon_view, item);
 
3512
 
 
3513
              for (l = icon_view->priv->cell_list; l; l = l->next)
 
3514
                {
 
3515
                  GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3516
 
 
3517
                  if (!info->cell->visible)
 
3518
                    continue;
 
3519
 
 
3520
                  gtk_icon_view_get_cell_box (icon_view, item, info, &box);
 
3521
 
 
3522
                  if ((x >= box.x && x <= box.x + box.width &&
 
3523
                       y >= box.y && y <= box.y + box.height) ||
 
3524
                      (x >= box.x  &&
 
3525
                       x <= box.x + box.width &&
 
3526
                       y >= box.y &&
 
3527
                       y <= box.y + box.height))
 
3528
                    {
 
3529
                      if (cell_at_pos)
 
3530
                        *cell_at_pos = info;
 
3531
 
 
3532
                      return item;
 
3533
                    }
 
3534
                }
 
3535
 
 
3536
              if (only_in_cell)
 
3537
                return NULL;
 
3538
            }
 
3539
 
 
3540
          return item;
 
3541
        }
 
3542
    }
 
3543
 
 
3544
  return NULL;
 
3545
}
 
3546
 
 
3547
static void
 
3548
gtk_icon_view_select_item (GtkIconView      *icon_view,
 
3549
                           GtkIconViewItem  *item)
 
3550
{
 
3551
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
3552
  g_return_if_fail (item != NULL);
 
3553
 
 
3554
  if (item->selected)
 
3555
    return;
 
3556
  
 
3557
  if (icon_view->priv->selection_mode == GTK_SELECTION_NONE)
 
3558
    return;
 
3559
  else if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
3560
    gtk_icon_view_unselect_all_internal (icon_view);
 
3561
 
 
3562
  item->selected = TRUE;
 
3563
 
 
3564
  gtk_icon_view_item_selected_changed (icon_view, item);
 
3565
  g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
3566
 
 
3567
  gtk_icon_view_queue_draw_item (icon_view, item);
 
3568
}
 
3569
 
 
3570
 
 
3571
static void
 
3572
gtk_icon_view_unselect_item (GtkIconView      *icon_view,
 
3573
                             GtkIconViewItem  *item)
 
3574
{
 
3575
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
3576
  g_return_if_fail (item != NULL);
 
3577
 
 
3578
  if (!item->selected)
 
3579
    return;
 
3580
  
 
3581
  if (icon_view->priv->selection_mode == GTK_SELECTION_NONE ||
 
3582
      icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
 
3583
    return;
 
3584
  
 
3585
  item->selected = FALSE;
 
3586
 
 
3587
  gtk_icon_view_item_selected_changed (icon_view, item);
 
3588
  g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
3589
 
 
3590
  gtk_icon_view_queue_draw_item (icon_view, item);
 
3591
}
 
3592
 
 
3593
static void
 
3594
verify_items (GtkIconView *icon_view)
 
3595
{
 
3596
  GList *items;
 
3597
  int i = 0;
 
3598
 
 
3599
  for (items = icon_view->priv->items; items; items = items->next)
 
3600
    {
 
3601
      GtkIconViewItem *item = items->data;
 
3602
 
 
3603
      if (item->index != i)
 
3604
        g_error ("List item does not match its index: "
 
3605
                 "item index %d and list index %d\n", item->index, i);
 
3606
 
 
3607
      i++;
 
3608
    }
 
3609
}
 
3610
 
 
3611
static void
 
3612
gtk_icon_view_row_changed (GtkTreeModel *model,
 
3613
                           GtkTreePath  *path,
 
3614
                           GtkTreeIter  *iter,
 
3615
                           gpointer      data)
 
3616
{
 
3617
  GtkIconViewItem *item;
 
3618
  gint index;
 
3619
  GtkIconView *icon_view;
 
3620
 
 
3621
  icon_view = GTK_ICON_VIEW (data);
 
3622
 
 
3623
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
3624
  
 
3625
  index = gtk_tree_path_get_indices(path)[0];
 
3626
  item = g_list_nth_data (icon_view->priv->items, index);
 
3627
 
 
3628
  gtk_icon_view_item_invalidate_size (item);
 
3629
  gtk_icon_view_queue_layout (icon_view);
 
3630
 
 
3631
  verify_items (icon_view);
 
3632
}
 
3633
 
 
3634
static void
 
3635
gtk_icon_view_row_inserted (GtkTreeModel *model,
 
3636
                            GtkTreePath  *path,
 
3637
                            GtkTreeIter  *iter,
 
3638
                            gpointer      data)
 
3639
{
 
3640
  gint index;
 
3641
  GtkIconViewItem *item;
 
3642
  gboolean iters_persist;
 
3643
  GtkIconView *icon_view;
 
3644
  GList *list;
 
3645
  
 
3646
  icon_view = GTK_ICON_VIEW (data);
 
3647
 
 
3648
  iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
 
3649
  
 
3650
  index = gtk_tree_path_get_indices(path)[0];
 
3651
 
 
3652
  item = gtk_icon_view_item_new ();
 
3653
 
 
3654
  if (iters_persist)
 
3655
    item->iter = *iter;
 
3656
 
 
3657
  item->index = index;
 
3658
 
 
3659
  /* FIXME: We can be more efficient here,
 
3660
     we can store a tail pointer and use that when
 
3661
     appending (which is a rather common operation)
 
3662
  */
 
3663
  icon_view->priv->items = g_list_insert (icon_view->priv->items,
 
3664
                                         item, index);
 
3665
  
 
3666
  list = g_list_nth (icon_view->priv->items, index + 1);
 
3667
  for (; list; list = list->next)
 
3668
    {
 
3669
      item = list->data;
 
3670
 
 
3671
      item->index++;
 
3672
    }
 
3673
    
 
3674
  verify_items (icon_view);
 
3675
 
 
3676
  gtk_icon_view_queue_layout (icon_view);
 
3677
}
 
3678
 
 
3679
static void
 
3680
gtk_icon_view_row_deleted (GtkTreeModel *model,
 
3681
                           GtkTreePath  *path,
 
3682
                           gpointer      data)
 
3683
{
 
3684
  gint index;
 
3685
  GtkIconView *icon_view;
 
3686
  GtkIconViewItem *item;
 
3687
  GList *list, *next;
 
3688
  gboolean emit = FALSE;
 
3689
  
 
3690
  icon_view = GTK_ICON_VIEW (data);
 
3691
 
 
3692
  index = gtk_tree_path_get_indices(path)[0];
 
3693
 
 
3694
  list = g_list_nth (icon_view->priv->items, index);
 
3695
  item = list->data;
 
3696
 
 
3697
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
3698
 
 
3699
  if (item == icon_view->priv->anchor_item)
 
3700
    icon_view->priv->anchor_item = NULL;
 
3701
 
 
3702
  if (item == icon_view->priv->cursor_item)
 
3703
    icon_view->priv->cursor_item = NULL;
 
3704
 
 
3705
  if (item->selected)
 
3706
    emit = TRUE;
 
3707
  
 
3708
  gtk_icon_view_item_free (item);
 
3709
 
 
3710
  for (next = list->next; next; next = next->next)
 
3711
    {
 
3712
      item = next->data;
 
3713
 
 
3714
      item->index--;
 
3715
    }
 
3716
  
 
3717
  icon_view->priv->items = g_list_delete_link (icon_view->priv->items, list);
 
3718
 
 
3719
  verify_items (icon_view);  
 
3720
  
 
3721
  gtk_icon_view_queue_layout (icon_view);
 
3722
 
 
3723
  if (emit)
 
3724
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
3725
}
 
3726
 
 
3727
static void
 
3728
gtk_icon_view_rows_reordered (GtkTreeModel *model,
 
3729
                              GtkTreePath  *parent,
 
3730
                              GtkTreeIter  *iter,
 
3731
                              gint         *new_order,
 
3732
                              gpointer      data)
 
3733
{
 
3734
  int i;
 
3735
  int length;
 
3736
  GtkIconView *icon_view;
 
3737
  GList *items = NULL, *list;
 
3738
  GtkIconViewItem **item_array;
 
3739
  gint *order;
 
3740
  
 
3741
  icon_view = GTK_ICON_VIEW (data);
 
3742
 
 
3743
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
3744
 
 
3745
  length = gtk_tree_model_iter_n_children (model, NULL);
 
3746
 
 
3747
  order = g_new (gint, length);
 
3748
  for (i = 0; i < length; i++)
 
3749
    order [new_order[i]] = i;
 
3750
 
 
3751
  item_array = g_new (GtkIconViewItem *, length);
 
3752
  for (i = 0, list = icon_view->priv->items; list != NULL; list = list->next, i++)
 
3753
    item_array[order[i]] = list->data;
 
3754
  g_free (order);
 
3755
 
 
3756
  for (i = length - 1; i >= 0; i--)
 
3757
    {
 
3758
      item_array[i]->index = i;
 
3759
      items = g_list_prepend (items, item_array[i]);
 
3760
    }
 
3761
  
 
3762
  g_free (item_array);
 
3763
  g_list_free (icon_view->priv->items);
 
3764
  icon_view->priv->items = items;
 
3765
 
 
3766
  gtk_icon_view_queue_layout (icon_view);
 
3767
 
 
3768
  verify_items (icon_view);  
 
3769
}
 
3770
 
 
3771
static void
 
3772
gtk_icon_view_build_items (GtkIconView *icon_view)
 
3773
{
 
3774
  GtkTreeIter iter;
 
3775
  int i;
 
3776
  gboolean iters_persist;
 
3777
  GList *items = NULL;
 
3778
 
 
3779
  iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
 
3780
  
 
3781
  if (!gtk_tree_model_get_iter_first (icon_view->priv->model,
 
3782
                                      &iter))
 
3783
    return;
 
3784
 
 
3785
  i = 0;
 
3786
  
 
3787
  do
 
3788
    {
 
3789
      GtkIconViewItem *item = gtk_icon_view_item_new ();
 
3790
 
 
3791
      if (iters_persist)
 
3792
        item->iter = iter;
 
3793
 
 
3794
      item->index = i;
 
3795
      
 
3796
      i++;
 
3797
 
 
3798
      items = g_list_prepend (items, item);
 
3799
      
 
3800
    } while (gtk_tree_model_iter_next (icon_view->priv->model, &iter));
 
3801
 
 
3802
  icon_view->priv->items = g_list_reverse (items);
 
3803
}
 
3804
 
 
3805
static void
 
3806
gtk_icon_view_add_move_binding (GtkBindingSet  *binding_set,
 
3807
                                guint           keyval,
 
3808
                                guint           modmask,
 
3809
                                GtkMovementStep step,
 
3810
                                gint            count)
 
3811
{
 
3812
  
 
3813
  gtk_binding_entry_add_signal (binding_set, keyval, modmask,
 
3814
                                I_("move-cursor"), 2,
 
3815
                                G_TYPE_ENUM, step,
 
3816
                                G_TYPE_INT, count);
 
3817
 
 
3818
  gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
 
3819
                                "move-cursor", 2,
 
3820
                                G_TYPE_ENUM, step,
 
3821
                                G_TYPE_INT, count);
 
3822
 
 
3823
  if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
 
3824
   return;
 
3825
 
 
3826
  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
 
3827
                                "move-cursor", 2,
 
3828
                                G_TYPE_ENUM, step,
 
3829
                                G_TYPE_INT, count);
 
3830
 
 
3831
  gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
 
3832
                                "move-cursor", 2,
 
3833
                                G_TYPE_ENUM, step,
 
3834
                                G_TYPE_INT, count);
 
3835
}
 
3836
 
 
3837
static gboolean
 
3838
gtk_icon_view_real_move_cursor (GtkIconView     *icon_view,
 
3839
                                GtkMovementStep  step,
 
3840
                                gint             count)
 
3841
{
 
3842
  GdkModifierType state;
 
3843
 
 
3844
  g_return_val_if_fail (GTK_ICON_VIEW (icon_view), FALSE);
 
3845
  g_return_val_if_fail (step == GTK_MOVEMENT_LOGICAL_POSITIONS ||
 
3846
                        step == GTK_MOVEMENT_VISUAL_POSITIONS ||
 
3847
                        step == GTK_MOVEMENT_DISPLAY_LINES ||
 
3848
                        step == GTK_MOVEMENT_PAGES ||
 
3849
                        step == GTK_MOVEMENT_BUFFER_ENDS, FALSE);
 
3850
 
 
3851
  if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
3852
    return FALSE;
 
3853
 
 
3854
  gtk_icon_view_stop_editing (icon_view, FALSE);
 
3855
  gtk_widget_grab_focus (GTK_WIDGET (icon_view));
 
3856
 
 
3857
  if (gtk_get_current_event_state (&state))
 
3858
    {
 
3859
      if ((state & GTK_MODIFY_SELECTION_MOD_MASK) == GTK_MODIFY_SELECTION_MOD_MASK)
 
3860
        icon_view->priv->modify_selection_pressed = TRUE;
 
3861
      if ((state & GTK_EXTEND_SELECTION_MOD_MASK) == GTK_EXTEND_SELECTION_MOD_MASK)
 
3862
        icon_view->priv->extend_selection_pressed = TRUE;
 
3863
    }
 
3864
  /* else we assume not pressed */
 
3865
 
 
3866
  switch (step)
 
3867
    {
 
3868
    case GTK_MOVEMENT_LOGICAL_POSITIONS:
 
3869
    case GTK_MOVEMENT_VISUAL_POSITIONS:
 
3870
      gtk_icon_view_move_cursor_left_right (icon_view, count);
 
3871
      break;
 
3872
    case GTK_MOVEMENT_DISPLAY_LINES:
 
3873
      gtk_icon_view_move_cursor_up_down (icon_view, count);
 
3874
      break;
 
3875
    case GTK_MOVEMENT_PAGES:
 
3876
      gtk_icon_view_move_cursor_page_up_down (icon_view, count);
 
3877
      break;
 
3878
    case GTK_MOVEMENT_BUFFER_ENDS:
 
3879
      gtk_icon_view_move_cursor_start_end (icon_view, count);
 
3880
      break;
 
3881
    default:
 
3882
      g_assert_not_reached ();
 
3883
    }
 
3884
 
 
3885
  icon_view->priv->modify_selection_pressed = FALSE;
 
3886
  icon_view->priv->extend_selection_pressed = FALSE;
 
3887
 
 
3888
  icon_view->priv->draw_focus = TRUE;
 
3889
 
 
3890
  return TRUE;
 
3891
}
 
3892
 
 
3893
static GtkIconViewItem *
 
3894
find_item (GtkIconView     *icon_view,
 
3895
           GtkIconViewItem *current,
 
3896
           gint             row_ofs,
 
3897
           gint             col_ofs)
 
3898
{
 
3899
  gint row, col;
 
3900
  GList *items;
 
3901
  GtkIconViewItem *item;
 
3902
 
 
3903
  /* FIXME: this could be more efficient 
 
3904
   */
 
3905
  row = current->row + row_ofs;
 
3906
  col = current->col + col_ofs;
 
3907
 
 
3908
  for (items = icon_view->priv->items; items; items = items->next)
 
3909
    {
 
3910
      item = items->data;
 
3911
      if (item->row == row && item->col == col)
 
3912
        return item;
 
3913
    }
 
3914
  
 
3915
  return NULL;
 
3916
}
 
3917
 
 
3918
static gint
 
3919
find_cell (GtkIconView     *icon_view,
 
3920
           GtkIconViewItem *item,
 
3921
           gint             cell,
 
3922
           GtkOrientation   orientation,
 
3923
           gint             step,
 
3924
           gint            *count)
 
3925
{
 
3926
  gint n_focusable;
 
3927
  gint *focusable;
 
3928
  gint current;
 
3929
  gint i, k;
 
3930
  GList *l;
 
3931
 
 
3932
  if (icon_view->priv->item_orientation != orientation)
 
3933
    return cell;
 
3934
 
 
3935
  gtk_icon_view_set_cell_data (icon_view, item);
 
3936
 
 
3937
  focusable = g_new0 (gint, icon_view->priv->n_cells);
 
3938
  n_focusable = 0;
 
3939
 
 
3940
  current = 0;
 
3941
  for (k = 0; k < 2; k++)
 
3942
    for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
3943
      {
 
3944
        GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
3945
        
 
3946
        if (info->pack == (k ? GTK_PACK_START : GTK_PACK_END))
 
3947
          continue;
 
3948
        
 
3949
        if (!info->cell->visible)
 
3950
          continue;
 
3951
 
 
3952
        if (info->cell->mode != GTK_CELL_RENDERER_MODE_INERT)
 
3953
          {
 
3954
            if (cell == i)
 
3955
              current = n_focusable;
 
3956
 
 
3957
            focusable[n_focusable] = i;
 
3958
 
 
3959
            n_focusable++;
 
3960
          }
 
3961
      }
 
3962
  
 
3963
  if (n_focusable == 0)
 
3964
    {
 
3965
      g_free (focusable);
 
3966
      return -1;
 
3967
    }
 
3968
 
 
3969
  if (cell < 0)
 
3970
    {
 
3971
      current = step > 0 ? 0 : n_focusable - 1;
 
3972
      cell = focusable[current];
 
3973
    }
 
3974
 
 
3975
  if (current + *count < 0)
 
3976
    {
 
3977
      cell = -1;
 
3978
      *count = current + *count;
 
3979
    }
 
3980
  else if (current + *count > n_focusable - 1)
 
3981
    {
 
3982
      cell = -1;
 
3983
      *count = current + *count - (n_focusable - 1);
 
3984
    }
 
3985
  else
 
3986
    {
 
3987
      cell = focusable[current + *count];
 
3988
      *count = 0;
 
3989
    }
 
3990
  
 
3991
  g_free (focusable);
 
3992
  
 
3993
  return cell;
 
3994
}
 
3995
 
 
3996
static GtkIconViewItem *
 
3997
find_item_page_up_down (GtkIconView     *icon_view,
 
3998
                        GtkIconViewItem *current,
 
3999
                        gint             count)
 
4000
{
 
4001
  GList *item, *next;
 
4002
  gint y, col;
 
4003
  
 
4004
  col = current->col;
 
4005
  y = current->y + count * icon_view->priv->vadjustment->page_size;
 
4006
 
 
4007
  item = g_list_find (icon_view->priv->items, current);
 
4008
  if (count > 0)
 
4009
    {
 
4010
      while (item)
 
4011
        {
 
4012
          for (next = item->next; next; next = next->next)
 
4013
            {
 
4014
              if (((GtkIconViewItem *)next->data)->col == col)
 
4015
                break;
 
4016
            }
 
4017
          if (!next || ((GtkIconViewItem *)next->data)->y > y)
 
4018
            break;
 
4019
 
 
4020
          item = next;
 
4021
        }
 
4022
    }
 
4023
  else 
 
4024
    {
 
4025
      while (item)
 
4026
        {
 
4027
          for (next = item->prev; next; next = next->prev)
 
4028
            {
 
4029
              if (((GtkIconViewItem *)next->data)->col == col)
 
4030
                break;
 
4031
            }
 
4032
          if (!next || ((GtkIconViewItem *)next->data)->y < y)
 
4033
            break;
 
4034
 
 
4035
          item = next;
 
4036
        }
 
4037
    }
 
4038
 
 
4039
  if (item)
 
4040
    return item->data;
 
4041
 
 
4042
  return NULL;
 
4043
}
 
4044
 
 
4045
static gboolean
 
4046
gtk_icon_view_select_all_between (GtkIconView     *icon_view,
 
4047
                                  GtkIconViewItem *anchor,
 
4048
                                  GtkIconViewItem *cursor)
 
4049
{
 
4050
  GList *items;
 
4051
  GtkIconViewItem *item;
 
4052
  gint row1, row2, col1, col2;
 
4053
  gboolean dirty = FALSE;
 
4054
  
 
4055
  if (anchor->row < cursor->row)
 
4056
    {
 
4057
      row1 = anchor->row;
 
4058
      row2 = cursor->row;
 
4059
    }
 
4060
  else
 
4061
    {
 
4062
      row1 = cursor->row;
 
4063
      row2 = anchor->row;
 
4064
    }
 
4065
 
 
4066
  if (anchor->col < cursor->col)
 
4067
    {
 
4068
      col1 = anchor->col;
 
4069
      col2 = cursor->col;
 
4070
    }
 
4071
  else
 
4072
    {
 
4073
      col1 = cursor->col;
 
4074
      col2 = anchor->col;
 
4075
    }
 
4076
 
 
4077
  for (items = icon_view->priv->items; items; items = items->next)
 
4078
    {
 
4079
      item = items->data;
 
4080
 
 
4081
      if (row1 <= item->row && item->row <= row2 &&
 
4082
          col1 <= item->col && item->col <= col2)
 
4083
        {
 
4084
          if (!item->selected)
 
4085
            {
 
4086
              dirty = TRUE;
 
4087
              item->selected = TRUE;
 
4088
              gtk_icon_view_item_selected_changed (icon_view, item);
 
4089
            }
 
4090
          gtk_icon_view_queue_draw_item (icon_view, item);
 
4091
        }
 
4092
    }
 
4093
 
 
4094
  return dirty;
 
4095
}
 
4096
 
 
4097
static void 
 
4098
gtk_icon_view_move_cursor_up_down (GtkIconView *icon_view,
 
4099
                                   gint         count)
 
4100
{
 
4101
  GtkIconViewItem *item;
 
4102
  gint cell;
 
4103
  gboolean dirty = FALSE;
 
4104
  gint step;
 
4105
  GtkDirectionType direction;
 
4106
  
 
4107
  if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
4108
    return;
 
4109
 
 
4110
  direction = count < 0 ? GTK_DIR_UP : GTK_DIR_DOWN;
 
4111
 
 
4112
  if (!icon_view->priv->cursor_item)
 
4113
    {
 
4114
      GList *list;
 
4115
 
 
4116
      if (count > 0)
 
4117
        list = icon_view->priv->items;
 
4118
      else
 
4119
        list = g_list_last (icon_view->priv->items);
 
4120
 
 
4121
      item = list ? list->data : NULL;
 
4122
      cell = -1;
 
4123
    }
 
4124
  else
 
4125
    {
 
4126
      item = icon_view->priv->cursor_item;
 
4127
      cell = icon_view->priv->cursor_cell;
 
4128
      step = count > 0 ? 1 : -1;      
 
4129
      while (item)
 
4130
        {
 
4131
          cell = find_cell (icon_view, item, cell,
 
4132
                            GTK_ORIENTATION_VERTICAL, 
 
4133
                            step, &count);
 
4134
          if (count == 0)
 
4135
            break;
 
4136
 
 
4137
          item = find_item (icon_view, item, step, 0);
 
4138
          count = count - step;
 
4139
        }
 
4140
    }
 
4141
 
 
4142
  if (!item)
 
4143
    {
 
4144
      if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction))
 
4145
        {
 
4146
          GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view));
 
4147
          if (toplevel)
 
4148
            gtk_widget_child_focus (toplevel,
 
4149
                                    direction == GTK_DIR_UP ?
 
4150
                                    GTK_DIR_TAB_BACKWARD :
 
4151
                                    GTK_DIR_TAB_FORWARD);
 
4152
        }
 
4153
 
 
4154
      return;
 
4155
    }
 
4156
 
 
4157
  if (icon_view->priv->modify_selection_pressed ||
 
4158
      !icon_view->priv->extend_selection_pressed ||
 
4159
      !icon_view->priv->anchor_item ||
 
4160
      icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
4161
    icon_view->priv->anchor_item = item;
 
4162
 
 
4163
  gtk_icon_view_set_cursor_item (icon_view, item, cell);
 
4164
 
 
4165
  if (!icon_view->priv->modify_selection_pressed &&
 
4166
      icon_view->priv->selection_mode != GTK_SELECTION_NONE)
 
4167
    {
 
4168
      dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
4169
      dirty = gtk_icon_view_select_all_between (icon_view, 
 
4170
                                                icon_view->priv->anchor_item,
 
4171
                                                item) || dirty;
 
4172
    }
 
4173
 
 
4174
  gtk_icon_view_scroll_to_item (icon_view, item);
 
4175
 
 
4176
  if (dirty)
 
4177
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
4178
}
 
4179
 
 
4180
static void 
 
4181
gtk_icon_view_move_cursor_page_up_down (GtkIconView *icon_view,
 
4182
                                        gint         count)
 
4183
{
 
4184
  GtkIconViewItem *item;
 
4185
  gboolean dirty = FALSE;
 
4186
  
 
4187
  if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
4188
    return;
 
4189
  
 
4190
  if (!icon_view->priv->cursor_item)
 
4191
    {
 
4192
      GList *list;
 
4193
 
 
4194
      if (count > 0)
 
4195
        list = icon_view->priv->items;
 
4196
      else
 
4197
        list = g_list_last (icon_view->priv->items);
 
4198
 
 
4199
      item = list ? list->data : NULL;
 
4200
    }
 
4201
  else
 
4202
    item = find_item_page_up_down (icon_view, 
 
4203
                                   icon_view->priv->cursor_item,
 
4204
                                   count);
 
4205
 
 
4206
  if (item == icon_view->priv->cursor_item)
 
4207
    gtk_widget_error_bell (GTK_WIDGET (icon_view));
 
4208
 
 
4209
  if (!item)
 
4210
    return;
 
4211
 
 
4212
  if (icon_view->priv->modify_selection_pressed ||
 
4213
      !icon_view->priv->extend_selection_pressed ||
 
4214
      !icon_view->priv->anchor_item ||
 
4215
      icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
4216
    icon_view->priv->anchor_item = item;
 
4217
 
 
4218
  gtk_icon_view_set_cursor_item (icon_view, item, -1);
 
4219
 
 
4220
  if (!icon_view->priv->modify_selection_pressed &&
 
4221
      icon_view->priv->selection_mode != GTK_SELECTION_NONE)
 
4222
    {
 
4223
      dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
4224
      dirty = gtk_icon_view_select_all_between (icon_view, 
 
4225
                                                icon_view->priv->anchor_item,
 
4226
                                                item) || dirty;
 
4227
    }
 
4228
 
 
4229
  gtk_icon_view_scroll_to_item (icon_view, item);
 
4230
 
 
4231
  if (dirty)
 
4232
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);  
 
4233
}
 
4234
 
 
4235
static void 
 
4236
gtk_icon_view_move_cursor_left_right (GtkIconView *icon_view,
 
4237
                                      gint         count)
 
4238
{
 
4239
  GtkIconViewItem *item;
 
4240
  gint cell = -1;
 
4241
  gboolean dirty = FALSE;
 
4242
  gint step;
 
4243
  GtkDirectionType direction;
 
4244
 
 
4245
  if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
4246
    return;
 
4247
 
 
4248
  direction = count < 0 ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
 
4249
 
 
4250
  if (!icon_view->priv->cursor_item)
 
4251
    {
 
4252
      GList *list;
 
4253
 
 
4254
      if (count > 0)
 
4255
        list = icon_view->priv->items;
 
4256
      else
 
4257
        list = g_list_last (icon_view->priv->items);
 
4258
 
 
4259
      item = list ? list->data : NULL;
 
4260
    }
 
4261
  else
 
4262
    {
 
4263
      item = icon_view->priv->cursor_item;
 
4264
      cell = icon_view->priv->cursor_cell;
 
4265
      step = count > 0 ? 1 : -1;
 
4266
      while (item)
 
4267
        {
 
4268
          cell = find_cell (icon_view, item, cell,
 
4269
                            GTK_ORIENTATION_HORIZONTAL, 
 
4270
                            step, &count);
 
4271
          if (count == 0)
 
4272
            break;
 
4273
          
 
4274
          item = find_item (icon_view, item, 0, step);
 
4275
          count = count - step;
 
4276
        }
 
4277
    }
 
4278
 
 
4279
  if (!item)
 
4280
    {
 
4281
      if (!gtk_widget_keynav_failed (GTK_WIDGET (icon_view), direction))
 
4282
        {
 
4283
          GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (icon_view));
 
4284
          if (toplevel)
 
4285
            gtk_widget_child_focus (toplevel,
 
4286
                                    direction == GTK_DIR_LEFT ?
 
4287
                                    GTK_DIR_TAB_BACKWARD :
 
4288
                                    GTK_DIR_TAB_FORWARD);
 
4289
        }
 
4290
 
 
4291
      return;
 
4292
    }
 
4293
 
 
4294
  if (icon_view->priv->modify_selection_pressed ||
 
4295
      !icon_view->priv->extend_selection_pressed ||
 
4296
      !icon_view->priv->anchor_item ||
 
4297
      icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
4298
    icon_view->priv->anchor_item = item;
 
4299
 
 
4300
  gtk_icon_view_set_cursor_item (icon_view, item, cell);
 
4301
 
 
4302
  if (!icon_view->priv->modify_selection_pressed &&
 
4303
      icon_view->priv->selection_mode != GTK_SELECTION_NONE)
 
4304
    {
 
4305
      dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
4306
      dirty = gtk_icon_view_select_all_between (icon_view, 
 
4307
                                                icon_view->priv->anchor_item,
 
4308
                                                item) || dirty;
 
4309
    }
 
4310
 
 
4311
  gtk_icon_view_scroll_to_item (icon_view, item);
 
4312
 
 
4313
  if (dirty)
 
4314
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
4315
}
 
4316
 
 
4317
static void 
 
4318
gtk_icon_view_move_cursor_start_end (GtkIconView *icon_view,
 
4319
                                     gint         count)
 
4320
{
 
4321
  GtkIconViewItem *item;
 
4322
  GList *list;
 
4323
  gboolean dirty = FALSE;
 
4324
  
 
4325
  if (!gtk_widget_has_focus (GTK_WIDGET (icon_view)))
 
4326
    return;
 
4327
  
 
4328
  if (count < 0)
 
4329
    list = icon_view->priv->items;
 
4330
  else
 
4331
    list = g_list_last (icon_view->priv->items);
 
4332
  
 
4333
  item = list ? list->data : NULL;
 
4334
 
 
4335
  if (item == icon_view->priv->cursor_item)
 
4336
    gtk_widget_error_bell (GTK_WIDGET (icon_view));
 
4337
 
 
4338
  if (!item)
 
4339
    return;
 
4340
 
 
4341
  if (icon_view->priv->modify_selection_pressed ||
 
4342
      !icon_view->priv->extend_selection_pressed ||
 
4343
      !icon_view->priv->anchor_item ||
 
4344
      icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
4345
    icon_view->priv->anchor_item = item;
 
4346
 
 
4347
  gtk_icon_view_set_cursor_item (icon_view, item, -1);
 
4348
 
 
4349
  if (!icon_view->priv->modify_selection_pressed &&
 
4350
      icon_view->priv->selection_mode != GTK_SELECTION_NONE)
 
4351
    {
 
4352
      dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
4353
      dirty = gtk_icon_view_select_all_between (icon_view, 
 
4354
                                                icon_view->priv->anchor_item,
 
4355
                                                item) || dirty;
 
4356
    }
 
4357
 
 
4358
  gtk_icon_view_scroll_to_item (icon_view, item);
 
4359
 
 
4360
  if (dirty)
 
4361
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
4362
}
 
4363
 
 
4364
/**
 
4365
 * gtk_icon_view_scroll_to_path:
 
4366
 * @icon_view: A #GtkIconView.
 
4367
 * @path: The path of the item to move to.
 
4368
 * @use_align: whether to use alignment arguments, or %FALSE.
 
4369
 * @row_align: The vertical alignment of the item specified by @path.
 
4370
 * @col_align: The horizontal alignment of the item specified by @path.
 
4371
 *
 
4372
 * Moves the alignments of @icon_view to the position specified by @path.  
 
4373
 * @row_align determines where the row is placed, and @col_align determines 
 
4374
 * where @column is placed.  Both are expected to be between 0.0 and 1.0. 
 
4375
 * 0.0 means left/top alignment, 1.0 means right/bottom alignment, 0.5 means 
 
4376
 * center.
 
4377
 *
 
4378
 * If @use_align is %FALSE, then the alignment arguments are ignored, and the
 
4379
 * tree does the minimum amount of work to scroll the item onto the screen.
 
4380
 * This means that the item will be scrolled to the edge closest to its current
 
4381
 * position.  If the item is currently visible on the screen, nothing is done.
 
4382
 *
 
4383
 * This function only works if the model is set, and @path is a valid row on 
 
4384
 * the model. If the model changes before the @icon_view is realized, the 
 
4385
 * centered path will be modified to reflect this change.
 
4386
 *
 
4387
 * Since: 2.8
 
4388
 **/
 
4389
void
 
4390
gtk_icon_view_scroll_to_path (GtkIconView *icon_view,
 
4391
                              GtkTreePath *path,
 
4392
                              gboolean     use_align,
 
4393
                              gfloat       row_align,
 
4394
                              gfloat       col_align)
 
4395
{
 
4396
  GtkIconViewItem *item = NULL;
 
4397
 
 
4398
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
4399
  g_return_if_fail (path != NULL);
 
4400
  g_return_if_fail (row_align >= 0.0 && row_align <= 1.0);
 
4401
  g_return_if_fail (col_align >= 0.0 && col_align <= 1.0);
 
4402
 
 
4403
  if (gtk_tree_path_get_depth (path) > 0)
 
4404
    item = g_list_nth_data (icon_view->priv->items,
 
4405
                            gtk_tree_path_get_indices(path)[0]);
 
4406
  
 
4407
  if (!item || item->width < 0 ||
 
4408
      !gtk_widget_get_realized (GTK_WIDGET (icon_view)))
 
4409
    {
 
4410
      if (icon_view->priv->scroll_to_path)
 
4411
        gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
 
4412
 
 
4413
      icon_view->priv->scroll_to_path = NULL;
 
4414
 
 
4415
      if (path)
 
4416
        icon_view->priv->scroll_to_path = gtk_tree_row_reference_new_proxy (G_OBJECT (icon_view), icon_view->priv->model, path);
 
4417
 
 
4418
      icon_view->priv->scroll_to_use_align = use_align;
 
4419
      icon_view->priv->scroll_to_row_align = row_align;
 
4420
      icon_view->priv->scroll_to_col_align = col_align;
 
4421
 
 
4422
      return;
 
4423
    }
 
4424
 
 
4425
  if (use_align)
 
4426
    {
 
4427
      gint x, y;
 
4428
      gint focus_width;
 
4429
      gfloat offset, value;
 
4430
 
 
4431
      gtk_widget_style_get (GTK_WIDGET (icon_view),
 
4432
                            "focus-line-width", &focus_width,
 
4433
                            NULL);
 
4434
      
 
4435
      gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
 
4436
      
 
4437
      offset =  y + item->y - focus_width - 
 
4438
        row_align * (GTK_WIDGET (icon_view)->allocation.height - item->height);
 
4439
      value = CLAMP (icon_view->priv->vadjustment->value + offset, 
 
4440
                     icon_view->priv->vadjustment->lower,
 
4441
                     icon_view->priv->vadjustment->upper - icon_view->priv->vadjustment->page_size);
 
4442
      gtk_adjustment_set_value (icon_view->priv->vadjustment, value);
 
4443
 
 
4444
      offset = x + item->x - focus_width - 
 
4445
        col_align * (GTK_WIDGET (icon_view)->allocation.width - item->width);
 
4446
      value = CLAMP (icon_view->priv->hadjustment->value + offset, 
 
4447
                     icon_view->priv->hadjustment->lower,
 
4448
                     icon_view->priv->hadjustment->upper - icon_view->priv->hadjustment->page_size);
 
4449
      gtk_adjustment_set_value (icon_view->priv->hadjustment, value);
 
4450
 
 
4451
      gtk_adjustment_changed (icon_view->priv->hadjustment);
 
4452
      gtk_adjustment_changed (icon_view->priv->vadjustment);
 
4453
    }
 
4454
  else
 
4455
    gtk_icon_view_scroll_to_item (icon_view, item);
 
4456
}
 
4457
 
 
4458
 
 
4459
static void     
 
4460
gtk_icon_view_scroll_to_item (GtkIconView     *icon_view, 
 
4461
                              GtkIconViewItem *item)
 
4462
{
 
4463
  gint x, y, width, height;
 
4464
  gint focus_width;
 
4465
 
 
4466
  gtk_widget_style_get (GTK_WIDGET (icon_view),
 
4467
                        "focus-line-width", &focus_width,
 
4468
                        NULL);
 
4469
 
 
4470
  width = gdk_window_get_width (icon_view->priv->bin_window);
 
4471
  height = gdk_window_get_height (icon_view->priv->bin_window);
 
4472
  gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
 
4473
  
 
4474
  if (y + item->y - focus_width < 0)
 
4475
    gtk_adjustment_set_value (icon_view->priv->vadjustment, 
 
4476
                              icon_view->priv->vadjustment->value + y + item->y - focus_width);
 
4477
  else if (y + item->y + item->height + focus_width > GTK_WIDGET (icon_view)->allocation.height)
 
4478
    gtk_adjustment_set_value (icon_view->priv->vadjustment, 
 
4479
                              icon_view->priv->vadjustment->value + y + item->y + item->height 
 
4480
                              + focus_width - GTK_WIDGET (icon_view)->allocation.height);
 
4481
 
 
4482
  if (x + item->x - focus_width < 0)
 
4483
    gtk_adjustment_set_value (icon_view->priv->hadjustment, 
 
4484
                              icon_view->priv->hadjustment->value + x + item->x - focus_width);
 
4485
  else if (x + item->x + item->width + focus_width > GTK_WIDGET (icon_view)->allocation.width)
 
4486
    gtk_adjustment_set_value (icon_view->priv->hadjustment, 
 
4487
                              icon_view->priv->hadjustment->value + x + item->x + item->width 
 
4488
                              + focus_width - GTK_WIDGET (icon_view)->allocation.width);
 
4489
 
 
4490
  gtk_adjustment_changed (icon_view->priv->hadjustment);
 
4491
  gtk_adjustment_changed (icon_view->priv->vadjustment);
 
4492
}
 
4493
 
 
4494
/* GtkCellLayout implementation */
 
4495
static GtkIconViewCellInfo *
 
4496
gtk_icon_view_get_cell_info (GtkIconView     *icon_view,
 
4497
                             GtkCellRenderer *renderer)
 
4498
{
 
4499
  GList *i;
 
4500
 
 
4501
  for (i = icon_view->priv->cell_list; i; i = i->next)
 
4502
    {
 
4503
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)i->data;
 
4504
 
 
4505
      if (info->cell == renderer)
 
4506
        return info;
 
4507
    }
 
4508
 
 
4509
  return NULL;
 
4510
}
 
4511
 
 
4512
static void
 
4513
gtk_icon_view_set_cell_data (GtkIconView     *icon_view, 
 
4514
                             GtkIconViewItem *item)
 
4515
{
 
4516
  GList *i;
 
4517
  gboolean iters_persist;
 
4518
  GtkTreeIter iter;
 
4519
  
 
4520
  iters_persist = gtk_tree_model_get_flags (icon_view->priv->model) & GTK_TREE_MODEL_ITERS_PERSIST;
 
4521
  
 
4522
  if (!iters_persist)
 
4523
    {
 
4524
      GtkTreePath *path;
 
4525
 
 
4526
      path = gtk_tree_path_new_from_indices (item->index, -1);
 
4527
      if (!gtk_tree_model_get_iter (icon_view->priv->model, &iter, path))
 
4528
        return;
 
4529
      gtk_tree_path_free (path);
 
4530
    }
 
4531
  else
 
4532
    iter = item->iter;
 
4533
  
 
4534
  for (i = icon_view->priv->cell_list; i; i = i->next)
 
4535
    {
 
4536
      GSList *j;
 
4537
      GtkIconViewCellInfo *info = i->data;
 
4538
 
 
4539
      g_object_freeze_notify (G_OBJECT (info->cell));
 
4540
 
 
4541
      for (j = info->attributes; j && j->next; j = j->next->next)
 
4542
        {
 
4543
          gchar *property = j->data;
 
4544
          gint column = GPOINTER_TO_INT (j->next->data);
 
4545
          GValue value = {0, };
 
4546
 
 
4547
          gtk_tree_model_get_value (icon_view->priv->model, &iter,
 
4548
                                    column, &value);
 
4549
          g_object_set_property (G_OBJECT (info->cell),
 
4550
                                 property, &value);
 
4551
          g_value_unset (&value);
 
4552
        }
 
4553
 
 
4554
      if (info->func)
 
4555
        (* info->func) (GTK_CELL_LAYOUT (icon_view),
 
4556
                        info->cell,
 
4557
                        icon_view->priv->model,
 
4558
                        &iter,
 
4559
                        info->func_data);
 
4560
      
 
4561
      g_object_thaw_notify (G_OBJECT (info->cell));
 
4562
    }  
 
4563
}
 
4564
 
 
4565
static void 
 
4566
free_cell_attributes (GtkIconViewCellInfo *info)
 
4567
 
4568
  GSList *list;
 
4569
 
 
4570
  list = info->attributes;
 
4571
  while (list && list->next)
 
4572
    {
 
4573
      g_free (list->data);
 
4574
      list = list->next->next;
 
4575
    }
 
4576
  
 
4577
  g_slist_free (info->attributes);
 
4578
  info->attributes = NULL;
 
4579
}
 
4580
 
 
4581
static void
 
4582
free_cell_info (GtkIconViewCellInfo *info)
 
4583
{
 
4584
  free_cell_attributes (info);
 
4585
 
 
4586
  g_object_unref (info->cell);
 
4587
  
 
4588
  if (info->destroy)
 
4589
    (* info->destroy) (info->func_data);
 
4590
 
 
4591
  g_free (info);
 
4592
}
 
4593
 
 
4594
static void
 
4595
gtk_icon_view_cell_layout_pack_start (GtkCellLayout   *layout,
 
4596
                                      GtkCellRenderer *renderer,
 
4597
                                      gboolean         expand)
 
4598
{
 
4599
  GtkIconViewCellInfo *info;
 
4600
  GtkIconView *icon_view = GTK_ICON_VIEW (layout);
 
4601
 
 
4602
  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
 
4603
  g_return_if_fail (!gtk_icon_view_get_cell_info (icon_view, renderer));
 
4604
 
 
4605
  g_object_ref_sink (renderer);
 
4606
 
 
4607
  info = g_new0 (GtkIconViewCellInfo, 1);
 
4608
  info->cell = renderer;
 
4609
  info->expand = expand ? TRUE : FALSE;
 
4610
  info->pack = GTK_PACK_START;
 
4611
  info->position = icon_view->priv->n_cells;
 
4612
  
 
4613
  icon_view->priv->cell_list = g_list_append (icon_view->priv->cell_list, info);
 
4614
  icon_view->priv->n_cells++;
 
4615
}
 
4616
 
 
4617
static void
 
4618
gtk_icon_view_cell_layout_pack_end (GtkCellLayout   *layout,
 
4619
                                    GtkCellRenderer *renderer,
 
4620
                                    gboolean         expand)
 
4621
{
 
4622
  GtkIconViewCellInfo *info;
 
4623
  GtkIconView *icon_view = GTK_ICON_VIEW (layout);
 
4624
 
 
4625
  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
 
4626
  g_return_if_fail (!gtk_icon_view_get_cell_info (icon_view, renderer));
 
4627
 
 
4628
  g_object_ref_sink (renderer);
 
4629
 
 
4630
  info = g_new0 (GtkIconViewCellInfo, 1);
 
4631
  info->cell = renderer;
 
4632
  info->expand = expand ? TRUE : FALSE;
 
4633
  info->pack = GTK_PACK_END;
 
4634
  info->position = icon_view->priv->n_cells;
 
4635
 
 
4636
  icon_view->priv->cell_list = g_list_append (icon_view->priv->cell_list, info);
 
4637
  icon_view->priv->n_cells++;
 
4638
}
 
4639
 
 
4640
static void
 
4641
gtk_icon_view_cell_layout_add_attribute (GtkCellLayout   *layout,
 
4642
                                         GtkCellRenderer *renderer,
 
4643
                                         const gchar     *attribute,
 
4644
                                         gint             column)
 
4645
{
 
4646
  GtkIconViewCellInfo *info;
 
4647
  GtkIconView *icon_view = GTK_ICON_VIEW (layout);
 
4648
 
 
4649
  info = gtk_icon_view_get_cell_info (icon_view, renderer);
 
4650
  g_return_if_fail (info != NULL);
 
4651
 
 
4652
  info->attributes = g_slist_prepend (info->attributes,
 
4653
                                      GINT_TO_POINTER (column));
 
4654
  info->attributes = g_slist_prepend (info->attributes,
 
4655
                                      g_strdup (attribute));
 
4656
}
 
4657
 
 
4658
static void
 
4659
gtk_icon_view_cell_layout_clear (GtkCellLayout *layout)
 
4660
{
 
4661
  GtkIconView *icon_view = GTK_ICON_VIEW (layout);
 
4662
 
 
4663
  while (icon_view->priv->cell_list)
 
4664
    {
 
4665
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)icon_view->priv->cell_list->data;
 
4666
      free_cell_info (info);
 
4667
      icon_view->priv->cell_list = g_list_delete_link (icon_view->priv->cell_list, 
 
4668
                                                       icon_view->priv->cell_list);
 
4669
    }
 
4670
 
 
4671
  icon_view->priv->n_cells = 0;
 
4672
}
 
4673
 
 
4674
static void
 
4675
gtk_icon_view_cell_layout_set_cell_data_func (GtkCellLayout         *layout,
 
4676
                                              GtkCellRenderer       *cell,
 
4677
                                              GtkCellLayoutDataFunc  func,
 
4678
                                              gpointer               func_data,
 
4679
                                              GDestroyNotify         destroy)
 
4680
{
 
4681
  GtkIconViewCellInfo *info;
 
4682
  GtkIconView *icon_view = GTK_ICON_VIEW (layout);
 
4683
 
 
4684
  info = gtk_icon_view_get_cell_info (icon_view, cell);
 
4685
  g_return_if_fail (info != NULL);
 
4686
 
 
4687
  if (info->destroy)
 
4688
    {
 
4689
      GDestroyNotify d = info->destroy;
 
4690
 
 
4691
      info->destroy = NULL;
 
4692
      d (info->func_data);
 
4693
    }
 
4694
 
 
4695
  info->func = func;
 
4696
  info->func_data = func_data;
 
4697
  info->destroy = destroy;
 
4698
}
 
4699
 
 
4700
static void
 
4701
gtk_icon_view_cell_layout_clear_attributes (GtkCellLayout   *layout,
 
4702
                                            GtkCellRenderer *renderer)
 
4703
{
 
4704
  GtkIconViewCellInfo *info;
 
4705
 
 
4706
  info = gtk_icon_view_get_cell_info (GTK_ICON_VIEW (layout), renderer);
 
4707
  if (info != NULL)
 
4708
    free_cell_attributes (info);
 
4709
}
 
4710
 
 
4711
static void
 
4712
gtk_icon_view_cell_layout_reorder (GtkCellLayout   *layout,
 
4713
                                   GtkCellRenderer *cell,
 
4714
                                   gint             position)
 
4715
{
 
4716
  GtkIconView *icon_view;
 
4717
  GList *link, *l;
 
4718
  GtkIconViewCellInfo *info;
 
4719
  gint i;
 
4720
 
 
4721
  icon_view = GTK_ICON_VIEW (layout);
 
4722
 
 
4723
  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
 
4724
 
 
4725
  info = gtk_icon_view_get_cell_info (icon_view, cell);
 
4726
 
 
4727
  g_return_if_fail (info != NULL);
 
4728
  g_return_if_fail (position >= 0);
 
4729
 
 
4730
  link = g_list_find (icon_view->priv->cell_list, info);
 
4731
 
 
4732
  g_return_if_fail (link != NULL);
 
4733
 
 
4734
  icon_view->priv->cell_list = g_list_delete_link (icon_view->priv->cell_list,
 
4735
                                                   link);
 
4736
  icon_view->priv->cell_list = g_list_insert (icon_view->priv->cell_list,
 
4737
                                             info, position);
 
4738
 
 
4739
  for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
4740
    {
 
4741
      info = l->data;
 
4742
 
 
4743
      info->position = i;
 
4744
    }
 
4745
 
 
4746
  gtk_widget_queue_draw (GTK_WIDGET (icon_view));
 
4747
}
 
4748
 
 
4749
static GList *
 
4750
gtk_icon_view_cell_layout_get_cells (GtkCellLayout *layout)
 
4751
{
 
4752
  GtkIconView *icon_view = (GtkIconView *)layout;
 
4753
  GList *retval = NULL, *l;
 
4754
 
 
4755
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
4756
    {
 
4757
      GtkIconViewCellInfo *info = (GtkIconViewCellInfo *)l->data;
 
4758
 
 
4759
      retval = g_list_prepend (retval, info->cell);
 
4760
    }
 
4761
 
 
4762
  return g_list_reverse (retval);
 
4763
}
 
4764
 
 
4765
/* Public API */
 
4766
 
 
4767
 
 
4768
/**
 
4769
 * gtk_icon_view_new:
 
4770
 * 
 
4771
 * Creates a new #GtkIconView widget
 
4772
 * 
 
4773
 * Return value: A newly created #GtkIconView widget
 
4774
 *
 
4775
 * Since: 2.6
 
4776
 **/
 
4777
GtkWidget *
 
4778
gtk_icon_view_new (void)
 
4779
{
 
4780
  return g_object_new (GTK_TYPE_ICON_VIEW, NULL);
 
4781
}
 
4782
 
 
4783
/**
 
4784
 * gtk_icon_view_new_with_model:
 
4785
 * @model: The model.
 
4786
 * 
 
4787
 * Creates a new #GtkIconView widget with the model @model.
 
4788
 * 
 
4789
 * Return value: A newly created #GtkIconView widget.
 
4790
 *
 
4791
 * Since: 2.6 
 
4792
 **/
 
4793
GtkWidget *
 
4794
gtk_icon_view_new_with_model (GtkTreeModel *model)
 
4795
{
 
4796
  return g_object_new (GTK_TYPE_ICON_VIEW, "model", model, NULL);
 
4797
}
 
4798
 
 
4799
/**
 
4800
 * gtk_icon_view_convert_widget_to_bin_window_coords:
 
4801
 * @icon_view: a #GtkIconView 
 
4802
 * @wx: X coordinate relative to the widget
 
4803
 * @wy: Y coordinate relative to the widget
 
4804
 * @bx: (out): return location for bin_window X coordinate
 
4805
 * @by: (out): return location for bin_window Y coordinate
 
4806
 * 
 
4807
 * Converts widget coordinates to coordinates for the bin_window,
 
4808
 * as expected by e.g. gtk_icon_view_get_path_at_pos(). 
 
4809
 *
 
4810
 * Since: 2.12
 
4811
 */
 
4812
void
 
4813
gtk_icon_view_convert_widget_to_bin_window_coords (GtkIconView *icon_view,
 
4814
                                                   gint         wx,
 
4815
                                                   gint         wy, 
 
4816
                                                   gint        *bx,
 
4817
                                                   gint        *by)
 
4818
{
 
4819
  gint x, y;
 
4820
 
 
4821
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
4822
 
 
4823
  if (icon_view->priv->bin_window) 
 
4824
    gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
 
4825
  else
 
4826
    x = y = 0;
 
4827
 
 
4828
  if (bx)
 
4829
    *bx = wx - x;
 
4830
  if (by)
 
4831
    *by = wy - y;
 
4832
}
 
4833
 
 
4834
/**
 
4835
 * gtk_icon_view_get_path_at_pos:
 
4836
 * @icon_view: A #GtkIconView.
 
4837
 * @x: The x position to be identified
 
4838
 * @y: The y position to be identified
 
4839
 * 
 
4840
 * Finds the path at the point (@x, @y), relative to bin_window coordinates.
 
4841
 * See gtk_icon_view_get_item_at_pos(), if you are also interested in
 
4842
 * the cell at the specified position. 
 
4843
 * See gtk_icon_view_convert_widget_to_bin_window_coords() for converting
 
4844
 * widget coordinates to bin_window coordinates.
 
4845
 * 
 
4846
 * Return value: The #GtkTreePath corresponding to the icon or %NULL
 
4847
 * if no icon exists at that position.
 
4848
 *
 
4849
 * Since: 2.6 
 
4850
 **/
 
4851
GtkTreePath *
 
4852
gtk_icon_view_get_path_at_pos (GtkIconView *icon_view,
 
4853
                               gint         x,
 
4854
                               gint         y)
 
4855
{
 
4856
  GtkIconViewItem *item;
 
4857
  GtkTreePath *path;
 
4858
  
 
4859
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
 
4860
 
 
4861
  item = gtk_icon_view_get_item_at_coords (icon_view, x, y, TRUE, NULL);
 
4862
 
 
4863
  if (!item)
 
4864
    return NULL;
 
4865
 
 
4866
  path = gtk_tree_path_new_from_indices (item->index, -1);
 
4867
 
 
4868
  return path;
 
4869
}
 
4870
 
 
4871
/**
 
4872
 * gtk_icon_view_get_item_at_pos:
 
4873
 * @icon_view: A #GtkIconView.
 
4874
 * @x: The x position to be identified
 
4875
 * @y: The y position to be identified
 
4876
 * @path: (allow-none): Return location for the path, or %NULL
 
4877
 * @cell: Return location for the renderer responsible for the cell
 
4878
 *   at (@x, @y), or %NULL
 
4879
 * 
 
4880
 * Finds the path at the point (@x, @y), relative to bin_window coordinates.
 
4881
 * In contrast to gtk_icon_view_get_path_at_pos(), this function also 
 
4882
 * obtains the cell at the specified position. The returned path should
 
4883
 * be freed with gtk_tree_path_free().
 
4884
 * See gtk_icon_view_convert_widget_to_bin_window_coords() for converting
 
4885
 * widget coordinates to bin_window coordinates.
 
4886
 * 
 
4887
 * Return value: %TRUE if an item exists at the specified position
 
4888
 *
 
4889
 * Since: 2.8
 
4890
 **/
 
4891
gboolean 
 
4892
gtk_icon_view_get_item_at_pos (GtkIconView      *icon_view,
 
4893
                               gint              x,
 
4894
                               gint              y,
 
4895
                               GtkTreePath     **path,
 
4896
                               GtkCellRenderer **cell)
 
4897
{
 
4898
  GtkIconViewItem *item;
 
4899
  GtkIconViewCellInfo *info;
 
4900
  
 
4901
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
4902
 
 
4903
  item = gtk_icon_view_get_item_at_coords (icon_view, x, y, TRUE, &info);
 
4904
 
 
4905
  if (path != NULL)
 
4906
    {
 
4907
      if (item != NULL)
 
4908
        *path = gtk_tree_path_new_from_indices (item->index, -1);
 
4909
      else
 
4910
        *path = NULL;
 
4911
    }
 
4912
 
 
4913
  if (cell != NULL)
 
4914
    {
 
4915
      if (info != NULL)
 
4916
        *cell = info->cell;
 
4917
      else 
 
4918
        *cell = NULL;
 
4919
    }
 
4920
 
 
4921
  return (item != NULL);
 
4922
}
 
4923
 
 
4924
/**
 
4925
 * gtk_icon_view_set_tooltip_item:
 
4926
 * @icon_view: a #GtkIconView
 
4927
 * @tooltip: a #GtkTooltip
 
4928
 * @path: a #GtkTreePath
 
4929
 * 
 
4930
 * Sets the tip area of @tooltip to be the area covered by the item at @path.
 
4931
 * See also gtk_icon_view_set_tooltip_column() for a simpler alternative.
 
4932
 * See also gtk_tooltip_set_tip_area().
 
4933
 * 
 
4934
 * Since: 2.12
 
4935
 */
 
4936
void 
 
4937
gtk_icon_view_set_tooltip_item (GtkIconView     *icon_view,
 
4938
                                GtkTooltip      *tooltip,
 
4939
                                GtkTreePath     *path)
 
4940
{
 
4941
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
4942
  g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
 
4943
 
 
4944
  gtk_icon_view_set_tooltip_cell (icon_view, tooltip, path, NULL);
 
4945
}
 
4946
 
 
4947
/**
 
4948
 * gtk_icon_view_set_tooltip_cell:
 
4949
 * @icon_view: a #GtkIconView
 
4950
 * @tooltip: a #GtkTooltip
 
4951
 * @path: a #GtkTreePath
 
4952
 * @cell: (allow-none): a #GtkCellRenderer or %NULL
 
4953
 *
 
4954
 * Sets the tip area of @tooltip to the area which @cell occupies in
 
4955
 * the item pointed to by @path. See also gtk_tooltip_set_tip_area().
 
4956
 *
 
4957
 * See also gtk_icon_view_set_tooltip_column() for a simpler alternative.
 
4958
 *
 
4959
 * Since: 2.12
 
4960
 */
 
4961
void
 
4962
gtk_icon_view_set_tooltip_cell (GtkIconView     *icon_view,
 
4963
                                GtkTooltip      *tooltip,
 
4964
                                GtkTreePath     *path,
 
4965
                                GtkCellRenderer *cell)
 
4966
{
 
4967
  GdkRectangle rect;
 
4968
  GtkIconViewItem *item = NULL;
 
4969
  GtkIconViewCellInfo *info = NULL;
 
4970
  gint x, y;
 
4971
 
 
4972
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
4973
  g_return_if_fail (GTK_IS_TOOLTIP (tooltip));
 
4974
  g_return_if_fail (cell == NULL || GTK_IS_CELL_RENDERER (cell));
 
4975
 
 
4976
  if (gtk_tree_path_get_depth (path) > 0)
 
4977
    item = g_list_nth_data (icon_view->priv->items,
 
4978
                            gtk_tree_path_get_indices(path)[0]);
 
4979
 
 
4980
  if (!item)
 
4981
    return;
 
4982
 
 
4983
  if (cell)
 
4984
    {
 
4985
      info = gtk_icon_view_get_cell_info (icon_view, cell);
 
4986
      gtk_icon_view_get_cell_area (icon_view, item, info, &rect);
 
4987
    }
 
4988
  else
 
4989
    {
 
4990
      rect.x = item->x;
 
4991
      rect.y = item->y;
 
4992
      rect.width = item->width;
 
4993
      rect.height = item->height;
 
4994
    }
 
4995
  
 
4996
  if (icon_view->priv->bin_window)
 
4997
    {
 
4998
      gdk_window_get_position (icon_view->priv->bin_window, &x, &y);
 
4999
      rect.x += x;
 
5000
      rect.y += y; 
 
5001
    }
 
5002
 
 
5003
  gtk_tooltip_set_tip_area (tooltip, &rect); 
 
5004
}
 
5005
 
 
5006
 
 
5007
/**
 
5008
 * gtk_icon_view_get_tooltip_context:
 
5009
 * @icon_view: an #GtkIconView
 
5010
 * @x: (inout): the x coordinate (relative to widget coordinates)
 
5011
 * @y: (inout): the y coordinate (relative to widget coordinates)
 
5012
 * @keyboard_tip: whether this is a keyboard tooltip or not
 
5013
 * @model: (out) (allow-none): a pointer to receive a #GtkTreeModel or %NULL
 
5014
 * @path: (out) (allow-none): a pointer to receive a #GtkTreePath or %NULL
 
5015
 * @iter: (out) (allow-none): a pointer to receive a #GtkTreeIter or %NULL
 
5016
 *
 
5017
 * This function is supposed to be used in a #GtkWidget::query-tooltip
 
5018
 * signal handler for #GtkIconView.  The @x, @y and @keyboard_tip values
 
5019
 * which are received in the signal handler, should be passed to this
 
5020
 * function without modification.
 
5021
 *
 
5022
 * The return value indicates whether there is an icon view item at the given
 
5023
 * coordinates (%TRUE) or not (%FALSE) for mouse tooltips. For keyboard
 
5024
 * tooltips the item returned will be the cursor item. When %TRUE, then any of
 
5025
 * @model, @path and @iter which have been provided will be set to point to
 
5026
 * that row and the corresponding model. @x and @y will always be converted
 
5027
 * to be relative to @icon_view's bin_window if @keyboard_tooltip is %FALSE.
 
5028
 *
 
5029
 * Return value: whether or not the given tooltip context points to a item
 
5030
 *
 
5031
 * Since: 2.12
 
5032
 */
 
5033
gboolean
 
5034
gtk_icon_view_get_tooltip_context (GtkIconView   *icon_view,
 
5035
                                   gint          *x,
 
5036
                                   gint          *y,
 
5037
                                   gboolean       keyboard_tip,
 
5038
                                   GtkTreeModel **model,
 
5039
                                   GtkTreePath  **path,
 
5040
                                   GtkTreeIter   *iter)
 
5041
{
 
5042
  GtkTreePath *tmppath = NULL;
 
5043
 
 
5044
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
5045
  g_return_val_if_fail (x != NULL, FALSE);
 
5046
  g_return_val_if_fail (y != NULL, FALSE);
 
5047
 
 
5048
  if (keyboard_tip)
 
5049
    {
 
5050
      gtk_icon_view_get_cursor (icon_view, &tmppath, NULL);
 
5051
 
 
5052
      if (!tmppath)
 
5053
        return FALSE;
 
5054
    }
 
5055
  else
 
5056
    {
 
5057
      gtk_icon_view_convert_widget_to_bin_window_coords (icon_view, *x, *y,
 
5058
                                                         x, y);
 
5059
 
 
5060
      if (!gtk_icon_view_get_item_at_pos (icon_view, *x, *y, &tmppath, NULL))
 
5061
        return FALSE;
 
5062
    }
 
5063
 
 
5064
  if (model)
 
5065
    *model = gtk_icon_view_get_model (icon_view);
 
5066
 
 
5067
  if (iter)
 
5068
    gtk_tree_model_get_iter (gtk_icon_view_get_model (icon_view),
 
5069
                             iter, tmppath);
 
5070
 
 
5071
  if (path)
 
5072
    *path = tmppath;
 
5073
  else
 
5074
    gtk_tree_path_free (tmppath);
 
5075
 
 
5076
  return TRUE;
 
5077
}
 
5078
 
 
5079
static gboolean
 
5080
gtk_icon_view_set_tooltip_query_cb (GtkWidget  *widget,
 
5081
                                    gint        x,
 
5082
                                    gint        y,
 
5083
                                    gboolean    keyboard_tip,
 
5084
                                    GtkTooltip *tooltip,
 
5085
                                    gpointer    data)
 
5086
{
 
5087
  gchar *str;
 
5088
  GtkTreeIter iter;
 
5089
  GtkTreePath *path;
 
5090
  GtkTreeModel *model;
 
5091
  GtkIconView *icon_view = GTK_ICON_VIEW (widget);
 
5092
 
 
5093
  if (!gtk_icon_view_get_tooltip_context (GTK_ICON_VIEW (widget),
 
5094
                                          &x, &y,
 
5095
                                          keyboard_tip,
 
5096
                                          &model, &path, &iter))
 
5097
    return FALSE;
 
5098
 
 
5099
  gtk_tree_model_get (model, &iter, icon_view->priv->tooltip_column, &str, -1);
 
5100
 
 
5101
  if (!str)
 
5102
    {
 
5103
      gtk_tree_path_free (path);
 
5104
      return FALSE;
 
5105
    }
 
5106
 
 
5107
  gtk_tooltip_set_markup (tooltip, str);
 
5108
  gtk_icon_view_set_tooltip_item (icon_view, tooltip, path);
 
5109
 
 
5110
  gtk_tree_path_free (path);
 
5111
  g_free (str);
 
5112
 
 
5113
  return TRUE;
 
5114
}
 
5115
 
 
5116
 
 
5117
/**
 
5118
 * gtk_icon_view_set_tooltip_column:
 
5119
 * @icon_view: a #GtkIconView
 
5120
 * @column: an integer, which is a valid column number for @icon_view's model
 
5121
 *
 
5122
 * If you only plan to have simple (text-only) tooltips on full items, you
 
5123
 * can use this function to have #GtkIconView handle these automatically
 
5124
 * for you. @column should be set to the column in @icon_view's model
 
5125
 * containing the tooltip texts, or -1 to disable this feature.
 
5126
 *
 
5127
 * When enabled, #GtkWidget::has-tooltip will be set to %TRUE and
 
5128
 * @icon_view will connect a #GtkWidget::query-tooltip signal handler.
 
5129
 *
 
5130
 * Since: 2.12
 
5131
 */
 
5132
void
 
5133
gtk_icon_view_set_tooltip_column (GtkIconView *icon_view,
 
5134
                                  gint         column)
 
5135
{
 
5136
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5137
 
 
5138
  if (column == icon_view->priv->tooltip_column)
 
5139
    return;
 
5140
 
 
5141
  if (column == -1)
 
5142
    {
 
5143
      g_signal_handlers_disconnect_by_func (icon_view,
 
5144
                                            gtk_icon_view_set_tooltip_query_cb,
 
5145
                                            NULL);
 
5146
      gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), FALSE);
 
5147
    }
 
5148
  else
 
5149
    {
 
5150
      if (icon_view->priv->tooltip_column == -1)
 
5151
        {
 
5152
          g_signal_connect (icon_view, "query-tooltip",
 
5153
                            G_CALLBACK (gtk_icon_view_set_tooltip_query_cb), NULL);
 
5154
          gtk_widget_set_has_tooltip (GTK_WIDGET (icon_view), TRUE);
 
5155
        }
 
5156
    }
 
5157
 
 
5158
  icon_view->priv->tooltip_column = column;
 
5159
  g_object_notify (G_OBJECT (icon_view), "tooltip-column");
 
5160
}
 
5161
 
 
5162
/** 
 
5163
 * gtk_icon_view_get_tooltip_column:
 
5164
 * @icon_view: a #GtkIconView
 
5165
 *
 
5166
 * Returns the column of @icon_view's model which is being used for
 
5167
 * displaying tooltips on @icon_view's rows.
 
5168
 *
 
5169
 * Return value: the index of the tooltip column that is currently being
 
5170
 * used, or -1 if this is disabled.
 
5171
 *
 
5172
 * Since: 2.12
 
5173
 */
 
5174
gint
 
5175
gtk_icon_view_get_tooltip_column (GtkIconView *icon_view)
 
5176
{
 
5177
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), 0);
 
5178
 
 
5179
  return icon_view->priv->tooltip_column;
 
5180
}
 
5181
 
 
5182
/**
 
5183
 * gtk_icon_view_get_visible_range:
 
5184
 * @icon_view: A #GtkIconView
 
5185
 * @start_path: (allow-none): Return location for start of region, or %NULL
 
5186
 * @end_path: (allow-none): Return location for end of region, or %NULL
 
5187
 * 
 
5188
 * Sets @start_path and @end_path to be the first and last visible path. 
 
5189
 * Note that there may be invisible paths in between.
 
5190
 * 
 
5191
 * Both paths should be freed with gtk_tree_path_free() after use.
 
5192
 * 
 
5193
 * Return value: %TRUE, if valid paths were placed in @start_path and @end_path
 
5194
 *
 
5195
 * Since: 2.8
 
5196
 **/
 
5197
gboolean
 
5198
gtk_icon_view_get_visible_range (GtkIconView  *icon_view,
 
5199
                                 GtkTreePath **start_path,
 
5200
                                 GtkTreePath **end_path)
 
5201
{
 
5202
  gint start_index = -1;
 
5203
  gint end_index = -1;
 
5204
  GList *icons;
 
5205
 
 
5206
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
5207
 
 
5208
  if (icon_view->priv->hadjustment == NULL ||
 
5209
      icon_view->priv->vadjustment == NULL)
 
5210
    return FALSE;
 
5211
 
 
5212
  if (start_path == NULL && end_path == NULL)
 
5213
    return FALSE;
 
5214
  
 
5215
  for (icons = icon_view->priv->items; icons; icons = icons->next) 
 
5216
    {
 
5217
      GtkIconViewItem *item = icons->data;
 
5218
 
 
5219
      if ((item->x + item->width >= (int)icon_view->priv->hadjustment->value) &&
 
5220
          (item->y + item->height >= (int)icon_view->priv->vadjustment->value) &&
 
5221
          (item->x <= (int) (icon_view->priv->hadjustment->value + icon_view->priv->hadjustment->page_size)) &&
 
5222
          (item->y <= (int) (icon_view->priv->vadjustment->value + icon_view->priv->vadjustment->page_size)))
 
5223
        {
 
5224
          if (start_index == -1)
 
5225
            start_index = item->index;
 
5226
          end_index = item->index;
 
5227
        }
 
5228
    }
 
5229
 
 
5230
  if (start_path && start_index != -1)
 
5231
    *start_path = gtk_tree_path_new_from_indices (start_index, -1);
 
5232
  if (end_path && end_index != -1)
 
5233
    *end_path = gtk_tree_path_new_from_indices (end_index, -1);
 
5234
  
 
5235
  return start_index != -1;
 
5236
}
 
5237
 
 
5238
/**
 
5239
 * gtk_icon_view_selected_foreach:
 
5240
 * @icon_view: A #GtkIconView.
 
5241
 * @func: (scope call): The function to call for each selected icon.
 
5242
 * @data: User data to pass to the function.
 
5243
 * 
 
5244
 * Calls a function for each selected icon. Note that the model or
 
5245
 * selection cannot be modified from within this function.
 
5246
 *
 
5247
 * Since: 2.6 
 
5248
 **/
 
5249
void
 
5250
gtk_icon_view_selected_foreach (GtkIconView           *icon_view,
 
5251
                                GtkIconViewForeachFunc func,
 
5252
                                gpointer               data)
 
5253
{
 
5254
  GList *list;
 
5255
  
 
5256
  for (list = icon_view->priv->items; list; list = list->next)
 
5257
    {
 
5258
      GtkIconViewItem *item = list->data;
 
5259
      GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
 
5260
 
 
5261
      if (item->selected)
 
5262
        (* func) (icon_view, path, data);
 
5263
 
 
5264
      gtk_tree_path_free (path);
 
5265
    }
 
5266
}
 
5267
 
 
5268
/**
 
5269
 * gtk_icon_view_set_selection_mode:
 
5270
 * @icon_view: A #GtkIconView.
 
5271
 * @mode: The selection mode
 
5272
 * 
 
5273
 * Sets the selection mode of the @icon_view.
 
5274
 *
 
5275
 * Since: 2.6 
 
5276
 **/
 
5277
void
 
5278
gtk_icon_view_set_selection_mode (GtkIconView      *icon_view,
 
5279
                                  GtkSelectionMode  mode)
 
5280
{
 
5281
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5282
 
 
5283
  if (mode == icon_view->priv->selection_mode)
 
5284
    return;
 
5285
  
 
5286
  if (mode == GTK_SELECTION_NONE ||
 
5287
      icon_view->priv->selection_mode == GTK_SELECTION_MULTIPLE)
 
5288
    gtk_icon_view_unselect_all (icon_view);
 
5289
  
 
5290
  icon_view->priv->selection_mode = mode;
 
5291
 
 
5292
  g_object_notify (G_OBJECT (icon_view), "selection-mode");
 
5293
}
 
5294
 
 
5295
/**
 
5296
 * gtk_icon_view_get_selection_mode:
 
5297
 * @icon_view: A #GtkIconView.
 
5298
 * 
 
5299
 * Gets the selection mode of the @icon_view.
 
5300
 *
 
5301
 * Return value: the current selection mode
 
5302
 *
 
5303
 * Since: 2.6 
 
5304
 **/
 
5305
GtkSelectionMode
 
5306
gtk_icon_view_get_selection_mode (GtkIconView *icon_view)
 
5307
{
 
5308
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), GTK_SELECTION_SINGLE);
 
5309
 
 
5310
  return icon_view->priv->selection_mode;
 
5311
}
 
5312
 
 
5313
/**
 
5314
 * gtk_icon_view_set_model:
 
5315
 * @icon_view: A #GtkIconView.
 
5316
 * @model: (allow-none): The model.
 
5317
 *
 
5318
 * Sets the model for a #GtkIconView.
 
5319
 * If the @icon_view already has a model set, it will remove
 
5320
 * it before setting the new model.  If @model is %NULL, then
 
5321
 * it will unset the old model.
 
5322
 *
 
5323
 * Since: 2.6 
 
5324
 **/
 
5325
void
 
5326
gtk_icon_view_set_model (GtkIconView *icon_view,
 
5327
                         GtkTreeModel *model)
 
5328
{
 
5329
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5330
  g_return_if_fail (model == NULL || GTK_IS_TREE_MODEL (model));
 
5331
  
 
5332
  if (icon_view->priv->model == model)
 
5333
    return;
 
5334
 
 
5335
  if (icon_view->priv->scroll_to_path)
 
5336
    {
 
5337
      gtk_tree_row_reference_free (icon_view->priv->scroll_to_path);
 
5338
      icon_view->priv->scroll_to_path = NULL;
 
5339
    }
 
5340
 
 
5341
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
5342
 
 
5343
  if (model)
 
5344
    {
 
5345
      GType column_type;
 
5346
      
 
5347
      g_return_if_fail (gtk_tree_model_get_flags (model) & GTK_TREE_MODEL_LIST_ONLY);
 
5348
 
 
5349
      if (icon_view->priv->pixbuf_column != -1)
 
5350
        {
 
5351
          column_type = gtk_tree_model_get_column_type (model,
 
5352
                                                        icon_view->priv->pixbuf_column);          
 
5353
 
 
5354
          g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
 
5355
        }
 
5356
 
 
5357
      if (icon_view->priv->text_column != -1)
 
5358
        {
 
5359
          column_type = gtk_tree_model_get_column_type (model,
 
5360
                                                        icon_view->priv->text_column);    
 
5361
 
 
5362
          g_return_if_fail (column_type == G_TYPE_STRING);
 
5363
        }
 
5364
 
 
5365
      if (icon_view->priv->markup_column != -1)
 
5366
        {
 
5367
          column_type = gtk_tree_model_get_column_type (model,
 
5368
                                                        icon_view->priv->markup_column);          
 
5369
 
 
5370
          g_return_if_fail (column_type == G_TYPE_STRING);
 
5371
        }
 
5372
      
 
5373
    }
 
5374
  
 
5375
  if (icon_view->priv->model)
 
5376
    {
 
5377
      g_signal_handlers_disconnect_by_func (icon_view->priv->model,
 
5378
                                            gtk_icon_view_row_changed,
 
5379
                                            icon_view);
 
5380
      g_signal_handlers_disconnect_by_func (icon_view->priv->model,
 
5381
                                            gtk_icon_view_row_inserted,
 
5382
                                            icon_view);
 
5383
      g_signal_handlers_disconnect_by_func (icon_view->priv->model,
 
5384
                                            gtk_icon_view_row_deleted,
 
5385
                                            icon_view);
 
5386
      g_signal_handlers_disconnect_by_func (icon_view->priv->model,
 
5387
                                            gtk_icon_view_rows_reordered,
 
5388
                                            icon_view);
 
5389
 
 
5390
      g_object_unref (icon_view->priv->model);
 
5391
      
 
5392
      g_list_foreach (icon_view->priv->items, (GFunc)gtk_icon_view_item_free, NULL);
 
5393
      g_list_free (icon_view->priv->items);
 
5394
      icon_view->priv->items = NULL;
 
5395
      icon_view->priv->anchor_item = NULL;
 
5396
      icon_view->priv->cursor_item = NULL;
 
5397
      icon_view->priv->last_single_clicked = NULL;
 
5398
      icon_view->priv->width = 0;
 
5399
      icon_view->priv->height = 0;
 
5400
    }
 
5401
 
 
5402
  icon_view->priv->model = model;
 
5403
 
 
5404
  if (icon_view->priv->model)
 
5405
    {
 
5406
      g_object_ref (icon_view->priv->model);
 
5407
      g_signal_connect (icon_view->priv->model,
 
5408
                        "row-changed",
 
5409
                        G_CALLBACK (gtk_icon_view_row_changed),
 
5410
                        icon_view);
 
5411
      g_signal_connect (icon_view->priv->model,
 
5412
                        "row-inserted",
 
5413
                        G_CALLBACK (gtk_icon_view_row_inserted),
 
5414
                        icon_view);
 
5415
      g_signal_connect (icon_view->priv->model,
 
5416
                        "row-deleted",
 
5417
                        G_CALLBACK (gtk_icon_view_row_deleted),
 
5418
                        icon_view);
 
5419
      g_signal_connect (icon_view->priv->model,
 
5420
                        "rows-reordered",
 
5421
                        G_CALLBACK (gtk_icon_view_rows_reordered),
 
5422
                        icon_view);
 
5423
 
 
5424
      gtk_icon_view_build_items (icon_view);
 
5425
 
 
5426
      gtk_icon_view_layout (icon_view);
 
5427
    }
 
5428
 
 
5429
  g_object_notify (G_OBJECT (icon_view), "model");  
 
5430
 
 
5431
  if (gtk_widget_get_realized (GTK_WIDGET (icon_view)))
 
5432
    gtk_widget_queue_resize (GTK_WIDGET (icon_view));
 
5433
}
 
5434
 
 
5435
/**
 
5436
 * gtk_icon_view_get_model:
 
5437
 * @icon_view: a #GtkIconView
 
5438
 *
 
5439
 * Returns the model the #GtkIconView is based on.  Returns %NULL if the
 
5440
 * model is unset.
 
5441
 *
 
5442
 * Return value: (transfer none): A #GtkTreeModel, or %NULL if none is
 
5443
 *     currently being used.
 
5444
 *
 
5445
 * Since: 2.6 
 
5446
 **/
 
5447
GtkTreeModel *
 
5448
gtk_icon_view_get_model (GtkIconView *icon_view)
 
5449
{
 
5450
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
 
5451
 
 
5452
  return icon_view->priv->model;
 
5453
}
 
5454
 
 
5455
static void
 
5456
update_text_cell (GtkIconView *icon_view)
 
5457
{
 
5458
  GtkIconViewCellInfo *info;
 
5459
  GList *l;
 
5460
  gint i;
 
5461
          
 
5462
  if (icon_view->priv->text_column == -1 &&
 
5463
      icon_view->priv->markup_column == -1)
 
5464
    {
 
5465
      if (icon_view->priv->text_cell != -1)
 
5466
        {
 
5467
          if (icon_view->priv->pixbuf_cell > icon_view->priv->text_cell)
 
5468
            icon_view->priv->pixbuf_cell--;
 
5469
 
 
5470
          info = g_list_nth_data (icon_view->priv->cell_list, 
 
5471
                                  icon_view->priv->text_cell);
 
5472
          
 
5473
          icon_view->priv->cell_list = g_list_remove (icon_view->priv->cell_list, info);
 
5474
          
 
5475
          free_cell_info (info);
 
5476
          
 
5477
          icon_view->priv->n_cells--;
 
5478
          icon_view->priv->text_cell = -1;
 
5479
        }
 
5480
    }
 
5481
  else 
 
5482
    {
 
5483
      if (icon_view->priv->text_cell == -1)
 
5484
        {
 
5485
          GtkCellRenderer *cell = gtk_cell_renderer_text_new ();
 
5486
          gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (icon_view), cell, FALSE);
 
5487
          for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
5488
            {
 
5489
              info = l->data;
 
5490
              if (info->cell == cell)
 
5491
                {
 
5492
                  icon_view->priv->text_cell = i;
 
5493
                  break;
 
5494
                }
 
5495
            }
 
5496
        }
 
5497
      
 
5498
      info = g_list_nth_data (icon_view->priv->cell_list,
 
5499
                              icon_view->priv->text_cell);
 
5500
 
 
5501
      if (icon_view->priv->markup_column != -1)
 
5502
        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
 
5503
                                        info->cell, 
 
5504
                                        "markup", icon_view->priv->markup_column, 
 
5505
                                        NULL);
 
5506
      else
 
5507
        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
 
5508
                                        info->cell, 
 
5509
                                        "text", icon_view->priv->text_column, 
 
5510
                                        NULL);
 
5511
 
 
5512
      if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
 
5513
        g_object_set (info->cell,
 
5514
                      "alignment", PANGO_ALIGN_CENTER,
 
5515
                      "wrap-mode", PANGO_WRAP_WORD_CHAR,
 
5516
                      "xalign", 0.0,
 
5517
                      "yalign", 0.0,
 
5518
                      NULL);
 
5519
      else
 
5520
        g_object_set (info->cell,
 
5521
                      "alignment", PANGO_ALIGN_LEFT,
 
5522
                      "wrap-mode", PANGO_WRAP_WORD_CHAR,
 
5523
                      "xalign", 0.0,
 
5524
                      "yalign", 0.0,
 
5525
                      NULL);
 
5526
    }
 
5527
}
 
5528
 
 
5529
static void
 
5530
update_pixbuf_cell (GtkIconView *icon_view)
 
5531
{
 
5532
  GtkIconViewCellInfo *info;
 
5533
  GList *l;
 
5534
  gint i;
 
5535
 
 
5536
  if (icon_view->priv->pixbuf_column == -1)
 
5537
    {
 
5538
      if (icon_view->priv->pixbuf_cell != -1)
 
5539
        {
 
5540
          if (icon_view->priv->text_cell > icon_view->priv->pixbuf_cell)
 
5541
            icon_view->priv->text_cell--;
 
5542
 
 
5543
          info = g_list_nth_data (icon_view->priv->cell_list, 
 
5544
                                  icon_view->priv->pixbuf_cell);
 
5545
          
 
5546
          icon_view->priv->cell_list = g_list_remove (icon_view->priv->cell_list, info);
 
5547
          
 
5548
          free_cell_info (info);
 
5549
          
 
5550
          icon_view->priv->n_cells--;
 
5551
          icon_view->priv->pixbuf_cell = -1;
 
5552
        }
 
5553
    }
 
5554
  else 
 
5555
    {
 
5556
      if (icon_view->priv->pixbuf_cell == -1)
 
5557
        {
 
5558
          GtkCellRenderer *cell = gtk_cell_renderer_pixbuf_new ();
 
5559
          
 
5560
          gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (icon_view), cell, FALSE);
 
5561
          for (l = icon_view->priv->cell_list, i = 0; l; l = l->next, i++)
 
5562
            {
 
5563
              info = l->data;
 
5564
              if (info->cell == cell)
 
5565
                {
 
5566
                  icon_view->priv->pixbuf_cell = i;
 
5567
                  break;
 
5568
                }
 
5569
            }
 
5570
        }
 
5571
      
 
5572
        info = g_list_nth_data (icon_view->priv->cell_list, 
 
5573
                                icon_view->priv->pixbuf_cell);
 
5574
        
 
5575
        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (icon_view),
 
5576
                                        info->cell, 
 
5577
                                        "pixbuf", icon_view->priv->pixbuf_column, 
 
5578
                                        NULL);
 
5579
 
 
5580
        if (icon_view->priv->item_orientation == GTK_ORIENTATION_VERTICAL)
 
5581
          g_object_set (info->cell,
 
5582
                        "xalign", 0.5,
 
5583
                        "yalign", 1.0,
 
5584
                        NULL);
 
5585
        else
 
5586
          g_object_set (info->cell,
 
5587
                        "xalign", 0.0,
 
5588
                        "yalign", 0.0,
 
5589
                        NULL);
 
5590
    }
 
5591
}
 
5592
 
 
5593
/**
 
5594
 * gtk_icon_view_set_text_column:
 
5595
 * @icon_view: A #GtkIconView.
 
5596
 * @column: A column in the currently used model, or -1 to display no text
 
5597
 * 
 
5598
 * Sets the column with text for @icon_view to be @column. The text
 
5599
 * column must be of type #G_TYPE_STRING.
 
5600
 *
 
5601
 * Since: 2.6 
 
5602
 **/
 
5603
void
 
5604
gtk_icon_view_set_text_column (GtkIconView *icon_view,
 
5605
                               gint          column)
 
5606
{
 
5607
  if (column == icon_view->priv->text_column)
 
5608
    return;
 
5609
  
 
5610
  if (column == -1)
 
5611
    icon_view->priv->text_column = -1;
 
5612
  else
 
5613
    {
 
5614
      if (icon_view->priv->model != NULL)
 
5615
        {
 
5616
          GType column_type;
 
5617
          
 
5618
          column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
 
5619
 
 
5620
          g_return_if_fail (column_type == G_TYPE_STRING);
 
5621
        }
 
5622
      
 
5623
      icon_view->priv->text_column = column;
 
5624
    }
 
5625
 
 
5626
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
5627
 
 
5628
  update_text_cell (icon_view);
 
5629
 
 
5630
  gtk_icon_view_invalidate_sizes (icon_view);
 
5631
  gtk_icon_view_queue_layout (icon_view);
 
5632
  
 
5633
  g_object_notify (G_OBJECT (icon_view), "text-column");
 
5634
}
 
5635
 
 
5636
/**
 
5637
 * gtk_icon_view_get_text_column:
 
5638
 * @icon_view: A #GtkIconView.
 
5639
 *
 
5640
 * Returns the column with text for @icon_view.
 
5641
 *
 
5642
 * Returns: the text column, or -1 if it's unset.
 
5643
 *
 
5644
 * Since: 2.6
 
5645
 */
 
5646
gint
 
5647
gtk_icon_view_get_text_column (GtkIconView  *icon_view)
 
5648
{
 
5649
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
5650
 
 
5651
  return icon_view->priv->text_column;
 
5652
}
 
5653
 
 
5654
/**
 
5655
 * gtk_icon_view_set_markup_column:
 
5656
 * @icon_view: A #GtkIconView.
 
5657
 * @column: A column in the currently used model, or -1 to display no text
 
5658
 * 
 
5659
 * Sets the column with markup information for @icon_view to be
 
5660
 * @column. The markup column must be of type #G_TYPE_STRING.
 
5661
 * If the markup column is set to something, it overrides
 
5662
 * the text column set by gtk_icon_view_set_text_column().
 
5663
 *
 
5664
 * Since: 2.6
 
5665
 **/
 
5666
void
 
5667
gtk_icon_view_set_markup_column (GtkIconView *icon_view,
 
5668
                                 gint         column)
 
5669
{
 
5670
  if (column == icon_view->priv->markup_column)
 
5671
    return;
 
5672
  
 
5673
  if (column == -1)
 
5674
    icon_view->priv->markup_column = -1;
 
5675
  else
 
5676
    {
 
5677
      if (icon_view->priv->model != NULL)
 
5678
        {
 
5679
          GType column_type;
 
5680
          
 
5681
          column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
 
5682
 
 
5683
          g_return_if_fail (column_type == G_TYPE_STRING);
 
5684
        }
 
5685
      
 
5686
      icon_view->priv->markup_column = column;
 
5687
    }
 
5688
 
 
5689
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
5690
 
 
5691
  update_text_cell (icon_view);
 
5692
 
 
5693
  gtk_icon_view_invalidate_sizes (icon_view);
 
5694
  gtk_icon_view_queue_layout (icon_view);
 
5695
  
 
5696
  g_object_notify (G_OBJECT (icon_view), "markup-column");
 
5697
}
 
5698
 
 
5699
/**
 
5700
 * gtk_icon_view_get_markup_column:
 
5701
 * @icon_view: A #GtkIconView.
 
5702
 *
 
5703
 * Returns the column with markup text for @icon_view.
 
5704
 *
 
5705
 * Returns: the markup column, or -1 if it's unset.
 
5706
 *
 
5707
 * Since: 2.6
 
5708
 */
 
5709
gint
 
5710
gtk_icon_view_get_markup_column (GtkIconView  *icon_view)
 
5711
{
 
5712
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
5713
 
 
5714
  return icon_view->priv->markup_column;
 
5715
}
 
5716
 
 
5717
/**
 
5718
 * gtk_icon_view_set_pixbuf_column:
 
5719
 * @icon_view: A #GtkIconView.
 
5720
 * @column: A column in the currently used model, or -1 to disable
 
5721
 * 
 
5722
 * Sets the column with pixbufs for @icon_view to be @column. The pixbuf
 
5723
 * column must be of type #GDK_TYPE_PIXBUF
 
5724
 *
 
5725
 * Since: 2.6 
 
5726
 **/
 
5727
void
 
5728
gtk_icon_view_set_pixbuf_column (GtkIconView *icon_view,
 
5729
                                 gint         column)
 
5730
{
 
5731
  if (column == icon_view->priv->pixbuf_column)
 
5732
    return;
 
5733
  
 
5734
  if (column == -1)
 
5735
    icon_view->priv->pixbuf_column = -1;
 
5736
  else
 
5737
    {
 
5738
      if (icon_view->priv->model != NULL)
 
5739
        {
 
5740
          GType column_type;
 
5741
          
 
5742
          column_type = gtk_tree_model_get_column_type (icon_view->priv->model, column);
 
5743
 
 
5744
          g_return_if_fail (column_type == GDK_TYPE_PIXBUF);
 
5745
        }
 
5746
      
 
5747
      icon_view->priv->pixbuf_column = column;
 
5748
    }
 
5749
 
 
5750
  gtk_icon_view_stop_editing (icon_view, TRUE);
 
5751
 
 
5752
  update_pixbuf_cell (icon_view);
 
5753
 
 
5754
  gtk_icon_view_invalidate_sizes (icon_view);
 
5755
  gtk_icon_view_queue_layout (icon_view);
 
5756
  
 
5757
  g_object_notify (G_OBJECT (icon_view), "pixbuf-column");
 
5758
  
 
5759
}
 
5760
 
 
5761
/**
 
5762
 * gtk_icon_view_get_pixbuf_column:
 
5763
 * @icon_view: A #GtkIconView.
 
5764
 *
 
5765
 * Returns the column with pixbufs for @icon_view.
 
5766
 *
 
5767
 * Returns: the pixbuf column, or -1 if it's unset.
 
5768
 *
 
5769
 * Since: 2.6
 
5770
 */
 
5771
gint
 
5772
gtk_icon_view_get_pixbuf_column (GtkIconView  *icon_view)
 
5773
{
 
5774
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
5775
 
 
5776
  return icon_view->priv->pixbuf_column;
 
5777
}
 
5778
 
 
5779
/**
 
5780
 * gtk_icon_view_select_path:
 
5781
 * @icon_view: A #GtkIconView.
 
5782
 * @path: The #GtkTreePath to be selected.
 
5783
 * 
 
5784
 * Selects the row at @path.
 
5785
 *
 
5786
 * Since: 2.6
 
5787
 **/
 
5788
void
 
5789
gtk_icon_view_select_path (GtkIconView *icon_view,
 
5790
                           GtkTreePath *path)
 
5791
{
 
5792
  GtkIconViewItem *item = NULL;
 
5793
 
 
5794
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5795
  g_return_if_fail (icon_view->priv->model != NULL);
 
5796
  g_return_if_fail (path != NULL);
 
5797
 
 
5798
  if (gtk_tree_path_get_depth (path) > 0)
 
5799
    item = g_list_nth_data (icon_view->priv->items,
 
5800
                            gtk_tree_path_get_indices(path)[0]);
 
5801
 
 
5802
  if (item)
 
5803
    gtk_icon_view_select_item (icon_view, item);
 
5804
}
 
5805
 
 
5806
/**
 
5807
 * gtk_icon_view_unselect_path:
 
5808
 * @icon_view: A #GtkIconView.
 
5809
 * @path: The #GtkTreePath to be unselected.
 
5810
 * 
 
5811
 * Unselects the row at @path.
 
5812
 *
 
5813
 * Since: 2.6
 
5814
 **/
 
5815
void
 
5816
gtk_icon_view_unselect_path (GtkIconView *icon_view,
 
5817
                             GtkTreePath *path)
 
5818
{
 
5819
  GtkIconViewItem *item;
 
5820
  
 
5821
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5822
  g_return_if_fail (icon_view->priv->model != NULL);
 
5823
  g_return_if_fail (path != NULL);
 
5824
 
 
5825
  item = g_list_nth_data (icon_view->priv->items,
 
5826
                          gtk_tree_path_get_indices(path)[0]);
 
5827
 
 
5828
  if (!item)
 
5829
    return;
 
5830
  
 
5831
  gtk_icon_view_unselect_item (icon_view, item);
 
5832
}
 
5833
 
 
5834
/**
 
5835
 * gtk_icon_view_get_selected_items:
 
5836
 * @icon_view: A #GtkIconView.
 
5837
 *
 
5838
 * Creates a list of paths of all selected items. Additionally, if you are
 
5839
 * planning on modifying the model after calling this function, you may
 
5840
 * want to convert the returned list into a list of #GtkTreeRowReference<!-- -->s.
 
5841
 * To do this, you can use gtk_tree_row_reference_new().
 
5842
 *
 
5843
 * To free the return value, use:
 
5844
 * |[
 
5845
 * g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
 
5846
 * g_list_free (list);
 
5847
 * ]|
 
5848
 *
 
5849
 * Return value: (element-type GtkTreePath) (transfer full): A #GList containing a #GtkTreePath for each selected row.
 
5850
 *
 
5851
 * Since: 2.6
 
5852
 **/
 
5853
GList *
 
5854
gtk_icon_view_get_selected_items (GtkIconView *icon_view)
 
5855
{
 
5856
  GList *list;
 
5857
  GList *selected = NULL;
 
5858
  
 
5859
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
 
5860
  
 
5861
  for (list = icon_view->priv->items; list != NULL; list = list->next)
 
5862
    {
 
5863
      GtkIconViewItem *item = list->data;
 
5864
 
 
5865
      if (item->selected)
 
5866
        {
 
5867
          GtkTreePath *path = gtk_tree_path_new_from_indices (item->index, -1);
 
5868
 
 
5869
          selected = g_list_prepend (selected, path);
 
5870
        }
 
5871
    }
 
5872
 
 
5873
  return selected;
 
5874
}
 
5875
 
 
5876
/**
 
5877
 * gtk_icon_view_select_all:
 
5878
 * @icon_view: A #GtkIconView.
 
5879
 * 
 
5880
 * Selects all the icons. @icon_view must has its selection mode set
 
5881
 * to #GTK_SELECTION_MULTIPLE.
 
5882
 *
 
5883
 * Since: 2.6
 
5884
 **/
 
5885
void
 
5886
gtk_icon_view_select_all (GtkIconView *icon_view)
 
5887
{
 
5888
  GList *items;
 
5889
  gboolean dirty = FALSE;
 
5890
  
 
5891
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5892
 
 
5893
  if (icon_view->priv->selection_mode != GTK_SELECTION_MULTIPLE)
 
5894
    return;
 
5895
 
 
5896
  for (items = icon_view->priv->items; items; items = items->next)
 
5897
    {
 
5898
      GtkIconViewItem *item = items->data;
 
5899
      
 
5900
      if (!item->selected)
 
5901
        {
 
5902
          dirty = TRUE;
 
5903
          item->selected = TRUE;
 
5904
          gtk_icon_view_queue_draw_item (icon_view, item);
 
5905
        }
 
5906
    }
 
5907
 
 
5908
  if (dirty)
 
5909
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
5910
}
 
5911
 
 
5912
/**
 
5913
 * gtk_icon_view_unselect_all:
 
5914
 * @icon_view: A #GtkIconView.
 
5915
 * 
 
5916
 * Unselects all the icons.
 
5917
 *
 
5918
 * Since: 2.6
 
5919
 **/
 
5920
void
 
5921
gtk_icon_view_unselect_all (GtkIconView *icon_view)
 
5922
{
 
5923
  gboolean dirty = FALSE;
 
5924
  
 
5925
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
5926
 
 
5927
  if (icon_view->priv->selection_mode == GTK_SELECTION_BROWSE)
 
5928
    return;
 
5929
 
 
5930
  dirty = gtk_icon_view_unselect_all_internal (icon_view);
 
5931
 
 
5932
  if (dirty)
 
5933
    g_signal_emit (icon_view, icon_view_signals[SELECTION_CHANGED], 0);
 
5934
}
 
5935
 
 
5936
/**
 
5937
 * gtk_icon_view_path_is_selected:
 
5938
 * @icon_view: A #GtkIconView.
 
5939
 * @path: A #GtkTreePath to check selection on.
 
5940
 * 
 
5941
 * Returns %TRUE if the icon pointed to by @path is currently
 
5942
 * selected. If @path does not point to a valid location, %FALSE is returned.
 
5943
 * 
 
5944
 * Return value: %TRUE if @path is selected.
 
5945
 *
 
5946
 * Since: 2.6
 
5947
 **/
 
5948
gboolean
 
5949
gtk_icon_view_path_is_selected (GtkIconView *icon_view,
 
5950
                                GtkTreePath *path)
 
5951
{
 
5952
  GtkIconViewItem *item;
 
5953
  
 
5954
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
5955
  g_return_val_if_fail (icon_view->priv->model != NULL, FALSE);
 
5956
  g_return_val_if_fail (path != NULL, FALSE);
 
5957
  
 
5958
  item = g_list_nth_data (icon_view->priv->items,
 
5959
                          gtk_tree_path_get_indices(path)[0]);
 
5960
 
 
5961
  if (!item)
 
5962
    return FALSE;
 
5963
  
 
5964
  return item->selected;
 
5965
}
 
5966
 
 
5967
/**
 
5968
 * gtk_icon_view_get_item_row:
 
5969
 * @icon_view: a #GtkIconView
 
5970
 * @path: the #GtkTreePath of the item
 
5971
 *
 
5972
 * Gets the row in which the item @path is currently
 
5973
 * displayed. Row numbers start at 0.
 
5974
 *
 
5975
 * Returns: The row in which the item is displayed
 
5976
 *
 
5977
 * Since: 2.22
 
5978
 */
 
5979
gint
 
5980
gtk_icon_view_get_item_row (GtkIconView *icon_view,
 
5981
                            GtkTreePath *path)
 
5982
{
 
5983
  GtkIconViewItem *item;
 
5984
 
 
5985
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
5986
  g_return_val_if_fail (icon_view->priv->model != NULL, FALSE);
 
5987
  g_return_val_if_fail (path != NULL, FALSE);
 
5988
 
 
5989
  item = g_list_nth_data (icon_view->priv->items,
 
5990
                          gtk_tree_path_get_indices(path)[0]);
 
5991
 
 
5992
  if (!item)
 
5993
    return -1;
 
5994
 
 
5995
  return item->row;
 
5996
}
 
5997
 
 
5998
/**
 
5999
 * gtk_icon_view_get_item_column:
 
6000
 * @icon_view: a #GtkIconView
 
6001
 * @path: the #GtkTreePath of the item
 
6002
 *
 
6003
 * Gets the column in which the item @path is currently
 
6004
 * displayed. Column numbers start at 0.
 
6005
 *
 
6006
 * Returns: The column in which the item is displayed
 
6007
 *
 
6008
 * Since: 2.22
 
6009
 */
 
6010
gint
 
6011
gtk_icon_view_get_item_column (GtkIconView *icon_view,
 
6012
                               GtkTreePath *path)
 
6013
{
 
6014
  GtkIconViewItem *item;
 
6015
 
 
6016
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
6017
  g_return_val_if_fail (icon_view->priv->model != NULL, FALSE);
 
6018
  g_return_val_if_fail (path != NULL, FALSE);
 
6019
 
 
6020
  item = g_list_nth_data (icon_view->priv->items,
 
6021
                          gtk_tree_path_get_indices(path)[0]);
 
6022
 
 
6023
  if (!item)
 
6024
    return -1;
 
6025
 
 
6026
  return item->col;
 
6027
}
 
6028
 
 
6029
/**
 
6030
 * gtk_icon_view_item_activated:
 
6031
 * @icon_view: A #GtkIconView
 
6032
 * @path: The #GtkTreePath to be activated
 
6033
 * 
 
6034
 * Activates the item determined by @path.
 
6035
 *
 
6036
 * Since: 2.6
 
6037
 **/
 
6038
void
 
6039
gtk_icon_view_item_activated (GtkIconView      *icon_view,
 
6040
                              GtkTreePath      *path)
 
6041
{
 
6042
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6043
  g_return_if_fail (path != NULL);
 
6044
  
 
6045
  g_signal_emit (icon_view, icon_view_signals[ITEM_ACTIVATED], 0, path);
 
6046
}
 
6047
 
 
6048
/**
 
6049
 * gtk_icon_view_set_item_orientation:
 
6050
 * @icon_view: a #GtkIconView
 
6051
 * @orientation: the relative position of texts and icons 
 
6052
 * 
 
6053
 * Sets the ::item-orientation property which determines whether
 
6054
 * the labels are drawn beside the icons instead of below.
 
6055
 *
 
6056
 * Since: 2.22
 
6057
 **/
 
6058
void 
 
6059
gtk_icon_view_set_item_orientation (GtkIconView    *icon_view,
 
6060
                                    GtkOrientation  orientation)
 
6061
{
 
6062
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6063
 
 
6064
  if (icon_view->priv->item_orientation != orientation)
 
6065
    {
 
6066
      icon_view->priv->item_orientation = orientation;
 
6067
 
 
6068
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6069
      gtk_icon_view_invalidate_sizes (icon_view);
 
6070
      gtk_icon_view_queue_layout (icon_view);
 
6071
 
 
6072
      update_text_cell (icon_view);
 
6073
      update_pixbuf_cell (icon_view);
 
6074
      
 
6075
      g_object_notify (G_OBJECT (icon_view), "item-orientation");
 
6076
      g_object_notify (G_OBJECT (icon_view), "orientation");
 
6077
    }
 
6078
}
 
6079
 
 
6080
/**
 
6081
 * gtk_icon_view_set_orientation:
 
6082
 * @icon_view: a #GtkIconView
 
6083
 * @orientation: the relative position of texts and icons 
 
6084
 * 
 
6085
 * Sets the ::orientation property which determines whether the labels 
 
6086
 * are drawn beside the icons instead of below.
 
6087
 *
 
6088
 * Since: 2.6
 
6089
 *
 
6090
 * Deprecated: 2.22: Use gtk_icon_view_set_item_orientation()
 
6091
 **/
 
6092
void 
 
6093
gtk_icon_view_set_orientation (GtkIconView    *icon_view,
 
6094
                               GtkOrientation  orientation)
 
6095
{
 
6096
  gtk_icon_view_set_item_orientation (icon_view, orientation);
 
6097
}
 
6098
 
 
6099
/**
 
6100
 * gtk_icon_view_get_item_orientation:
 
6101
 * @icon_view: a #GtkIconView
 
6102
 *
 
6103
 * Returns the value of the ::item-orientation property which determines
 
6104
 * whether the labels are drawn beside the icons instead of below.
 
6105
 *
 
6106
 * Return value: the relative position of texts and icons
 
6107
 *
 
6108
 * Since: 2.22
 
6109
 */
 
6110
GtkOrientation
 
6111
gtk_icon_view_get_item_orientation (GtkIconView *icon_view)
 
6112
{
 
6113
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view),
 
6114
                        GTK_ORIENTATION_VERTICAL);
 
6115
 
 
6116
  return icon_view->priv->item_orientation;
 
6117
}
 
6118
 
 
6119
/**
 
6120
 * gtk_icon_view_get_orientation:
 
6121
 * @icon_view: a #GtkIconView
 
6122
 * 
 
6123
 * Returns the value of the ::orientation property which determines 
 
6124
 * whether the labels are drawn beside the icons instead of below. 
 
6125
 * 
 
6126
 * Return value: the relative position of texts and icons 
 
6127
 *
 
6128
 * Since: 2.6
 
6129
 *
 
6130
 * Deprecated: 2.22: Use gtk_icon_view_get_item_orientation()
 
6131
 **/
 
6132
GtkOrientation
 
6133
gtk_icon_view_get_orientation (GtkIconView *icon_view)
 
6134
{
 
6135
  return gtk_icon_view_get_item_orientation (icon_view);
 
6136
}
 
6137
 
 
6138
/**
 
6139
 * gtk_icon_view_set_columns:
 
6140
 * @icon_view: a #GtkIconView
 
6141
 * @columns: the number of columns
 
6142
 * 
 
6143
 * Sets the ::columns property which determines in how
 
6144
 * many columns the icons are arranged. If @columns is
 
6145
 * -1, the number of columns will be chosen automatically 
 
6146
 * to fill the available area. 
 
6147
 *
 
6148
 * Since: 2.6
 
6149
 */
 
6150
void 
 
6151
gtk_icon_view_set_columns (GtkIconView *icon_view,
 
6152
                           gint         columns)
 
6153
{
 
6154
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6155
  
 
6156
  if (icon_view->priv->columns != columns)
 
6157
    {
 
6158
      icon_view->priv->columns = columns;
 
6159
 
 
6160
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6161
      gtk_icon_view_queue_layout (icon_view);
 
6162
      
 
6163
      g_object_notify (G_OBJECT (icon_view), "columns");
 
6164
    }  
 
6165
}
 
6166
 
 
6167
/**
 
6168
 * gtk_icon_view_get_columns:
 
6169
 * @icon_view: a #GtkIconView
 
6170
 * 
 
6171
 * Returns the value of the ::columns property.
 
6172
 * 
 
6173
 * Return value: the number of columns, or -1
 
6174
 *
 
6175
 * Since: 2.6
 
6176
 */
 
6177
gint
 
6178
gtk_icon_view_get_columns (GtkIconView *icon_view)
 
6179
{
 
6180
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6181
 
 
6182
  return icon_view->priv->columns;
 
6183
}
 
6184
 
 
6185
/**
 
6186
 * gtk_icon_view_set_item_width:
 
6187
 * @icon_view: a #GtkIconView
 
6188
 * @item_width: the width for each item
 
6189
 * 
 
6190
 * Sets the ::item-width property which specifies the width 
 
6191
 * to use for each item. If it is set to -1, the icon view will 
 
6192
 * automatically determine a suitable item size.
 
6193
 *
 
6194
 * Since: 2.6
 
6195
 */
 
6196
void 
 
6197
gtk_icon_view_set_item_width (GtkIconView *icon_view,
 
6198
                              gint         item_width)
 
6199
{
 
6200
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6201
  
 
6202
  if (icon_view->priv->item_width != item_width)
 
6203
    {
 
6204
      icon_view->priv->item_width = item_width;
 
6205
      
 
6206
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6207
      gtk_icon_view_invalidate_sizes (icon_view);
 
6208
      gtk_icon_view_queue_layout (icon_view);
 
6209
      
 
6210
      update_text_cell (icon_view);
 
6211
 
 
6212
      g_object_notify (G_OBJECT (icon_view), "item-width");
 
6213
    }  
 
6214
}
 
6215
 
 
6216
/**
 
6217
 * gtk_icon_view_get_item_width:
 
6218
 * @icon_view: a #GtkIconView
 
6219
 * 
 
6220
 * Returns the value of the ::item-width property.
 
6221
 * 
 
6222
 * Return value: the width of a single item, or -1
 
6223
 *
 
6224
 * Since: 2.6
 
6225
 */
 
6226
gint
 
6227
gtk_icon_view_get_item_width (GtkIconView *icon_view)
 
6228
{
 
6229
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6230
 
 
6231
  return icon_view->priv->item_width;
 
6232
}
 
6233
 
 
6234
 
 
6235
/**
 
6236
 * gtk_icon_view_set_spacing:
 
6237
 * @icon_view: a #GtkIconView
 
6238
 * @spacing: the spacing
 
6239
 * 
 
6240
 * Sets the ::spacing property which specifies the space 
 
6241
 * which is inserted between the cells (i.e. the icon and 
 
6242
 * the text) of an item.
 
6243
 *
 
6244
 * Since: 2.6
 
6245
 */
 
6246
void 
 
6247
gtk_icon_view_set_spacing (GtkIconView *icon_view,
 
6248
                           gint         spacing)
 
6249
{
 
6250
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6251
  
 
6252
  if (icon_view->priv->spacing != spacing)
 
6253
    {
 
6254
      icon_view->priv->spacing = spacing;
 
6255
 
 
6256
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6257
      gtk_icon_view_invalidate_sizes (icon_view);
 
6258
      gtk_icon_view_queue_layout (icon_view);
 
6259
      
 
6260
      g_object_notify (G_OBJECT (icon_view), "spacing");
 
6261
    }  
 
6262
}
 
6263
 
 
6264
/**
 
6265
 * gtk_icon_view_get_spacing:
 
6266
 * @icon_view: a #GtkIconView
 
6267
 * 
 
6268
 * Returns the value of the ::spacing property.
 
6269
 * 
 
6270
 * Return value: the space between cells 
 
6271
 *
 
6272
 * Since: 2.6
 
6273
 */
 
6274
gint
 
6275
gtk_icon_view_get_spacing (GtkIconView *icon_view)
 
6276
{
 
6277
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6278
 
 
6279
  return icon_view->priv->spacing;
 
6280
}
 
6281
 
 
6282
/**
 
6283
 * gtk_icon_view_set_row_spacing:
 
6284
 * @icon_view: a #GtkIconView
 
6285
 * @row_spacing: the row spacing
 
6286
 * 
 
6287
 * Sets the ::row-spacing property which specifies the space 
 
6288
 * which is inserted between the rows of the icon view.
 
6289
 *
 
6290
 * Since: 2.6
 
6291
 */
 
6292
void 
 
6293
gtk_icon_view_set_row_spacing (GtkIconView *icon_view,
 
6294
                               gint         row_spacing)
 
6295
{
 
6296
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6297
  
 
6298
  if (icon_view->priv->row_spacing != row_spacing)
 
6299
    {
 
6300
      icon_view->priv->row_spacing = row_spacing;
 
6301
 
 
6302
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6303
      gtk_icon_view_invalidate_sizes (icon_view);
 
6304
      gtk_icon_view_queue_layout (icon_view);
 
6305
      
 
6306
      g_object_notify (G_OBJECT (icon_view), "row-spacing");
 
6307
    }  
 
6308
}
 
6309
 
 
6310
/**
 
6311
 * gtk_icon_view_get_row_spacing:
 
6312
 * @icon_view: a #GtkIconView
 
6313
 * 
 
6314
 * Returns the value of the ::row-spacing property.
 
6315
 * 
 
6316
 * Return value: the space between rows
 
6317
 *
 
6318
 * Since: 2.6
 
6319
 */
 
6320
gint
 
6321
gtk_icon_view_get_row_spacing (GtkIconView *icon_view)
 
6322
{
 
6323
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6324
 
 
6325
  return icon_view->priv->row_spacing;
 
6326
}
 
6327
 
 
6328
/**
 
6329
 * gtk_icon_view_set_column_spacing:
 
6330
 * @icon_view: a #GtkIconView
 
6331
 * @column_spacing: the column spacing
 
6332
 * 
 
6333
 * Sets the ::column-spacing property which specifies the space 
 
6334
 * which is inserted between the columns of the icon view.
 
6335
 *
 
6336
 * Since: 2.6
 
6337
 */
 
6338
void 
 
6339
gtk_icon_view_set_column_spacing (GtkIconView *icon_view,
 
6340
                                  gint         column_spacing)
 
6341
{
 
6342
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6343
  
 
6344
  if (icon_view->priv->column_spacing != column_spacing)
 
6345
    {
 
6346
      icon_view->priv->column_spacing = column_spacing;
 
6347
 
 
6348
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6349
      gtk_icon_view_invalidate_sizes (icon_view);
 
6350
      gtk_icon_view_queue_layout (icon_view);
 
6351
      
 
6352
      g_object_notify (G_OBJECT (icon_view), "column-spacing");
 
6353
    }  
 
6354
}
 
6355
 
 
6356
/**
 
6357
 * gtk_icon_view_get_column_spacing:
 
6358
 * @icon_view: a #GtkIconView
 
6359
 * 
 
6360
 * Returns the value of the ::column-spacing property.
 
6361
 * 
 
6362
 * Return value: the space between columns
 
6363
 *
 
6364
 * Since: 2.6
 
6365
 */
 
6366
gint
 
6367
gtk_icon_view_get_column_spacing (GtkIconView *icon_view)
 
6368
{
 
6369
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6370
 
 
6371
  return icon_view->priv->column_spacing;
 
6372
}
 
6373
 
 
6374
/**
 
6375
 * gtk_icon_view_set_margin:
 
6376
 * @icon_view: a #GtkIconView
 
6377
 * @margin: the margin
 
6378
 * 
 
6379
 * Sets the ::margin property which specifies the space 
 
6380
 * which is inserted at the top, bottom, left and right 
 
6381
 * of the icon view.
 
6382
 *
 
6383
 * Since: 2.6
 
6384
 */
 
6385
void 
 
6386
gtk_icon_view_set_margin (GtkIconView *icon_view,
 
6387
                          gint         margin)
 
6388
{
 
6389
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6390
  
 
6391
  if (icon_view->priv->margin != margin)
 
6392
    {
 
6393
      icon_view->priv->margin = margin;
 
6394
 
 
6395
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6396
      gtk_icon_view_invalidate_sizes (icon_view);
 
6397
      gtk_icon_view_queue_layout (icon_view);
 
6398
      
 
6399
      g_object_notify (G_OBJECT (icon_view), "margin");
 
6400
    }  
 
6401
}
 
6402
 
 
6403
/**
 
6404
 * gtk_icon_view_get_margin:
 
6405
 * @icon_view: a #GtkIconView
 
6406
 * 
 
6407
 * Returns the value of the ::margin property.
 
6408
 * 
 
6409
 * Return value: the space at the borders 
 
6410
 *
 
6411
 * Since: 2.6
 
6412
 */
 
6413
gint
 
6414
gtk_icon_view_get_margin (GtkIconView *icon_view)
 
6415
{
 
6416
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6417
 
 
6418
  return icon_view->priv->margin;
 
6419
}
 
6420
 
 
6421
/**
 
6422
 * gtk_icon_view_set_item_padding:
 
6423
 * @icon_view: a #GtkIconView
 
6424
 * @item_padding: the item padding
 
6425
 *
 
6426
 * Sets the #GtkIconView:item-padding property which specifies the padding
 
6427
 * around each of the icon view's items.
 
6428
 *
 
6429
 * Since: 2.18
 
6430
 */
 
6431
void
 
6432
gtk_icon_view_set_item_padding (GtkIconView *icon_view,
 
6433
                                gint         item_padding)
 
6434
{
 
6435
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
6436
  
 
6437
  if (icon_view->priv->item_padding != item_padding)
 
6438
    {
 
6439
      icon_view->priv->item_padding = item_padding;
 
6440
 
 
6441
      gtk_icon_view_stop_editing (icon_view, TRUE);
 
6442
      gtk_icon_view_invalidate_sizes (icon_view);
 
6443
      gtk_icon_view_queue_layout (icon_view);
 
6444
      
 
6445
      g_object_notify (G_OBJECT (icon_view), "item-padding");
 
6446
    }  
 
6447
}
 
6448
 
 
6449
/**
 
6450
 * gtk_icon_view_get_item_padding:
 
6451
 * @icon_view: a #GtkIconView
 
6452
 * 
 
6453
 * Returns the value of the ::item-padding property.
 
6454
 * 
 
6455
 * Return value: the padding around items
 
6456
 *
 
6457
 * Since: 2.18
 
6458
 */
 
6459
gint
 
6460
gtk_icon_view_get_item_padding (GtkIconView *icon_view)
 
6461
{
 
6462
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), -1);
 
6463
 
 
6464
  return icon_view->priv->item_padding;
 
6465
}
 
6466
 
 
6467
/* Get/set whether drag_motion requested the drag data and
 
6468
 * drag_data_received should thus not actually insert the data,
 
6469
 * since the data doesn't result from a drop.
 
6470
 */
 
6471
static void
 
6472
set_status_pending (GdkDragContext *context,
 
6473
                    GdkDragAction   suggested_action)
 
6474
{
 
6475
  g_object_set_data (G_OBJECT (context),
 
6476
                     I_("gtk-icon-view-status-pending"),
 
6477
                     GINT_TO_POINTER (suggested_action));
 
6478
}
 
6479
 
 
6480
static GdkDragAction
 
6481
get_status_pending (GdkDragContext *context)
 
6482
{
 
6483
  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
 
6484
                                             "gtk-icon-view-status-pending"));
 
6485
}
 
6486
 
 
6487
static void
 
6488
unset_reorderable (GtkIconView *icon_view)
 
6489
{
 
6490
  if (icon_view->priv->reorderable)
 
6491
    {
 
6492
      icon_view->priv->reorderable = FALSE;
 
6493
      g_object_notify (G_OBJECT (icon_view), "reorderable");
 
6494
    }
 
6495
}
 
6496
 
 
6497
static void
 
6498
set_source_row (GdkDragContext *context,
 
6499
                GtkTreeModel   *model,
 
6500
                GtkTreePath    *source_row)
 
6501
{
 
6502
  if (source_row)
 
6503
    g_object_set_data_full (G_OBJECT (context),
 
6504
                            I_("gtk-icon-view-source-row"),
 
6505
                            gtk_tree_row_reference_new (model, source_row),
 
6506
                            (GDestroyNotify) gtk_tree_row_reference_free);
 
6507
  else
 
6508
    g_object_set_data_full (G_OBJECT (context),
 
6509
                            I_("gtk-icon-view-source-row"),
 
6510
                            NULL, NULL);
 
6511
}
 
6512
 
 
6513
static GtkTreePath*
 
6514
get_source_row (GdkDragContext *context)
 
6515
{
 
6516
  GtkTreeRowReference *ref;
 
6517
 
 
6518
  ref = g_object_get_data (G_OBJECT (context), "gtk-icon-view-source-row");
 
6519
 
 
6520
  if (ref)
 
6521
    return gtk_tree_row_reference_get_path (ref);
 
6522
  else
 
6523
    return NULL;
 
6524
}
 
6525
 
 
6526
typedef struct
 
6527
{
 
6528
  GtkTreeRowReference *dest_row;
 
6529
  gboolean             empty_view_drop;
 
6530
  gboolean             drop_append_mode;
 
6531
} DestRow;
 
6532
 
 
6533
static void
 
6534
dest_row_free (gpointer data)
 
6535
{
 
6536
  DestRow *dr = (DestRow *)data;
 
6537
 
 
6538
  gtk_tree_row_reference_free (dr->dest_row);
 
6539
  g_free (dr);
 
6540
}
 
6541
 
 
6542
static void
 
6543
set_dest_row (GdkDragContext *context,
 
6544
              GtkTreeModel   *model,
 
6545
              GtkTreePath    *dest_row,
 
6546
              gboolean        empty_view_drop,
 
6547
              gboolean        drop_append_mode)
 
6548
{
 
6549
  DestRow *dr;
 
6550
 
 
6551
  if (!dest_row)
 
6552
    {
 
6553
      g_object_set_data_full (G_OBJECT (context),
 
6554
                              I_("gtk-icon-view-dest-row"),
 
6555
                              NULL, NULL);
 
6556
      return;
 
6557
    }
 
6558
  
 
6559
  dr = g_new0 (DestRow, 1);
 
6560
     
 
6561
  dr->dest_row = gtk_tree_row_reference_new (model, dest_row);
 
6562
  dr->empty_view_drop = empty_view_drop;
 
6563
  dr->drop_append_mode = drop_append_mode;
 
6564
  g_object_set_data_full (G_OBJECT (context),
 
6565
                          I_("gtk-icon-view-dest-row"),
 
6566
                          dr, (GDestroyNotify) dest_row_free);
 
6567
}
 
6568
 
 
6569
static GtkTreePath*
 
6570
get_dest_row (GdkDragContext *context)
 
6571
{
 
6572
  DestRow *dr;
 
6573
 
 
6574
  dr = g_object_get_data (G_OBJECT (context), "gtk-icon-view-dest-row");
 
6575
 
 
6576
  if (dr)
 
6577
    {
 
6578
      GtkTreePath *path = NULL;
 
6579
      
 
6580
      if (dr->dest_row)
 
6581
        path = gtk_tree_row_reference_get_path (dr->dest_row);
 
6582
      else if (dr->empty_view_drop)
 
6583
        path = gtk_tree_path_new_from_indices (0, -1);
 
6584
      else
 
6585
        path = NULL;
 
6586
 
 
6587
      if (path && dr->drop_append_mode)
 
6588
        gtk_tree_path_next (path);
 
6589
 
 
6590
      return path;
 
6591
    }
 
6592
  else
 
6593
    return NULL;
 
6594
}
 
6595
 
 
6596
static gboolean
 
6597
check_model_dnd (GtkTreeModel *model,
 
6598
                 GType         required_iface,
 
6599
                 const gchar  *signal)
 
6600
{
 
6601
  if (model == NULL || !G_TYPE_CHECK_INSTANCE_TYPE ((model), required_iface))
 
6602
    {
 
6603
      g_warning ("You must override the default '%s' handler "
 
6604
                 "on GtkIconView when using models that don't support "
 
6605
                 "the %s interface and enabling drag-and-drop. The simplest way to do this "
 
6606
                 "is to connect to '%s' and call "
 
6607
                 "g_signal_stop_emission_by_name() in your signal handler to prevent "
 
6608
                 "the default handler from running. Look at the source code "
 
6609
                 "for the default handler in gtkiconview.c to get an idea what "
 
6610
                 "your handler should do. (gtkiconview.c is in the GTK+ source "
 
6611
                 "code.) If you're using GTK+ from a language other than C, "
 
6612
                 "there may be a more natural way to override default handlers, e.g. via derivation.",
 
6613
                 signal, g_type_name (required_iface), signal);
 
6614
      return FALSE;
 
6615
    }
 
6616
  else
 
6617
    return TRUE;
 
6618
}
 
6619
 
 
6620
static void
 
6621
remove_scroll_timeout (GtkIconView *icon_view)
 
6622
{
 
6623
  if (icon_view->priv->scroll_timeout_id != 0)
 
6624
    {
 
6625
      g_source_remove (icon_view->priv->scroll_timeout_id);
 
6626
 
 
6627
      icon_view->priv->scroll_timeout_id = 0;
 
6628
    }
 
6629
}
 
6630
 
 
6631
static void
 
6632
gtk_icon_view_autoscroll (GtkIconView *icon_view)
 
6633
{
 
6634
  gint px, py, x, y, width, height;
 
6635
  gint hoffset, voffset;
 
6636
  gfloat value;
 
6637
 
 
6638
  gdk_window_get_pointer (GTK_WIDGET (icon_view)->window, &px, &py, NULL);
 
6639
  gdk_window_get_geometry (GTK_WIDGET (icon_view)->window, &x, &y, &width, &height, NULL);
 
6640
 
 
6641
  /* see if we are near the edge. */
 
6642
  voffset = py - (y + 2 * SCROLL_EDGE_SIZE);
 
6643
  if (voffset > 0)
 
6644
    voffset = MAX (py - (y + height - 2 * SCROLL_EDGE_SIZE), 0);
 
6645
 
 
6646
  hoffset = px - (x + 2 * SCROLL_EDGE_SIZE);
 
6647
  if (hoffset > 0)
 
6648
    hoffset = MAX (px - (x + width - 2 * SCROLL_EDGE_SIZE), 0);
 
6649
 
 
6650
  if (voffset != 0)
 
6651
    {
 
6652
      value = CLAMP (icon_view->priv->vadjustment->value + voffset, 
 
6653
                     icon_view->priv->vadjustment->lower,
 
6654
                     icon_view->priv->vadjustment->upper - icon_view->priv->vadjustment->page_size);
 
6655
      gtk_adjustment_set_value (icon_view->priv->vadjustment, value);
 
6656
    }
 
6657
  if (hoffset != 0)
 
6658
    {
 
6659
      value = CLAMP (icon_view->priv->hadjustment->value + hoffset, 
 
6660
                     icon_view->priv->hadjustment->lower,
 
6661
                     icon_view->priv->hadjustment->upper - icon_view->priv->hadjustment->page_size);
 
6662
      gtk_adjustment_set_value (icon_view->priv->hadjustment, value);
 
6663
    }
 
6664
}
 
6665
 
 
6666
 
 
6667
static gboolean
 
6668
drag_scroll_timeout (gpointer data)
 
6669
{
 
6670
  GtkIconView *icon_view = GTK_ICON_VIEW (data);
 
6671
 
 
6672
  gtk_icon_view_autoscroll (icon_view);
 
6673
 
 
6674
  return TRUE;
 
6675
}
 
6676
 
 
6677
 
 
6678
static gboolean
 
6679
set_destination (GtkIconView    *icon_view,
 
6680
                 GdkDragContext *context,
 
6681
                 gint            x,
 
6682
                 gint            y,
 
6683
                 GdkDragAction  *suggested_action,
 
6684
                 GdkAtom        *target)
 
6685
{
 
6686
  GtkWidget *widget;
 
6687
  GtkTreePath *path = NULL;
 
6688
  GtkIconViewDropPosition pos;
 
6689
  GtkIconViewDropPosition old_pos;
 
6690
  GtkTreePath *old_dest_path = NULL;
 
6691
  gboolean can_drop = FALSE;
 
6692
 
 
6693
  widget = GTK_WIDGET (icon_view);
 
6694
 
 
6695
  *suggested_action = 0;
 
6696
  *target = GDK_NONE;
 
6697
 
 
6698
  if (!icon_view->priv->dest_set)
 
6699
    {
 
6700
      /* someone unset us as a drag dest, note that if
 
6701
       * we return FALSE drag_leave isn't called
 
6702
       */
 
6703
 
 
6704
      gtk_icon_view_set_drag_dest_item (icon_view,
 
6705
                                        NULL,
 
6706
                                        GTK_ICON_VIEW_DROP_LEFT);
 
6707
 
 
6708
      remove_scroll_timeout (GTK_ICON_VIEW (widget));
 
6709
 
 
6710
      return FALSE; /* no longer a drop site */
 
6711
    }
 
6712
 
 
6713
  *target = gtk_drag_dest_find_target (widget, context,
 
6714
                                       gtk_drag_dest_get_target_list (widget));
 
6715
  if (*target == GDK_NONE)
 
6716
    return FALSE;
 
6717
 
 
6718
  if (!gtk_icon_view_get_dest_item_at_pos (icon_view, x, y, &path, &pos)) 
 
6719
    {
 
6720
      gint n_children;
 
6721
      GtkTreeModel *model;
 
6722
      
 
6723
      /* the row got dropped on empty space, let's setup a special case
 
6724
       */
 
6725
 
 
6726
      if (path)
 
6727
        gtk_tree_path_free (path);
 
6728
 
 
6729
      model = gtk_icon_view_get_model (icon_view);
 
6730
 
 
6731
      n_children = gtk_tree_model_iter_n_children (model, NULL);
 
6732
      if (n_children)
 
6733
        {
 
6734
          pos = GTK_ICON_VIEW_DROP_BELOW;
 
6735
          path = gtk_tree_path_new_from_indices (n_children - 1, -1);
 
6736
        }
 
6737
      else
 
6738
        {
 
6739
          pos = GTK_ICON_VIEW_DROP_ABOVE;
 
6740
          path = gtk_tree_path_new_from_indices (0, -1);
 
6741
        }
 
6742
 
 
6743
      can_drop = TRUE;
 
6744
 
 
6745
      goto out;
 
6746
    }
 
6747
 
 
6748
  g_assert (path);
 
6749
 
 
6750
  gtk_icon_view_get_drag_dest_item (icon_view,
 
6751
                                    &old_dest_path,
 
6752
                                    &old_pos);
 
6753
  
 
6754
  if (old_dest_path)
 
6755
    gtk_tree_path_free (old_dest_path);
 
6756
  
 
6757
  if (TRUE /* FIXME if the location droppable predicate */)
 
6758
    {
 
6759
      can_drop = TRUE;
 
6760
    }
 
6761
 
 
6762
out:
 
6763
  if (can_drop)
 
6764
    {
 
6765
      GtkWidget *source_widget;
 
6766
 
 
6767
      *suggested_action = gdk_drag_context_get_suggested_action (context);
 
6768
      source_widget = gtk_drag_get_source_widget (context);
 
6769
 
 
6770
      if (source_widget == widget)
 
6771
        {
 
6772
          /* Default to MOVE, unless the user has
 
6773
           * pressed ctrl or shift to affect available actions
 
6774
           */
 
6775
          if ((gdk_drag_context_get_actions (context) & GDK_ACTION_MOVE) != 0)
 
6776
            *suggested_action = GDK_ACTION_MOVE;
 
6777
        }
 
6778
 
 
6779
      gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (widget),
 
6780
                                        path, pos);
 
6781
    }
 
6782
  else
 
6783
    {
 
6784
      /* can't drop here */
 
6785
      gtk_icon_view_set_drag_dest_item (GTK_ICON_VIEW (widget),
 
6786
                                        NULL,
 
6787
                                        GTK_ICON_VIEW_DROP_LEFT);
 
6788
    }
 
6789
  
 
6790
  if (path)
 
6791
    gtk_tree_path_free (path);
 
6792
  
 
6793
  return TRUE;
 
6794
}
 
6795
 
 
6796
static GtkTreePath*
 
6797
get_logical_destination (GtkIconView *icon_view,
 
6798
                         gboolean    *drop_append_mode)
 
6799
{
 
6800
  /* adjust path to point to the row the drop goes in front of */
 
6801
  GtkTreePath *path = NULL;
 
6802
  GtkIconViewDropPosition pos;
 
6803
  
 
6804
  *drop_append_mode = FALSE;
 
6805
 
 
6806
  gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
 
6807
 
 
6808
  if (path == NULL)
 
6809
    return NULL;
 
6810
 
 
6811
  if (pos == GTK_ICON_VIEW_DROP_RIGHT || 
 
6812
      pos == GTK_ICON_VIEW_DROP_BELOW)
 
6813
    {
 
6814
      GtkTreeIter iter;
 
6815
      GtkTreeModel *model = icon_view->priv->model;
 
6816
 
 
6817
      if (!gtk_tree_model_get_iter (model, &iter, path) ||
 
6818
          !gtk_tree_model_iter_next (model, &iter))
 
6819
        *drop_append_mode = TRUE;
 
6820
      else
 
6821
        {
 
6822
          *drop_append_mode = FALSE;
 
6823
          gtk_tree_path_next (path);
 
6824
        }      
 
6825
    }
 
6826
 
 
6827
  return path;
 
6828
}
 
6829
 
 
6830
static gboolean
 
6831
gtk_icon_view_maybe_begin_drag (GtkIconView    *icon_view,
 
6832
                                GdkEventMotion *event)
 
6833
{
 
6834
  GtkWidget *widget = GTK_WIDGET (icon_view);
 
6835
  GdkDragContext *context;
 
6836
  GtkTreePath *path = NULL;
 
6837
  gint button;
 
6838
  GtkTreeModel *model;
 
6839
  gboolean retval = FALSE;
 
6840
 
 
6841
  if (!icon_view->priv->source_set)
 
6842
    goto out;
 
6843
 
 
6844
  if (icon_view->priv->pressed_button < 0)
 
6845
    goto out;
 
6846
 
 
6847
  if (!gtk_drag_check_threshold (GTK_WIDGET (icon_view),
 
6848
                                 icon_view->priv->press_start_x,
 
6849
                                 icon_view->priv->press_start_y,
 
6850
                                 event->x, event->y))
 
6851
    goto out;
 
6852
 
 
6853
  model = gtk_icon_view_get_model (icon_view);
 
6854
 
 
6855
  if (model == NULL)
 
6856
    goto out;
 
6857
 
 
6858
  button = icon_view->priv->pressed_button;
 
6859
  icon_view->priv->pressed_button = -1;
 
6860
 
 
6861
  path = gtk_icon_view_get_path_at_pos (icon_view,
 
6862
                                        icon_view->priv->press_start_x,
 
6863
                                        icon_view->priv->press_start_y);
 
6864
 
 
6865
  if (path == NULL)
 
6866
    goto out;
 
6867
 
 
6868
  if (!GTK_IS_TREE_DRAG_SOURCE (model) ||
 
6869
      !gtk_tree_drag_source_row_draggable (GTK_TREE_DRAG_SOURCE (model),
 
6870
                                           path))
 
6871
    goto out;
 
6872
 
 
6873
  /* FIXME Check whether we're a start button, if not return FALSE and
 
6874
   * free path
 
6875
   */
 
6876
 
 
6877
  /* Now we can begin the drag */
 
6878
  
 
6879
  retval = TRUE;
 
6880
 
 
6881
  context = gtk_drag_begin (widget,
 
6882
                            gtk_drag_source_get_target_list (widget),
 
6883
                            icon_view->priv->source_actions,
 
6884
                            button,
 
6885
                            (GdkEvent*)event);
 
6886
 
 
6887
  set_source_row (context, model, path);
 
6888
  
 
6889
 out:
 
6890
  if (path)
 
6891
    gtk_tree_path_free (path);
 
6892
 
 
6893
  return retval;
 
6894
}
 
6895
 
 
6896
/* Source side drag signals */
 
6897
static void 
 
6898
gtk_icon_view_drag_begin (GtkWidget      *widget,
 
6899
                          GdkDragContext *context)
 
6900
{
 
6901
  GtkIconView *icon_view;
 
6902
  GtkIconViewItem *item;
 
6903
  GdkPixmap *icon;
 
6904
  gint x, y;
 
6905
  GtkTreePath *path;
 
6906
 
 
6907
  icon_view = GTK_ICON_VIEW (widget);
 
6908
 
 
6909
  /* if the user uses a custom DnD impl, we don't set the icon here */
 
6910
  if (!icon_view->priv->dest_set && !icon_view->priv->source_set)
 
6911
    return;
 
6912
 
 
6913
  item = gtk_icon_view_get_item_at_coords (icon_view,
 
6914
                                           icon_view->priv->press_start_x,
 
6915
                                           icon_view->priv->press_start_y,
 
6916
                                           TRUE,
 
6917
                                           NULL);
 
6918
 
 
6919
  g_return_if_fail (item != NULL);
 
6920
 
 
6921
  x = icon_view->priv->press_start_x - item->x + 1;
 
6922
  y = icon_view->priv->press_start_y - item->y + 1;
 
6923
  
 
6924
  path = gtk_tree_path_new_from_indices (item->index, -1);
 
6925
  icon = gtk_icon_view_create_drag_icon (icon_view, path);
 
6926
  gtk_tree_path_free (path);
 
6927
 
 
6928
  gtk_drag_set_icon_pixmap (context, 
 
6929
                            gdk_drawable_get_colormap (icon),
 
6930
                            icon, 
 
6931
                            NULL, 
 
6932
                            x, y);
 
6933
 
 
6934
  g_object_unref (icon);
 
6935
}
 
6936
 
 
6937
static void 
 
6938
gtk_icon_view_drag_end (GtkWidget      *widget,
 
6939
                        GdkDragContext *context)
 
6940
{
 
6941
  /* do nothing */
 
6942
}
 
6943
 
 
6944
static void 
 
6945
gtk_icon_view_drag_data_get (GtkWidget        *widget,
 
6946
                             GdkDragContext   *context,
 
6947
                             GtkSelectionData *selection_data,
 
6948
                             guint             info,
 
6949
                             guint             time)
 
6950
{
 
6951
  GtkIconView *icon_view;
 
6952
  GtkTreeModel *model;
 
6953
  GtkTreePath *source_row;
 
6954
 
 
6955
  icon_view = GTK_ICON_VIEW (widget);
 
6956
  model = gtk_icon_view_get_model (icon_view);
 
6957
 
 
6958
  if (model == NULL)
 
6959
    return;
 
6960
 
 
6961
  if (!icon_view->priv->source_set)
 
6962
    return;
 
6963
 
 
6964
  source_row = get_source_row (context);
 
6965
 
 
6966
  if (source_row == NULL)
 
6967
    return;
 
6968
 
 
6969
  /* We can implement the GTK_TREE_MODEL_ROW target generically for
 
6970
   * any model; for DragSource models there are some other targets
 
6971
   * we also support.
 
6972
   */
 
6973
 
 
6974
  if (GTK_IS_TREE_DRAG_SOURCE (model) &&
 
6975
      gtk_tree_drag_source_drag_data_get (GTK_TREE_DRAG_SOURCE (model),
 
6976
                                          source_row,
 
6977
                                          selection_data))
 
6978
    goto done;
 
6979
 
 
6980
  /* If drag_data_get does nothing, try providing row data. */
 
6981
  if (selection_data->target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
 
6982
    gtk_tree_set_row_drag_data (selection_data,
 
6983
                                model,
 
6984
                                source_row);
 
6985
 
 
6986
 done:
 
6987
  gtk_tree_path_free (source_row);
 
6988
}
 
6989
 
 
6990
static void 
 
6991
gtk_icon_view_drag_data_delete (GtkWidget      *widget,
 
6992
                                GdkDragContext *context)
 
6993
{
 
6994
  GtkTreeModel *model;
 
6995
  GtkIconView *icon_view;
 
6996
  GtkTreePath *source_row;
 
6997
 
 
6998
  icon_view = GTK_ICON_VIEW (widget);
 
6999
  model = gtk_icon_view_get_model (icon_view);
 
7000
 
 
7001
  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_SOURCE, "drag-data-delete"))
 
7002
    return;
 
7003
 
 
7004
  if (!icon_view->priv->source_set)
 
7005
    return;
 
7006
 
 
7007
  source_row = get_source_row (context);
 
7008
 
 
7009
  if (source_row == NULL)
 
7010
    return;
 
7011
 
 
7012
  gtk_tree_drag_source_drag_data_delete (GTK_TREE_DRAG_SOURCE (model),
 
7013
                                         source_row);
 
7014
 
 
7015
  gtk_tree_path_free (source_row);
 
7016
 
 
7017
  set_source_row (context, NULL, NULL);
 
7018
}
 
7019
 
 
7020
/* Target side drag signals */
 
7021
static void
 
7022
gtk_icon_view_drag_leave (GtkWidget      *widget,
 
7023
                          GdkDragContext *context,
 
7024
                          guint           time)
 
7025
{
 
7026
  GtkIconView *icon_view;
 
7027
 
 
7028
  icon_view = GTK_ICON_VIEW (widget);
 
7029
 
 
7030
  /* unset any highlight row */
 
7031
  gtk_icon_view_set_drag_dest_item (icon_view,
 
7032
                                    NULL,
 
7033
                                    GTK_ICON_VIEW_DROP_LEFT);
 
7034
 
 
7035
  remove_scroll_timeout (icon_view);
 
7036
}
 
7037
 
 
7038
static gboolean 
 
7039
gtk_icon_view_drag_motion (GtkWidget      *widget,
 
7040
                           GdkDragContext *context,
 
7041
                           gint            x,
 
7042
                           gint            y,
 
7043
                           guint           time)
 
7044
{
 
7045
  GtkTreePath *path = NULL;
 
7046
  GtkIconViewDropPosition pos;
 
7047
  GtkIconView *icon_view;
 
7048
  GdkDragAction suggested_action = 0;
 
7049
  GdkAtom target;
 
7050
  gboolean empty;
 
7051
 
 
7052
  icon_view = GTK_ICON_VIEW (widget);
 
7053
 
 
7054
  if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
 
7055
    return FALSE;
 
7056
 
 
7057
  gtk_icon_view_get_drag_dest_item (icon_view, &path, &pos);
 
7058
 
 
7059
  /* we only know this *after* set_desination_row */
 
7060
  empty = icon_view->priv->empty_view_drop;
 
7061
 
 
7062
  if (path == NULL && !empty)
 
7063
    {
 
7064
      /* Can't drop here. */
 
7065
      gdk_drag_status (context, 0, time);
 
7066
    }
 
7067
  else
 
7068
    {
 
7069
      if (icon_view->priv->scroll_timeout_id == 0)
 
7070
        {
 
7071
          icon_view->priv->scroll_timeout_id =
 
7072
            gdk_threads_add_timeout (50, drag_scroll_timeout, icon_view);
 
7073
        }
 
7074
 
 
7075
      if (target == gdk_atom_intern_static_string ("GTK_TREE_MODEL_ROW"))
 
7076
        {
 
7077
          /* Request data so we can use the source row when
 
7078
           * determining whether to accept the drop
 
7079
           */
 
7080
          set_status_pending (context, suggested_action);
 
7081
          gtk_drag_get_data (widget, context, target, time);
 
7082
        }
 
7083
      else
 
7084
        {
 
7085
          set_status_pending (context, 0);
 
7086
          gdk_drag_status (context, suggested_action, time);
 
7087
        }
 
7088
    }
 
7089
 
 
7090
  if (path)
 
7091
    gtk_tree_path_free (path);
 
7092
 
 
7093
  return TRUE;
 
7094
}
 
7095
 
 
7096
static gboolean 
 
7097
gtk_icon_view_drag_drop (GtkWidget      *widget,
 
7098
                         GdkDragContext *context,
 
7099
                         gint            x,
 
7100
                         gint            y,
 
7101
                         guint           time)
 
7102
{
 
7103
  GtkIconView *icon_view;
 
7104
  GtkTreePath *path;
 
7105
  GdkDragAction suggested_action = 0;
 
7106
  GdkAtom target = GDK_NONE;
 
7107
  GtkTreeModel *model;
 
7108
  gboolean drop_append_mode;
 
7109
 
 
7110
  icon_view = GTK_ICON_VIEW (widget);
 
7111
  model = gtk_icon_view_get_model (icon_view);
 
7112
 
 
7113
  remove_scroll_timeout (GTK_ICON_VIEW (widget));
 
7114
 
 
7115
  if (!icon_view->priv->dest_set)
 
7116
    return FALSE;
 
7117
 
 
7118
  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-drop"))
 
7119
    return FALSE;
 
7120
 
 
7121
  if (!set_destination (icon_view, context, x, y, &suggested_action, &target))
 
7122
    return FALSE;
 
7123
  
 
7124
  path = get_logical_destination (icon_view, &drop_append_mode);
 
7125
 
 
7126
  if (target != GDK_NONE && path != NULL)
 
7127
    {
 
7128
      /* in case a motion had requested drag data, change things so we
 
7129
       * treat drag data receives as a drop.
 
7130
       */
 
7131
      set_status_pending (context, 0);
 
7132
      set_dest_row (context, model, path, 
 
7133
                    icon_view->priv->empty_view_drop, drop_append_mode);
 
7134
    }
 
7135
 
 
7136
  if (path)
 
7137
    gtk_tree_path_free (path);
 
7138
 
 
7139
  /* Unset this thing */
 
7140
  gtk_icon_view_set_drag_dest_item (icon_view, NULL, GTK_ICON_VIEW_DROP_LEFT);
 
7141
 
 
7142
  if (target != GDK_NONE)
 
7143
    {
 
7144
      gtk_drag_get_data (widget, context, target, time);
 
7145
      return TRUE;
 
7146
    }
 
7147
  else
 
7148
    return FALSE;
 
7149
}
 
7150
 
 
7151
static void
 
7152
gtk_icon_view_drag_data_received (GtkWidget        *widget,
 
7153
                                  GdkDragContext   *context,
 
7154
                                  gint              x,
 
7155
                                  gint              y,
 
7156
                                  GtkSelectionData *selection_data,
 
7157
                                  guint             info,
 
7158
                                  guint             time)
 
7159
{
 
7160
  GtkTreePath *path;
 
7161
  gboolean accepted = FALSE;
 
7162
  GtkTreeModel *model;
 
7163
  GtkIconView *icon_view;
 
7164
  GtkTreePath *dest_row;
 
7165
  GdkDragAction suggested_action;
 
7166
  gboolean drop_append_mode;
 
7167
  
 
7168
  icon_view = GTK_ICON_VIEW (widget);  
 
7169
  model = gtk_icon_view_get_model (icon_view);
 
7170
 
 
7171
  if (!check_model_dnd (model, GTK_TYPE_TREE_DRAG_DEST, "drag-data-received"))
 
7172
    return;
 
7173
 
 
7174
  if (!icon_view->priv->dest_set)
 
7175
    return;
 
7176
 
 
7177
  suggested_action = get_status_pending (context);
 
7178
 
 
7179
  if (suggested_action)
 
7180
    {
 
7181
      /* We are getting this data due to a request in drag_motion,
 
7182
       * rather than due to a request in drag_drop, so we are just
 
7183
       * supposed to call drag_status, not actually paste in the
 
7184
       * data.
 
7185
       */
 
7186
      path = get_logical_destination (icon_view, &drop_append_mode);
 
7187
 
 
7188
      if (path == NULL)
 
7189
        suggested_action = 0;
 
7190
 
 
7191
      if (suggested_action)
 
7192
        {
 
7193
          if (!gtk_tree_drag_dest_row_drop_possible (GTK_TREE_DRAG_DEST (model),
 
7194
                                                     path,
 
7195
                                                     selection_data))
 
7196
            suggested_action = 0;
 
7197
        }
 
7198
 
 
7199
      gdk_drag_status (context, suggested_action, time);
 
7200
 
 
7201
      if (path)
 
7202
        gtk_tree_path_free (path);
 
7203
 
 
7204
      /* If you can't drop, remove user drop indicator until the next motion */
 
7205
      if (suggested_action == 0)
 
7206
        gtk_icon_view_set_drag_dest_item (icon_view,
 
7207
                                          NULL,
 
7208
                                          GTK_ICON_VIEW_DROP_LEFT);
 
7209
      return;
 
7210
    }
 
7211
  
 
7212
 
 
7213
  dest_row = get_dest_row (context);
 
7214
 
 
7215
  if (dest_row == NULL)
 
7216
    return;
 
7217
 
 
7218
  if (selection_data->length >= 0)
 
7219
    {
 
7220
      if (gtk_tree_drag_dest_drag_data_received (GTK_TREE_DRAG_DEST (model),
 
7221
                                                 dest_row,
 
7222
                                                 selection_data))
 
7223
        accepted = TRUE;
 
7224
    }
 
7225
 
 
7226
  gtk_drag_finish (context,
 
7227
                   accepted,
 
7228
                   (gdk_drag_context_get_selected_action (context) == GDK_ACTION_MOVE),
 
7229
                   time);
 
7230
 
 
7231
  gtk_tree_path_free (dest_row);
 
7232
 
 
7233
  /* drop dest_row */
 
7234
  set_dest_row (context, NULL, NULL, FALSE, FALSE);
 
7235
}
 
7236
 
 
7237
/* Drag-and-Drop support */
 
7238
/**
 
7239
 * gtk_icon_view_enable_model_drag_source:
 
7240
 * @icon_view: a #GtkIconTreeView
 
7241
 * @start_button_mask: Mask of allowed buttons to start drag
 
7242
 * @targets: the table of targets that the drag will support
 
7243
 * @n_targets: the number of items in @targets
 
7244
 * @actions: the bitmask of possible actions for a drag from this
 
7245
 *    widget
 
7246
 *
 
7247
 * Turns @icon_view into a drag source for automatic DND. Calling this
 
7248
 * method sets #GtkIconView:reorderable to %FALSE.
 
7249
 *
 
7250
 * Since: 2.8
 
7251
 **/
 
7252
void
 
7253
gtk_icon_view_enable_model_drag_source (GtkIconView              *icon_view,
 
7254
                                        GdkModifierType           start_button_mask,
 
7255
                                        const GtkTargetEntry     *targets,
 
7256
                                        gint                      n_targets,
 
7257
                                        GdkDragAction             actions)
 
7258
{
 
7259
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7260
 
 
7261
  gtk_drag_source_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions);
 
7262
 
 
7263
  icon_view->priv->start_button_mask = start_button_mask;
 
7264
  icon_view->priv->source_actions = actions;
 
7265
 
 
7266
  icon_view->priv->source_set = TRUE;
 
7267
 
 
7268
  unset_reorderable (icon_view);
 
7269
}
 
7270
 
 
7271
/**
 
7272
 * gtk_icon_view_enable_model_drag_dest:
 
7273
 * @icon_view: a #GtkIconView
 
7274
 * @targets: the table of targets that the drag will support
 
7275
 * @n_targets: the number of items in @targets
 
7276
 * @actions: the bitmask of possible actions for a drag to this
 
7277
 *    widget
 
7278
 *
 
7279
 * Turns @icon_view into a drop destination for automatic DND. Calling this
 
7280
 * method sets #GtkIconView:reorderable to %FALSE.
 
7281
 *
 
7282
 * Since: 2.8
 
7283
 **/
 
7284
void 
 
7285
gtk_icon_view_enable_model_drag_dest (GtkIconView          *icon_view,
 
7286
                                      const GtkTargetEntry *targets,
 
7287
                                      gint                  n_targets,
 
7288
                                      GdkDragAction         actions)
 
7289
{
 
7290
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7291
 
 
7292
  gtk_drag_dest_set (GTK_WIDGET (icon_view), 0, targets, n_targets, actions);
 
7293
 
 
7294
  icon_view->priv->dest_actions = actions;
 
7295
 
 
7296
  icon_view->priv->dest_set = TRUE;
 
7297
 
 
7298
  unset_reorderable (icon_view);  
 
7299
}
 
7300
 
 
7301
/**
 
7302
 * gtk_icon_view_unset_model_drag_source:
 
7303
 * @icon_view: a #GtkIconView
 
7304
 * 
 
7305
 * Undoes the effect of gtk_icon_view_enable_model_drag_source(). Calling this
 
7306
 * method sets #GtkIconView:reorderable to %FALSE.
 
7307
 *
 
7308
 * Since: 2.8
 
7309
 **/
 
7310
void
 
7311
gtk_icon_view_unset_model_drag_source (GtkIconView *icon_view)
 
7312
{
 
7313
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7314
 
 
7315
  if (icon_view->priv->source_set)
 
7316
    {
 
7317
      gtk_drag_source_unset (GTK_WIDGET (icon_view));
 
7318
      icon_view->priv->source_set = FALSE;
 
7319
    }
 
7320
 
 
7321
  unset_reorderable (icon_view);
 
7322
}
 
7323
 
 
7324
/**
 
7325
 * gtk_icon_view_unset_model_drag_dest:
 
7326
 * @icon_view: a #GtkIconView
 
7327
 * 
 
7328
 * Undoes the effect of gtk_icon_view_enable_model_drag_dest(). Calling this
 
7329
 * method sets #GtkIconView:reorderable to %FALSE.
 
7330
 *
 
7331
 * Since: 2.8
 
7332
 **/
 
7333
void
 
7334
gtk_icon_view_unset_model_drag_dest (GtkIconView *icon_view)
 
7335
{
 
7336
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7337
 
 
7338
  if (icon_view->priv->dest_set)
 
7339
    {
 
7340
      gtk_drag_dest_unset (GTK_WIDGET (icon_view));
 
7341
      icon_view->priv->dest_set = FALSE;
 
7342
    }
 
7343
 
 
7344
  unset_reorderable (icon_view);
 
7345
}
 
7346
 
 
7347
/* These are useful to implement your own custom stuff. */
 
7348
/**
 
7349
 * gtk_icon_view_set_drag_dest_item:
 
7350
 * @icon_view: a #GtkIconView
 
7351
 * @path: (allow-none): The path of the item to highlight, or %NULL.
 
7352
 * @pos: Specifies where to drop, relative to the item
 
7353
 *
 
7354
 * Sets the item that is highlighted for feedback.
 
7355
 *
 
7356
 * Since: 2.8
 
7357
 */
 
7358
void
 
7359
gtk_icon_view_set_drag_dest_item (GtkIconView              *icon_view,
 
7360
                                  GtkTreePath              *path,
 
7361
                                  GtkIconViewDropPosition   pos)
 
7362
{
 
7363
  /* Note; this function is exported to allow a custom DND
 
7364
   * implementation, so it can't touch TreeViewDragInfo
 
7365
   */
 
7366
 
 
7367
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7368
 
 
7369
  if (icon_view->priv->dest_item)
 
7370
    {
 
7371
      GtkTreePath *current_path;
 
7372
      current_path = gtk_tree_row_reference_get_path (icon_view->priv->dest_item);
 
7373
      gtk_tree_row_reference_free (icon_view->priv->dest_item);
 
7374
      icon_view->priv->dest_item = NULL;      
 
7375
 
 
7376
      gtk_icon_view_queue_draw_path (icon_view, current_path);
 
7377
      gtk_tree_path_free (current_path);
 
7378
    }
 
7379
  
 
7380
  /* special case a drop on an empty model */
 
7381
  icon_view->priv->empty_view_drop = FALSE;
 
7382
  if (pos == GTK_ICON_VIEW_DROP_ABOVE && path
 
7383
      && gtk_tree_path_get_depth (path) == 1
 
7384
      && gtk_tree_path_get_indices (path)[0] == 0)
 
7385
    {
 
7386
      gint n_children;
 
7387
 
 
7388
      n_children = gtk_tree_model_iter_n_children (icon_view->priv->model,
 
7389
                                                   NULL);
 
7390
 
 
7391
      if (n_children == 0)
 
7392
        icon_view->priv->empty_view_drop = TRUE;
 
7393
    }
 
7394
 
 
7395
  icon_view->priv->dest_pos = pos;
 
7396
 
 
7397
  if (path)
 
7398
    {
 
7399
      icon_view->priv->dest_item =
 
7400
        gtk_tree_row_reference_new_proxy (G_OBJECT (icon_view), 
 
7401
                                          icon_view->priv->model, path);
 
7402
      
 
7403
      gtk_icon_view_queue_draw_path (icon_view, path);
 
7404
    }
 
7405
}
 
7406
 
 
7407
/**
 
7408
 * gtk_icon_view_get_drag_dest_item:
 
7409
 * @icon_view: a #GtkIconView
 
7410
 * @path: (allow-none): Return location for the path of the highlighted item, or %NULL.
 
7411
 * @pos: (allow-none): Return location for the drop position, or %NULL
 
7412
 * 
 
7413
 * Gets information about the item that is highlighted for feedback.
 
7414
 *
 
7415
 * Since: 2.8
 
7416
 **/
 
7417
void
 
7418
gtk_icon_view_get_drag_dest_item (GtkIconView              *icon_view,
 
7419
                                  GtkTreePath             **path,
 
7420
                                  GtkIconViewDropPosition  *pos)
 
7421
{
 
7422
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7423
 
 
7424
  if (path)
 
7425
    {
 
7426
      if (icon_view->priv->dest_item)
 
7427
        *path = gtk_tree_row_reference_get_path (icon_view->priv->dest_item);
 
7428
      else
 
7429
        *path = NULL;
 
7430
    }
 
7431
 
 
7432
  if (pos)
 
7433
    *pos = icon_view->priv->dest_pos;
 
7434
}
 
7435
 
 
7436
/**
 
7437
 * gtk_icon_view_get_dest_item_at_pos:
 
7438
 * @icon_view: a #GtkIconView
 
7439
 * @drag_x: the position to determine the destination item for
 
7440
 * @drag_y: the position to determine the destination item for
 
7441
 * @path: (allow-none): Return location for the path of the item, or %NULL.
 
7442
 * @pos: (allow-none): Return location for the drop position, or %NULL
 
7443
 * 
 
7444
 * Determines the destination item for a given position.
 
7445
 * 
 
7446
 * Return value: whether there is an item at the given position.
 
7447
 *
 
7448
 * Since: 2.8
 
7449
 **/
 
7450
gboolean
 
7451
gtk_icon_view_get_dest_item_at_pos (GtkIconView              *icon_view,
 
7452
                                    gint                      drag_x,
 
7453
                                    gint                      drag_y,
 
7454
                                    GtkTreePath             **path,
 
7455
                                    GtkIconViewDropPosition  *pos)
 
7456
{
 
7457
  GtkIconViewItem *item;
 
7458
 
 
7459
  /* Note; this function is exported to allow a custom DND
 
7460
   * implementation, so it can't touch TreeViewDragInfo
 
7461
   */
 
7462
 
 
7463
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
7464
  g_return_val_if_fail (drag_x >= 0, FALSE);
 
7465
  g_return_val_if_fail (drag_y >= 0, FALSE);
 
7466
  g_return_val_if_fail (icon_view->priv->bin_window != NULL, FALSE);
 
7467
 
 
7468
 
 
7469
  if (path)
 
7470
    *path = NULL;
 
7471
 
 
7472
  item = gtk_icon_view_get_item_at_coords (icon_view, 
 
7473
                                           drag_x + icon_view->priv->hadjustment->value, 
 
7474
                                           drag_y + icon_view->priv->vadjustment->value,
 
7475
                                           FALSE, NULL);
 
7476
 
 
7477
  if (item == NULL)
 
7478
    return FALSE;
 
7479
 
 
7480
  if (path)
 
7481
    *path = gtk_tree_path_new_from_indices (item->index, -1);
 
7482
 
 
7483
  if (pos)
 
7484
    {
 
7485
      if (drag_x < item->x + item->width / 4)
 
7486
        *pos = GTK_ICON_VIEW_DROP_LEFT;
 
7487
      else if (drag_x > item->x + item->width * 3 / 4)
 
7488
        *pos = GTK_ICON_VIEW_DROP_RIGHT;
 
7489
      else if (drag_y < item->y + item->height / 4)
 
7490
        *pos = GTK_ICON_VIEW_DROP_ABOVE;
 
7491
      else if (drag_y > item->y + item->height * 3 / 4)
 
7492
        *pos = GTK_ICON_VIEW_DROP_BELOW;
 
7493
      else
 
7494
        *pos = GTK_ICON_VIEW_DROP_INTO;
 
7495
    }
 
7496
 
 
7497
  return TRUE;
 
7498
}
 
7499
 
 
7500
/**
 
7501
 * gtk_icon_view_create_drag_icon:
 
7502
 * @icon_view: a #GtkIconView
 
7503
 * @path: a #GtkTreePath in @icon_view
 
7504
 *
 
7505
 * Creates a #GdkPixmap representation of the item at @path.
 
7506
 * This image is used for a drag icon.
 
7507
 *
 
7508
 * Return value: (transfer full): a newly-allocated pixmap of the drag icon.
 
7509
 * 
 
7510
 * Since: 2.8
 
7511
 **/
 
7512
GdkPixmap *
 
7513
gtk_icon_view_create_drag_icon (GtkIconView *icon_view,
 
7514
                                GtkTreePath *path)
 
7515
{
 
7516
  GtkWidget *widget;
 
7517
  cairo_t *cr;
 
7518
  GdkPixmap *drawable;
 
7519
  GList *l;
 
7520
  gint index;
 
7521
  GdkRectangle area;
 
7522
 
 
7523
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), NULL);
 
7524
  g_return_val_if_fail (path != NULL, NULL);
 
7525
 
 
7526
  widget = GTK_WIDGET (icon_view);
 
7527
 
 
7528
  if (!gtk_widget_get_realized (widget))
 
7529
    return NULL;
 
7530
 
 
7531
  index = gtk_tree_path_get_indices (path)[0];
 
7532
 
 
7533
  for (l = icon_view->priv->items; l; l = l->next) 
 
7534
    {
 
7535
      GtkIconViewItem *item = l->data;
 
7536
      
 
7537
      if (index == item->index)
 
7538
        {
 
7539
          drawable = gdk_pixmap_new (icon_view->priv->bin_window,
 
7540
                                     item->width + 2,
 
7541
                                     item->height + 2,
 
7542
                                     -1);
 
7543
 
 
7544
          cr = gdk_cairo_create (drawable);
 
7545
          cairo_set_line_width (cr, 1.);
 
7546
 
 
7547
          gdk_cairo_set_source_color
 
7548
            (cr, &widget->style->base[gtk_widget_get_state (widget)]);
 
7549
          cairo_rectangle (cr, 0, 0, item->width + 2, item->height + 2);
 
7550
          cairo_fill (cr);
 
7551
 
 
7552
          area.x = 0;
 
7553
          area.y = 0;
 
7554
          area.width = item->width;
 
7555
          area.height = item->height;
 
7556
 
 
7557
          gtk_icon_view_paint_item (icon_view, cr, item, &area, 
 
7558
                                    drawable, 1, 1, FALSE); 
 
7559
 
 
7560
          cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
 
7561
          cairo_rectangle (cr, 0.5, 0.5, item->width + 1, item->height + 1);
 
7562
          cairo_stroke (cr);
 
7563
 
 
7564
          cairo_destroy (cr);
 
7565
 
 
7566
          return drawable;
 
7567
        }
 
7568
    }
 
7569
  
 
7570
  return NULL;
 
7571
}
 
7572
 
 
7573
/**
 
7574
 * gtk_icon_view_get_reorderable:
 
7575
 * @icon_view: a #GtkIconView
 
7576
 *
 
7577
 * Retrieves whether the user can reorder the list via drag-and-drop. 
 
7578
 * See gtk_icon_view_set_reorderable().
 
7579
 *
 
7580
 * Return value: %TRUE if the list can be reordered.
 
7581
 *
 
7582
 * Since: 2.8
 
7583
 **/
 
7584
gboolean
 
7585
gtk_icon_view_get_reorderable (GtkIconView *icon_view)
 
7586
{
 
7587
  g_return_val_if_fail (GTK_IS_ICON_VIEW (icon_view), FALSE);
 
7588
 
 
7589
  return icon_view->priv->reorderable;
 
7590
}
 
7591
 
 
7592
static const GtkTargetEntry item_targets[] = {
 
7593
  { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
 
7594
};
 
7595
 
 
7596
 
 
7597
/**
 
7598
 * gtk_icon_view_set_reorderable:
 
7599
 * @icon_view: A #GtkIconView.
 
7600
 * @reorderable: %TRUE, if the list of items can be reordered.
 
7601
 *
 
7602
 * This function is a convenience function to allow you to reorder models that
 
7603
 * support the #GtkTreeDragSourceIface and the #GtkTreeDragDestIface.  Both
 
7604
 * #GtkTreeStore and #GtkListStore support these.  If @reorderable is %TRUE, then
 
7605
 * the user can reorder the model by dragging and dropping rows.  The
 
7606
 * developer can listen to these changes by connecting to the model's
 
7607
 * row_inserted and row_deleted signals. The reordering is implemented by setting up
 
7608
 * the icon view as a drag source and destination. Therefore, drag and
 
7609
 * drop can not be used in a reorderable view for any other purpose.
 
7610
 *
 
7611
 * This function does not give you any degree of control over the order -- any
 
7612
 * reordering is allowed.  If more control is needed, you should probably
 
7613
 * handle drag and drop manually.
 
7614
 *
 
7615
 * Since: 2.8
 
7616
 **/
 
7617
void
 
7618
gtk_icon_view_set_reorderable (GtkIconView *icon_view,
 
7619
                               gboolean     reorderable)
 
7620
{
 
7621
  g_return_if_fail (GTK_IS_ICON_VIEW (icon_view));
 
7622
 
 
7623
  reorderable = reorderable != FALSE;
 
7624
 
 
7625
  if (icon_view->priv->reorderable == reorderable)
 
7626
    return;
 
7627
 
 
7628
  if (reorderable)
 
7629
    {
 
7630
      gtk_icon_view_enable_model_drag_source (icon_view,
 
7631
                                              GDK_BUTTON1_MASK,
 
7632
                                              item_targets,
 
7633
                                              G_N_ELEMENTS (item_targets),
 
7634
                                              GDK_ACTION_MOVE);
 
7635
      gtk_icon_view_enable_model_drag_dest (icon_view,
 
7636
                                            item_targets,
 
7637
                                            G_N_ELEMENTS (item_targets),
 
7638
                                            GDK_ACTION_MOVE);
 
7639
    }
 
7640
  else
 
7641
    {
 
7642
      gtk_icon_view_unset_model_drag_source (icon_view);
 
7643
      gtk_icon_view_unset_model_drag_dest (icon_view);
 
7644
    }
 
7645
 
 
7646
  icon_view->priv->reorderable = reorderable;
 
7647
 
 
7648
  g_object_notify (G_OBJECT (icon_view), "reorderable");
 
7649
}
 
7650
 
 
7651
 
 
7652
/* Accessibility Support */
 
7653
 
 
7654
static gpointer accessible_parent_class;
 
7655
static gpointer accessible_item_parent_class;
 
7656
static GQuark accessible_private_data_quark = 0;
 
7657
 
 
7658
#define GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE      (gtk_icon_view_item_accessible_get_type ())
 
7659
#define GTK_ICON_VIEW_ITEM_ACCESSIBLE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE, GtkIconViewItemAccessible))
 
7660
#define GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ITEM_ACCESSIBLE))
 
7661
 
 
7662
static GType gtk_icon_view_item_accessible_get_type (void);
 
7663
 
 
7664
enum {
 
7665
    ACTION_ACTIVATE,
 
7666
    LAST_ACTION
 
7667
};
 
7668
 
 
7669
typedef struct
 
7670
{
 
7671
  AtkObject parent;
 
7672
 
 
7673
  GtkIconViewItem *item;
 
7674
 
 
7675
  GtkWidget *widget;
 
7676
 
 
7677
  AtkStateSet *state_set;
 
7678
 
 
7679
  gchar *text;
 
7680
 
 
7681
  GtkTextBuffer *text_buffer;
 
7682
 
 
7683
  gchar *action_descriptions[LAST_ACTION];
 
7684
  gchar *image_description;
 
7685
  guint action_idle_handler;
 
7686
} GtkIconViewItemAccessible;
 
7687
 
 
7688
static const gchar *const gtk_icon_view_item_accessible_action_names[] = 
 
7689
{
 
7690
  "activate",
 
7691
  NULL
 
7692
};
 
7693
 
 
7694
static const gchar *const gtk_icon_view_item_accessible_action_descriptions[] =
 
7695
{
 
7696
  "Activate item",
 
7697
  NULL
 
7698
};
 
7699
typedef struct _GtkIconViewItemAccessibleClass
 
7700
{
 
7701
  AtkObjectClass parent_class;
 
7702
 
 
7703
} GtkIconViewItemAccessibleClass;
 
7704
 
 
7705
static gboolean gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item);
 
7706
 
 
7707
static gboolean
 
7708
gtk_icon_view_item_accessible_idle_do_action (gpointer data)
 
7709
{
 
7710
  GtkIconViewItemAccessible *item;
 
7711
  GtkIconView *icon_view;
 
7712
  GtkTreePath *path;
 
7713
 
 
7714
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (data);
 
7715
  item->action_idle_handler = 0;
 
7716
 
 
7717
  if (item->widget != NULL)
 
7718
    {
 
7719
      icon_view = GTK_ICON_VIEW (item->widget);
 
7720
      path = gtk_tree_path_new_from_indices (item->item->index, -1);
 
7721
      gtk_icon_view_item_activated (icon_view, path);
 
7722
      gtk_tree_path_free (path);
 
7723
    }
 
7724
 
 
7725
  return FALSE;
 
7726
}
 
7727
 
 
7728
static gboolean
 
7729
gtk_icon_view_item_accessible_action_do_action (AtkAction *action,
 
7730
                                                gint       i)
 
7731
{
 
7732
  GtkIconViewItemAccessible *item;
 
7733
 
 
7734
  if (i < 0 || i >= LAST_ACTION) 
 
7735
    return FALSE;
 
7736
 
 
7737
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
 
7738
 
 
7739
  if (!GTK_IS_ICON_VIEW (item->widget))
 
7740
    return FALSE;
 
7741
 
 
7742
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
7743
    return FALSE;
 
7744
 
 
7745
  switch (i)
 
7746
    {
 
7747
    case ACTION_ACTIVATE:
 
7748
      if (!item->action_idle_handler)
 
7749
        item->action_idle_handler = gdk_threads_add_idle (gtk_icon_view_item_accessible_idle_do_action, item);
 
7750
      break;
 
7751
    default:
 
7752
      g_assert_not_reached ();
 
7753
      return FALSE;
 
7754
 
 
7755
    }        
 
7756
  return TRUE;
 
7757
}
 
7758
 
 
7759
static gint
 
7760
gtk_icon_view_item_accessible_action_get_n_actions (AtkAction *action)
 
7761
{
 
7762
        return LAST_ACTION;
 
7763
}
 
7764
 
 
7765
static const gchar *
 
7766
gtk_icon_view_item_accessible_action_get_description (AtkAction *action,
 
7767
                                                      gint       i)
 
7768
{
 
7769
  GtkIconViewItemAccessible *item;
 
7770
 
 
7771
  if (i < 0 || i >= LAST_ACTION) 
 
7772
    return NULL;
 
7773
 
 
7774
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
 
7775
 
 
7776
  if (item->action_descriptions[i])
 
7777
    return item->action_descriptions[i];
 
7778
  else
 
7779
    return gtk_icon_view_item_accessible_action_descriptions[i];
 
7780
}
 
7781
 
 
7782
static const gchar *
 
7783
gtk_icon_view_item_accessible_action_get_name (AtkAction *action,
 
7784
                                               gint       i)
 
7785
{
 
7786
  if (i < 0 || i >= LAST_ACTION) 
 
7787
    return NULL;
 
7788
 
 
7789
  return gtk_icon_view_item_accessible_action_names[i];
 
7790
}
 
7791
 
 
7792
static gboolean
 
7793
gtk_icon_view_item_accessible_action_set_description (AtkAction   *action,
 
7794
                                                      gint         i,
 
7795
                                                      const gchar *description)
 
7796
{
 
7797
  GtkIconViewItemAccessible *item;
 
7798
 
 
7799
  if (i < 0 || i >= LAST_ACTION) 
 
7800
    return FALSE;
 
7801
 
 
7802
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (action);
 
7803
 
 
7804
  g_free (item->action_descriptions[i]);
 
7805
 
 
7806
  item->action_descriptions[i] = g_strdup (description);
 
7807
 
 
7808
  return TRUE;
 
7809
}
 
7810
 
 
7811
static void
 
7812
atk_action_item_interface_init (AtkActionIface *iface)
 
7813
{
 
7814
  iface->do_action = gtk_icon_view_item_accessible_action_do_action;
 
7815
  iface->get_n_actions = gtk_icon_view_item_accessible_action_get_n_actions;
 
7816
  iface->get_description = gtk_icon_view_item_accessible_action_get_description;
 
7817
  iface->get_name = gtk_icon_view_item_accessible_action_get_name;
 
7818
  iface->set_description = gtk_icon_view_item_accessible_action_set_description;
 
7819
}
 
7820
 
 
7821
static const gchar *
 
7822
gtk_icon_view_item_accessible_image_get_image_description (AtkImage *image)
 
7823
{
 
7824
  GtkIconViewItemAccessible *item;
 
7825
 
 
7826
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
 
7827
 
 
7828
  return item->image_description;
 
7829
}
 
7830
 
 
7831
static gboolean
 
7832
gtk_icon_view_item_accessible_image_set_image_description (AtkImage    *image,
 
7833
                                                           const gchar *description)
 
7834
{
 
7835
  GtkIconViewItemAccessible *item;
 
7836
 
 
7837
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
 
7838
 
 
7839
  g_free (item->image_description);
 
7840
  item->image_description = g_strdup (description);
 
7841
 
 
7842
  return TRUE;
 
7843
}
 
7844
 
 
7845
static gboolean
 
7846
get_pixbuf_box (GtkIconView     *icon_view,
 
7847
                GtkIconViewItem *item,
 
7848
                GdkRectangle    *box)
 
7849
{
 
7850
  GList *l;
 
7851
 
 
7852
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
7853
    {
 
7854
      GtkIconViewCellInfo *info = l->data;
 
7855
      
 
7856
      if (GTK_IS_CELL_RENDERER_PIXBUF (info->cell))
 
7857
        {
 
7858
          gtk_icon_view_get_cell_box (icon_view, item, info, box);
 
7859
 
 
7860
          return TRUE;
 
7861
        }
 
7862
    }
 
7863
 
 
7864
  return FALSE;
 
7865
}
 
7866
 
 
7867
static gchar *
 
7868
get_text (GtkIconView     *icon_view,
 
7869
          GtkIconViewItem *item)
 
7870
{
 
7871
  GList *l;
 
7872
  gchar *text;
 
7873
 
 
7874
  for (l = icon_view->priv->cell_list; l; l = l->next)
 
7875
    {
 
7876
      GtkIconViewCellInfo *info = l->data;
 
7877
      
 
7878
      if (GTK_IS_CELL_RENDERER_TEXT (info->cell))
 
7879
        {
 
7880
          g_object_get (info->cell, "text", &text, NULL);
 
7881
          
 
7882
          return text;
 
7883
        }
 
7884
    }
 
7885
 
 
7886
  return NULL;
 
7887
}
 
7888
 
 
7889
static void
 
7890
gtk_icon_view_item_accessible_image_get_image_size (AtkImage *image,
 
7891
                                                    gint     *width,
 
7892
                                                    gint     *height)
 
7893
{
 
7894
  GtkIconViewItemAccessible *item;
 
7895
  GdkRectangle box;
 
7896
 
 
7897
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
 
7898
 
 
7899
  if (!GTK_IS_ICON_VIEW (item->widget))
 
7900
    return;
 
7901
 
 
7902
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
7903
    return;
 
7904
 
 
7905
  if (get_pixbuf_box (GTK_ICON_VIEW (item->widget), item->item, &box))
 
7906
    {
 
7907
      *width = box.width;
 
7908
      *height = box.height;  
 
7909
    }
 
7910
}
 
7911
 
 
7912
static void
 
7913
gtk_icon_view_item_accessible_image_get_image_position (AtkImage    *image,
 
7914
                                                        gint        *x,
 
7915
                                                        gint        *y,
 
7916
                                                        AtkCoordType coord_type)
 
7917
{
 
7918
  GtkIconViewItemAccessible *item;
 
7919
  GdkRectangle box;
 
7920
 
 
7921
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (image);
 
7922
 
 
7923
  if (!GTK_IS_ICON_VIEW (item->widget))
 
7924
    return;
 
7925
 
 
7926
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
7927
    return;
 
7928
 
 
7929
  atk_component_get_position (ATK_COMPONENT (image), x, y, coord_type);
 
7930
 
 
7931
  if (get_pixbuf_box (GTK_ICON_VIEW (item->widget), item->item, &box))
 
7932
    {
 
7933
      *x+= box.x - item->item->x;
 
7934
      *y+= box.y - item->item->y;
 
7935
    }
 
7936
 
 
7937
}
 
7938
 
 
7939
static void
 
7940
atk_image_item_interface_init (AtkImageIface *iface)
 
7941
{
 
7942
  iface->get_image_description = gtk_icon_view_item_accessible_image_get_image_description;
 
7943
  iface->set_image_description = gtk_icon_view_item_accessible_image_set_image_description;
 
7944
  iface->get_image_size = gtk_icon_view_item_accessible_image_get_image_size;
 
7945
  iface->get_image_position = gtk_icon_view_item_accessible_image_get_image_position;
 
7946
}
 
7947
 
 
7948
static gchar *
 
7949
gtk_icon_view_item_accessible_text_get_text (AtkText *text,
 
7950
                                             gint     start_pos,
 
7951
                                             gint     end_pos)
 
7952
{
 
7953
  GtkIconViewItemAccessible *item;
 
7954
  GtkTextIter start, end;
 
7955
  GtkTextBuffer *buffer;
 
7956
 
 
7957
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
7958
 
 
7959
  if (!GTK_IS_ICON_VIEW (item->widget))
 
7960
    return NULL;
 
7961
 
 
7962
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
7963
    return NULL;
 
7964
 
 
7965
  buffer = item->text_buffer;
 
7966
  gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
 
7967
  if (end_pos < 0)
 
7968
    gtk_text_buffer_get_end_iter (buffer, &end);
 
7969
  else
 
7970
    gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
 
7971
 
 
7972
  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 
7973
}
 
7974
 
 
7975
static gunichar
 
7976
gtk_icon_view_item_accessible_text_get_character_at_offset (AtkText *text,
 
7977
                                                            gint     offset)
 
7978
{
 
7979
  GtkIconViewItemAccessible *item;
 
7980
  GtkTextIter start, end;
 
7981
  GtkTextBuffer *buffer;
 
7982
  gchar *string;
 
7983
  gunichar unichar;
 
7984
 
 
7985
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
7986
 
 
7987
  if (!GTK_IS_ICON_VIEW (item->widget))
 
7988
    return '\0';
 
7989
 
 
7990
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
7991
    return '\0';
 
7992
 
 
7993
  buffer = item->text_buffer;
 
7994
  if (offset >= gtk_text_buffer_get_char_count (buffer))
 
7995
    return '\0';
 
7996
 
 
7997
  gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
 
7998
  end = start;
 
7999
  gtk_text_iter_forward_char (&end);
 
8000
  string = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
 
8001
  unichar = g_utf8_get_char (string);
 
8002
  g_free(string);
 
8003
 
 
8004
  return unichar;
 
8005
}
 
8006
 
 
8007
#if 0
 
8008
static void
 
8009
get_pango_text_offsets (PangoLayout     *layout,
 
8010
                        GtkTextBuffer   *buffer,
 
8011
                        gint             function,
 
8012
                        AtkTextBoundary  boundary_type,
 
8013
                        gint             offset,
 
8014
                        gint            *start_offset,
 
8015
                        gint            *end_offset,
 
8016
                        GtkTextIter     *start_iter,
 
8017
                        GtkTextIter     *end_iter)
 
8018
{
 
8019
  PangoLayoutIter *iter;
 
8020
  PangoLayoutLine *line, *prev_line = NULL, *prev_prev_line = NULL;
 
8021
  gint index, start_index, end_index;
 
8022
  const gchar *text;
 
8023
  gboolean found = FALSE;
 
8024
 
 
8025
  text = pango_layout_get_text (layout);
 
8026
  index = g_utf8_offset_to_pointer (text, offset) - text;
 
8027
  iter = pango_layout_get_iter (layout);
 
8028
  do
 
8029
    {
 
8030
      line = pango_layout_iter_get_line_readonly (iter);
 
8031
      start_index = line->start_index;
 
8032
      end_index = start_index + line->length;
 
8033
 
 
8034
      if (index >= start_index && index <= end_index)
 
8035
        {
 
8036
          /*
 
8037
           * Found line for offset
 
8038
           */
 
8039
          switch (function)
 
8040
            {
 
8041
            case 0:
 
8042
                  /*
 
8043
                   * We want the previous line
 
8044
                   */
 
8045
              if (prev_line)
 
8046
                {
 
8047
                  switch (boundary_type)
 
8048
                    {
 
8049
                    case ATK_TEXT_BOUNDARY_LINE_START:
 
8050
                      end_index = start_index;
 
8051
                      start_index = prev_line->start_index;
 
8052
                      break;
 
8053
                    case ATK_TEXT_BOUNDARY_LINE_END:
 
8054
                      if (prev_prev_line)
 
8055
                        start_index = prev_prev_line->start_index + 
 
8056
                                  prev_prev_line->length;
 
8057
                      end_index = prev_line->start_index + prev_line->length;
 
8058
                      break;
 
8059
                    default:
 
8060
                      g_assert_not_reached();
 
8061
                    }
 
8062
                }
 
8063
              else
 
8064
                start_index = end_index = 0;
 
8065
              break;
 
8066
            case 1:
 
8067
              switch (boundary_type)
 
8068
                {
 
8069
                case ATK_TEXT_BOUNDARY_LINE_START:
 
8070
                  if (pango_layout_iter_next_line (iter))
 
8071
                    end_index = pango_layout_iter_get_line_readonly (iter)->start_index;
 
8072
                  break;
 
8073
                case ATK_TEXT_BOUNDARY_LINE_END:
 
8074
                  if (prev_line)
 
8075
                    start_index = prev_line->start_index + 
 
8076
                                  prev_line->length;
 
8077
                  break;
 
8078
                default:
 
8079
                  g_assert_not_reached();
 
8080
                }
 
8081
              break;
 
8082
            case 2:
 
8083
               /*
 
8084
                * We want the next line
 
8085
                */
 
8086
              if (pango_layout_iter_next_line (iter))
 
8087
                {
 
8088
                  line = pango_layout_iter_get_line_readonly (iter);
 
8089
                  switch (boundary_type)
 
8090
                    {
 
8091
                    case ATK_TEXT_BOUNDARY_LINE_START:
 
8092
                      start_index = line->start_index;
 
8093
                      if (pango_layout_iter_next_line (iter))
 
8094
                        end_index = pango_layout_iter_get_line_readonly (iter)->start_index;
 
8095
                      else
 
8096
                        end_index = start_index + line->length;
 
8097
                      break;
 
8098
                    case ATK_TEXT_BOUNDARY_LINE_END:
 
8099
                      start_index = end_index;
 
8100
                      end_index = line->start_index + line->length;
 
8101
                      break;
 
8102
                    default:
 
8103
                      g_assert_not_reached();
 
8104
                    }
 
8105
                }
 
8106
              else
 
8107
                start_index = end_index;
 
8108
              break;
 
8109
            }
 
8110
          found = TRUE;
 
8111
          break;
 
8112
        }
 
8113
      prev_prev_line = prev_line; 
 
8114
      prev_line = line; 
 
8115
    }
 
8116
  while (pango_layout_iter_next_line (iter));
 
8117
 
 
8118
  if (!found)
 
8119
    {
 
8120
      start_index = prev_line->start_index + prev_line->length;
 
8121
      end_index = start_index;
 
8122
    }
 
8123
  pango_layout_iter_free (iter);
 
8124
  *start_offset = g_utf8_pointer_to_offset (text, text + start_index);
 
8125
  *end_offset = g_utf8_pointer_to_offset (text, text + end_index);
 
8126
 
 
8127
  gtk_text_buffer_get_iter_at_offset (buffer, start_iter, *start_offset);
 
8128
  gtk_text_buffer_get_iter_at_offset (buffer, end_iter, *end_offset);
 
8129
}
 
8130
#endif
 
8131
 
 
8132
static gchar*
 
8133
gtk_icon_view_item_accessible_text_get_text_before_offset (AtkText         *text,
 
8134
                                                           gint            offset,
 
8135
                                                           AtkTextBoundary boundary_type,
 
8136
                                                           gint            *start_offset,
 
8137
                                                           gint            *end_offset)
 
8138
{
 
8139
  GtkIconViewItemAccessible *item;
 
8140
  GtkTextIter start, end;
 
8141
  GtkTextBuffer *buffer;
 
8142
#if 0
 
8143
  GtkIconView *icon_view;
 
8144
#endif
 
8145
 
 
8146
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8147
 
 
8148
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8149
    return NULL;
 
8150
 
 
8151
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8152
    return NULL;
 
8153
 
 
8154
  buffer = item->text_buffer;
 
8155
 
 
8156
  if (!gtk_text_buffer_get_char_count (buffer))
 
8157
    {
 
8158
      *start_offset = 0;
 
8159
      *end_offset = 0;
 
8160
      return g_strdup ("");
 
8161
    }
 
8162
  gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
 
8163
   
 
8164
  end = start;
 
8165
 
 
8166
  switch (boundary_type)
 
8167
    {
 
8168
    case ATK_TEXT_BOUNDARY_CHAR:
 
8169
      gtk_text_iter_backward_char(&start);
 
8170
      break;
 
8171
    case ATK_TEXT_BOUNDARY_WORD_START:
 
8172
      if (!gtk_text_iter_starts_word (&start))
 
8173
        gtk_text_iter_backward_word_start (&start);
 
8174
      end = start;
 
8175
      gtk_text_iter_backward_word_start(&start);
 
8176
      break;
 
8177
    case ATK_TEXT_BOUNDARY_WORD_END:
 
8178
      if (gtk_text_iter_inside_word (&start) &&
 
8179
          !gtk_text_iter_starts_word (&start))
 
8180
        gtk_text_iter_backward_word_start (&start);
 
8181
      while (!gtk_text_iter_ends_word (&start))
 
8182
        {
 
8183
          if (!gtk_text_iter_backward_char (&start))
 
8184
            break;
 
8185
        }
 
8186
      end = start;
 
8187
      gtk_text_iter_backward_word_start(&start);
 
8188
      while (!gtk_text_iter_ends_word (&start))
 
8189
        {
 
8190
          if (!gtk_text_iter_backward_char (&start))
 
8191
            break;
 
8192
        }
 
8193
      break;
 
8194
    case ATK_TEXT_BOUNDARY_SENTENCE_START:
 
8195
      if (!gtk_text_iter_starts_sentence (&start))
 
8196
        gtk_text_iter_backward_sentence_start (&start);
 
8197
      end = start;
 
8198
      gtk_text_iter_backward_sentence_start (&start);
 
8199
      break;
 
8200
    case ATK_TEXT_BOUNDARY_SENTENCE_END:
 
8201
      if (gtk_text_iter_inside_sentence (&start) &&
 
8202
          !gtk_text_iter_starts_sentence (&start))
 
8203
        gtk_text_iter_backward_sentence_start (&start);
 
8204
      while (!gtk_text_iter_ends_sentence (&start))
 
8205
        {
 
8206
          if (!gtk_text_iter_backward_char (&start))
 
8207
            break;
 
8208
        }
 
8209
      end = start;
 
8210
      gtk_text_iter_backward_sentence_start (&start);
 
8211
      while (!gtk_text_iter_ends_sentence (&start))
 
8212
        {
 
8213
          if (!gtk_text_iter_backward_char (&start))
 
8214
            break;
 
8215
        }
 
8216
      break;
 
8217
   case ATK_TEXT_BOUNDARY_LINE_START:
 
8218
   case ATK_TEXT_BOUNDARY_LINE_END:
 
8219
#if 0
 
8220
      icon_view = GTK_ICON_VIEW (item->widget);
 
8221
      /* FIXME we probably have to use GailTextCell to salvage this */
 
8222
      gtk_icon_view_update_item_text (icon_view, item->item);
 
8223
      get_pango_text_offsets (icon_view->priv->layout,
 
8224
                              buffer,
 
8225
                              0,
 
8226
                              boundary_type,
 
8227
                              offset,
 
8228
                              start_offset,
 
8229
                              end_offset,
 
8230
                              &start,
 
8231
                              &end);
 
8232
#endif
 
8233
      break;
 
8234
    }
 
8235
 
 
8236
  *start_offset = gtk_text_iter_get_offset (&start);
 
8237
  *end_offset = gtk_text_iter_get_offset (&end);
 
8238
 
 
8239
  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 
8240
}
 
8241
 
 
8242
static gchar*
 
8243
gtk_icon_view_item_accessible_text_get_text_at_offset (AtkText         *text,
 
8244
                                                       gint            offset,
 
8245
                                                       AtkTextBoundary boundary_type,
 
8246
                                                       gint            *start_offset,
 
8247
                                                       gint            *end_offset)
 
8248
{
 
8249
  GtkIconViewItemAccessible *item;
 
8250
  GtkTextIter start, end;
 
8251
  GtkTextBuffer *buffer;
 
8252
#if 0
 
8253
  GtkIconView *icon_view;
 
8254
#endif
 
8255
 
 
8256
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8257
 
 
8258
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8259
    return NULL;
 
8260
 
 
8261
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8262
    return NULL;
 
8263
 
 
8264
  buffer = item->text_buffer;
 
8265
 
 
8266
  if (!gtk_text_buffer_get_char_count (buffer))
 
8267
    {
 
8268
      *start_offset = 0;
 
8269
      *end_offset = 0;
 
8270
      return g_strdup ("");
 
8271
    }
 
8272
  gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
 
8273
   
 
8274
  end = start;
 
8275
 
 
8276
  switch (boundary_type)
 
8277
    {
 
8278
    case ATK_TEXT_BOUNDARY_CHAR:
 
8279
      gtk_text_iter_forward_char (&end);
 
8280
      break;
 
8281
    case ATK_TEXT_BOUNDARY_WORD_START:
 
8282
      if (!gtk_text_iter_starts_word (&start))
 
8283
        gtk_text_iter_backward_word_start (&start);
 
8284
      if (gtk_text_iter_inside_word (&end))
 
8285
        gtk_text_iter_forward_word_end (&end);
 
8286
      while (!gtk_text_iter_starts_word (&end))
 
8287
        {
 
8288
          if (!gtk_text_iter_forward_char (&end))
 
8289
            break;
 
8290
        }
 
8291
      break;
 
8292
    case ATK_TEXT_BOUNDARY_WORD_END:
 
8293
      if (gtk_text_iter_inside_word (&start) &&
 
8294
          !gtk_text_iter_starts_word (&start))
 
8295
        gtk_text_iter_backward_word_start (&start);
 
8296
      while (!gtk_text_iter_ends_word (&start))
 
8297
        {
 
8298
          if (!gtk_text_iter_backward_char (&start))
 
8299
            break;
 
8300
        }
 
8301
      gtk_text_iter_forward_word_end (&end);
 
8302
      break;
 
8303
    case ATK_TEXT_BOUNDARY_SENTENCE_START:
 
8304
      if (!gtk_text_iter_starts_sentence (&start))
 
8305
        gtk_text_iter_backward_sentence_start (&start);
 
8306
      if (gtk_text_iter_inside_sentence (&end))
 
8307
        gtk_text_iter_forward_sentence_end (&end);
 
8308
      while (!gtk_text_iter_starts_sentence (&end))
 
8309
        {
 
8310
          if (!gtk_text_iter_forward_char (&end))
 
8311
            break;
 
8312
        }
 
8313
      break;
 
8314
    case ATK_TEXT_BOUNDARY_SENTENCE_END:
 
8315
      if (gtk_text_iter_inside_sentence (&start) &&
 
8316
          !gtk_text_iter_starts_sentence (&start))
 
8317
        gtk_text_iter_backward_sentence_start (&start);
 
8318
      while (!gtk_text_iter_ends_sentence (&start))
 
8319
        {
 
8320
          if (!gtk_text_iter_backward_char (&start))
 
8321
            break;
 
8322
        }
 
8323
      gtk_text_iter_forward_sentence_end (&end);
 
8324
      break;
 
8325
   case ATK_TEXT_BOUNDARY_LINE_START:
 
8326
   case ATK_TEXT_BOUNDARY_LINE_END:
 
8327
#if 0
 
8328
      icon_view = GTK_ICON_VIEW (item->widget);
 
8329
      /* FIXME we probably have to use GailTextCell to salvage this */
 
8330
      gtk_icon_view_update_item_text (icon_view, item->item);
 
8331
      get_pango_text_offsets (icon_view->priv->layout,
 
8332
                              buffer,
 
8333
                              1,
 
8334
                              boundary_type,
 
8335
                              offset,
 
8336
                              start_offset,
 
8337
                              end_offset,
 
8338
                              &start,
 
8339
                              &end);
 
8340
#endif
 
8341
      break;
 
8342
    }
 
8343
 
 
8344
 
 
8345
  *start_offset = gtk_text_iter_get_offset (&start);
 
8346
  *end_offset = gtk_text_iter_get_offset (&end);
 
8347
 
 
8348
  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 
8349
}
 
8350
 
 
8351
static gchar*
 
8352
gtk_icon_view_item_accessible_text_get_text_after_offset (AtkText         *text,
 
8353
                                                          gint            offset,
 
8354
                                                          AtkTextBoundary boundary_type,
 
8355
                                                          gint            *start_offset,
 
8356
                                                          gint            *end_offset)
 
8357
{
 
8358
  GtkIconViewItemAccessible *item;
 
8359
  GtkTextIter start, end;
 
8360
  GtkTextBuffer *buffer;
 
8361
#if 0
 
8362
  GtkIconView *icon_view;
 
8363
#endif
 
8364
 
 
8365
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8366
 
 
8367
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8368
    return NULL;
 
8369
 
 
8370
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8371
    return NULL;
 
8372
 
 
8373
  buffer = item->text_buffer;
 
8374
 
 
8375
  if (!gtk_text_buffer_get_char_count (buffer))
 
8376
    {
 
8377
      *start_offset = 0;
 
8378
      *end_offset = 0;
 
8379
      return g_strdup ("");
 
8380
    }
 
8381
  gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
 
8382
   
 
8383
  end = start;
 
8384
 
 
8385
  switch (boundary_type)
 
8386
    {
 
8387
    case ATK_TEXT_BOUNDARY_CHAR:
 
8388
      gtk_text_iter_forward_char(&start);
 
8389
      gtk_text_iter_forward_chars(&end, 2);
 
8390
      break;
 
8391
    case ATK_TEXT_BOUNDARY_WORD_START:
 
8392
      if (gtk_text_iter_inside_word (&end))
 
8393
        gtk_text_iter_forward_word_end (&end);
 
8394
      while (!gtk_text_iter_starts_word (&end))
 
8395
        {
 
8396
          if (!gtk_text_iter_forward_char (&end))
 
8397
            break;
 
8398
        }
 
8399
      start = end;
 
8400
      if (!gtk_text_iter_is_end (&end))
 
8401
        {
 
8402
          gtk_text_iter_forward_word_end (&end);
 
8403
          while (!gtk_text_iter_starts_word (&end))
 
8404
            {
 
8405
              if (!gtk_text_iter_forward_char (&end))
 
8406
                break;
 
8407
            }
 
8408
        }
 
8409
      break;
 
8410
    case ATK_TEXT_BOUNDARY_WORD_END:
 
8411
      gtk_text_iter_forward_word_end (&end);
 
8412
      start = end;
 
8413
      if (!gtk_text_iter_is_end (&end))
 
8414
        gtk_text_iter_forward_word_end (&end);
 
8415
      break;
 
8416
    case ATK_TEXT_BOUNDARY_SENTENCE_START:
 
8417
      if (gtk_text_iter_inside_sentence (&end))
 
8418
        gtk_text_iter_forward_sentence_end (&end);
 
8419
      while (!gtk_text_iter_starts_sentence (&end))
 
8420
        {
 
8421
          if (!gtk_text_iter_forward_char (&end))
 
8422
            break;
 
8423
        }
 
8424
      start = end;
 
8425
      if (!gtk_text_iter_is_end (&end))
 
8426
        {
 
8427
          gtk_text_iter_forward_sentence_end (&end);
 
8428
          while (!gtk_text_iter_starts_sentence (&end))
 
8429
            {
 
8430
              if (!gtk_text_iter_forward_char (&end))
 
8431
                break;
 
8432
            }
 
8433
        }
 
8434
      break;
 
8435
    case ATK_TEXT_BOUNDARY_SENTENCE_END:
 
8436
      gtk_text_iter_forward_sentence_end (&end);
 
8437
      start = end;
 
8438
      if (!gtk_text_iter_is_end (&end))
 
8439
        gtk_text_iter_forward_sentence_end (&end);
 
8440
      break;
 
8441
   case ATK_TEXT_BOUNDARY_LINE_START:
 
8442
   case ATK_TEXT_BOUNDARY_LINE_END:
 
8443
#if 0
 
8444
      icon_view = GTK_ICON_VIEW (item->widget);
 
8445
      /* FIXME we probably have to use GailTextCell to salvage this */
 
8446
      gtk_icon_view_update_item_text (icon_view, item->item);
 
8447
      get_pango_text_offsets (icon_view->priv->layout,
 
8448
                              buffer,
 
8449
                              2,
 
8450
                              boundary_type,
 
8451
                              offset,
 
8452
                              start_offset,
 
8453
                              end_offset,
 
8454
                              &start,
 
8455
                              &end);
 
8456
#endif
 
8457
      break;
 
8458
    }
 
8459
  *start_offset = gtk_text_iter_get_offset (&start);
 
8460
  *end_offset = gtk_text_iter_get_offset (&end);
 
8461
 
 
8462
  return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
 
8463
}
 
8464
 
 
8465
static gint
 
8466
gtk_icon_view_item_accessible_text_get_character_count (AtkText *text)
 
8467
{
 
8468
  GtkIconViewItemAccessible *item;
 
8469
 
 
8470
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8471
 
 
8472
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8473
    return 0;
 
8474
 
 
8475
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8476
    return 0;
 
8477
 
 
8478
  return gtk_text_buffer_get_char_count (item->text_buffer);
 
8479
}
 
8480
 
 
8481
static void
 
8482
gtk_icon_view_item_accessible_text_get_character_extents (AtkText      *text,
 
8483
                                                          gint         offset,
 
8484
                                                          gint         *x,
 
8485
                                                          gint         *y,
 
8486
                                                          gint         *width,
 
8487
                                                          gint         *height,
 
8488
                                                          AtkCoordType coord_type)
 
8489
{
 
8490
  GtkIconViewItemAccessible *item;
 
8491
#if 0
 
8492
  GtkIconView *icon_view;
 
8493
  PangoRectangle char_rect;
 
8494
  const gchar *item_text;
 
8495
  gint index;
 
8496
#endif
 
8497
 
 
8498
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8499
 
 
8500
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8501
    return;
 
8502
 
 
8503
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8504
    return;
 
8505
 
 
8506
#if 0
 
8507
  icon_view = GTK_ICON_VIEW (item->widget);
 
8508
      /* FIXME we probably have to use GailTextCell to salvage this */
 
8509
  gtk_icon_view_update_item_text (icon_view, item->item);
 
8510
  item_text = pango_layout_get_text (icon_view->priv->layout);
 
8511
  index = g_utf8_offset_to_pointer (item_text, offset) - item_text;
 
8512
  pango_layout_index_to_pos (icon_view->priv->layout, index, &char_rect);
 
8513
 
 
8514
  atk_component_get_position (ATK_COMPONENT (text), x, y, coord_type);
 
8515
  *x += item->item->layout_x - item->item->x + char_rect.x / PANGO_SCALE;
 
8516
  /* Look at gtk_icon_view_paint_item() to see where the text is. */
 
8517
  *x -=  ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
 
8518
  *y += item->item->layout_y - item->item->y + char_rect.y / PANGO_SCALE;
 
8519
  *width = char_rect.width / PANGO_SCALE;
 
8520
  *height = char_rect.height / PANGO_SCALE;
 
8521
#endif
 
8522
}
 
8523
 
 
8524
static gint
 
8525
gtk_icon_view_item_accessible_text_get_offset_at_point (AtkText      *text,
 
8526
                                                        gint          x,
 
8527
                                                        gint          y,
 
8528
                                                        AtkCoordType coord_type)
 
8529
{
 
8530
  GtkIconViewItemAccessible *item;
 
8531
  gint offset = 0;
 
8532
#if 0
 
8533
  GtkIconView *icon_view;
 
8534
  const gchar *item_text;
 
8535
  gint index;
 
8536
  gint l_x, l_y;
 
8537
#endif
 
8538
 
 
8539
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (text);
 
8540
 
 
8541
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8542
    return -1;
 
8543
 
 
8544
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8545
    return -1;
 
8546
 
 
8547
#if 0
 
8548
  icon_view = GTK_ICON_VIEW (item->widget);
 
8549
      /* FIXME we probably have to use GailTextCell to salvage this */
 
8550
  gtk_icon_view_update_item_text (icon_view, item->item);
 
8551
  atk_component_get_position (ATK_COMPONENT (text), &l_x, &l_y, coord_type);
 
8552
  x -= l_x + item->item->layout_x - item->item->x;
 
8553
  x +=  ((item->item->width - item->item->layout_width) / 2) + (MAX (item->item->pixbuf_width, icon_view->priv->item_width) - item->item->width) / 2,
 
8554
  y -= l_y + item->item->layout_y - item->item->y;
 
8555
  item_text = pango_layout_get_text (icon_view->priv->layout);
 
8556
  if (!pango_layout_xy_to_index (icon_view->priv->layout, 
 
8557
                                x * PANGO_SCALE,
 
8558
                                y * PANGO_SCALE,
 
8559
                                &index, NULL))
 
8560
    {
 
8561
      if (x < 0 || y < 0)
 
8562
        index = 0;
 
8563
      else
 
8564
        index = -1;
 
8565
    } 
 
8566
  if (index == -1)
 
8567
    offset = g_utf8_strlen (item_text, -1);
 
8568
  else
 
8569
    offset = g_utf8_pointer_to_offset (item_text, item_text + index);
 
8570
#endif
 
8571
  return offset;
 
8572
}
 
8573
 
 
8574
static void
 
8575
atk_text_item_interface_init (AtkTextIface *iface)
 
8576
{
 
8577
  iface->get_text = gtk_icon_view_item_accessible_text_get_text;
 
8578
  iface->get_character_at_offset = gtk_icon_view_item_accessible_text_get_character_at_offset;
 
8579
  iface->get_text_before_offset = gtk_icon_view_item_accessible_text_get_text_before_offset;
 
8580
  iface->get_text_at_offset = gtk_icon_view_item_accessible_text_get_text_at_offset;
 
8581
  iface->get_text_after_offset = gtk_icon_view_item_accessible_text_get_text_after_offset;
 
8582
  iface->get_character_count = gtk_icon_view_item_accessible_text_get_character_count;
 
8583
  iface->get_character_extents = gtk_icon_view_item_accessible_text_get_character_extents;
 
8584
  iface->get_offset_at_point = gtk_icon_view_item_accessible_text_get_offset_at_point;
 
8585
}
 
8586
 
 
8587
static void
 
8588
gtk_icon_view_item_accessible_get_extents (AtkComponent *component,
 
8589
                                           gint         *x,
 
8590
                                           gint         *y,
 
8591
                                           gint         *width,
 
8592
                                           gint         *height,
 
8593
                                           AtkCoordType  coord_type)
 
8594
{
 
8595
  GtkIconViewItemAccessible *item;
 
8596
  AtkObject *parent_obj;
 
8597
  gint l_x, l_y;
 
8598
 
 
8599
  g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component));
 
8600
 
 
8601
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
 
8602
  if (!GTK_IS_WIDGET (item->widget))
 
8603
    return;
 
8604
 
 
8605
  if (atk_state_set_contains_state (item->state_set, ATK_STATE_DEFUNCT))
 
8606
    return;
 
8607
 
 
8608
  *width = item->item->width;
 
8609
  *height = item->item->height;
 
8610
  if (gtk_icon_view_item_accessible_is_showing (item))
 
8611
    {
 
8612
      parent_obj = gtk_widget_get_accessible (item->widget);
 
8613
      atk_component_get_position (ATK_COMPONENT (parent_obj), &l_x, &l_y, coord_type);
 
8614
      *x = l_x + item->item->x;
 
8615
      *y = l_y + item->item->y;
 
8616
    }
 
8617
  else
 
8618
    {
 
8619
      *x = G_MININT;
 
8620
      *y = G_MININT;
 
8621
    }
 
8622
}
 
8623
 
 
8624
static gboolean
 
8625
gtk_icon_view_item_accessible_grab_focus (AtkComponent *component)
 
8626
{
 
8627
  GtkIconViewItemAccessible *item;
 
8628
  GtkWidget *toplevel;
 
8629
 
 
8630
  g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (component), FALSE);
 
8631
 
 
8632
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (component);
 
8633
  if (!GTK_IS_WIDGET (item->widget))
 
8634
    return FALSE;
 
8635
 
 
8636
  gtk_widget_grab_focus (item->widget);
 
8637
  gtk_icon_view_set_cursor_item (GTK_ICON_VIEW (item->widget), item->item, -1);
 
8638
  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (item->widget));
 
8639
  if (gtk_widget_is_toplevel (toplevel))
 
8640
    gtk_window_present (GTK_WINDOW (toplevel));
 
8641
 
 
8642
  return TRUE;
 
8643
}
 
8644
 
 
8645
static void
 
8646
atk_component_item_interface_init (AtkComponentIface *iface)
 
8647
{
 
8648
  iface->get_extents = gtk_icon_view_item_accessible_get_extents;
 
8649
  iface->grab_focus = gtk_icon_view_item_accessible_grab_focus;
 
8650
}
 
8651
 
 
8652
static gboolean
 
8653
gtk_icon_view_item_accessible_add_state (GtkIconViewItemAccessible *item,
 
8654
                                         AtkStateType               state_type,
 
8655
                                         gboolean                   emit_signal)
 
8656
{
 
8657
  gboolean rc;
 
8658
 
 
8659
  rc = atk_state_set_add_state (item->state_set, state_type);
 
8660
  /*
 
8661
   * The signal should only be generated if the value changed,
 
8662
   * not when the item is set up.  So states that are set
 
8663
   * initially should pass FALSE as the emit_signal argument.
 
8664
   */
 
8665
 
 
8666
  if (emit_signal)
 
8667
    {
 
8668
      atk_object_notify_state_change (ATK_OBJECT (item), state_type, TRUE);
 
8669
      /* If state_type is ATK_STATE_VISIBLE, additional notification */
 
8670
      if (state_type == ATK_STATE_VISIBLE)
 
8671
        g_signal_emit_by_name (item, "visible-data-changed");
 
8672
    }
 
8673
 
 
8674
  return rc;
 
8675
}
 
8676
 
 
8677
static gboolean
 
8678
gtk_icon_view_item_accessible_remove_state (GtkIconViewItemAccessible *item,
 
8679
                                            AtkStateType               state_type,
 
8680
                                            gboolean                   emit_signal)
 
8681
{
 
8682
  if (atk_state_set_contains_state (item->state_set, state_type))
 
8683
    {
 
8684
      gboolean rc;
 
8685
 
 
8686
      rc = atk_state_set_remove_state (item->state_set, state_type);
 
8687
      /*
 
8688
       * The signal should only be generated if the value changed,
 
8689
       * not when the item is set up.  So states that are set
 
8690
       * initially should pass FALSE as the emit_signal argument.
 
8691
       */
 
8692
 
 
8693
      if (emit_signal)
 
8694
        {
 
8695
          atk_object_notify_state_change (ATK_OBJECT (item), state_type, FALSE);
 
8696
          /* If state_type is ATK_STATE_VISIBLE, additional notification */
 
8697
          if (state_type == ATK_STATE_VISIBLE)
 
8698
            g_signal_emit_by_name (item, "visible-data-changed");
 
8699
        }
 
8700
 
 
8701
      return rc;
 
8702
    }
 
8703
  else
 
8704
    return FALSE;
 
8705
}
 
8706
 
 
8707
static gboolean
 
8708
gtk_icon_view_item_accessible_is_showing (GtkIconViewItemAccessible *item)
 
8709
{
 
8710
  GtkIconView *icon_view;
 
8711
  GdkRectangle visible_rect;
 
8712
  gboolean is_showing;
 
8713
 
 
8714
  /*
 
8715
   * An item is considered "SHOWING" if any part of the item is in the
 
8716
   * visible rectangle.
 
8717
   */
 
8718
 
 
8719
  if (!GTK_IS_ICON_VIEW (item->widget))
 
8720
    return FALSE;
 
8721
 
 
8722
  if (item->item == NULL)
 
8723
    return FALSE;
 
8724
 
 
8725
  icon_view = GTK_ICON_VIEW (item->widget);
 
8726
  visible_rect.x = 0;
 
8727
  if (icon_view->priv->hadjustment)
 
8728
    visible_rect.x += icon_view->priv->hadjustment->value;
 
8729
  visible_rect.y = 0;
 
8730
  if (icon_view->priv->hadjustment)
 
8731
    visible_rect.y += icon_view->priv->vadjustment->value;
 
8732
  visible_rect.width = item->widget->allocation.width;
 
8733
  visible_rect.height = item->widget->allocation.height;
 
8734
 
 
8735
  if (((item->item->x + item->item->width) < visible_rect.x) ||
 
8736
     ((item->item->y + item->item->height) < (visible_rect.y)) ||
 
8737
     (item->item->x > (visible_rect.x + visible_rect.width)) ||
 
8738
     (item->item->y > (visible_rect.y + visible_rect.height)))
 
8739
    is_showing =  FALSE;
 
8740
  else
 
8741
    is_showing = TRUE;
 
8742
 
 
8743
  return is_showing;
 
8744
}
 
8745
 
 
8746
static gboolean
 
8747
gtk_icon_view_item_accessible_set_visibility (GtkIconViewItemAccessible *item,
 
8748
                                              gboolean                   emit_signal)
 
8749
{
 
8750
  if (gtk_icon_view_item_accessible_is_showing (item))
 
8751
    return gtk_icon_view_item_accessible_add_state (item, ATK_STATE_SHOWING,
 
8752
                                                    emit_signal);
 
8753
  else
 
8754
    return gtk_icon_view_item_accessible_remove_state (item, ATK_STATE_SHOWING,
 
8755
                                                       emit_signal);
 
8756
}
 
8757
 
 
8758
static void
 
8759
gtk_icon_view_item_accessible_object_init (GtkIconViewItemAccessible *item)
 
8760
{
 
8761
  gint i;
 
8762
 
 
8763
  item->state_set = atk_state_set_new ();
 
8764
 
 
8765
  atk_state_set_add_state (item->state_set, ATK_STATE_ENABLED);
 
8766
  atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSABLE);
 
8767
  atk_state_set_add_state (item->state_set, ATK_STATE_SENSITIVE);
 
8768
  atk_state_set_add_state (item->state_set, ATK_STATE_SELECTABLE);
 
8769
  atk_state_set_add_state (item->state_set, ATK_STATE_VISIBLE);
 
8770
 
 
8771
  for (i = 0; i < LAST_ACTION; i++)
 
8772
    item->action_descriptions[i] = NULL;
 
8773
 
 
8774
  item->image_description = NULL;
 
8775
 
 
8776
  item->action_idle_handler = 0;
 
8777
}
 
8778
 
 
8779
static void
 
8780
gtk_icon_view_item_accessible_finalize (GObject *object)
 
8781
{
 
8782
  GtkIconViewItemAccessible *item;
 
8783
  gint i;
 
8784
 
 
8785
  g_return_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (object));
 
8786
 
 
8787
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (object);
 
8788
 
 
8789
  if (item->widget)
 
8790
    g_object_remove_weak_pointer (G_OBJECT (item->widget), (gpointer) &item->widget);
 
8791
 
 
8792
  if (item->state_set)
 
8793
    g_object_unref (item->state_set);
 
8794
 
 
8795
  if (item->text_buffer)
 
8796
     g_object_unref (item->text_buffer);
 
8797
 
 
8798
  for (i = 0; i < LAST_ACTION; i++)
 
8799
    g_free (item->action_descriptions[i]);
 
8800
 
 
8801
  g_free (item->image_description);
 
8802
 
 
8803
  if (item->action_idle_handler)
 
8804
    {
 
8805
      g_source_remove (item->action_idle_handler);
 
8806
      item->action_idle_handler = 0;
 
8807
    }
 
8808
 
 
8809
  G_OBJECT_CLASS (accessible_item_parent_class)->finalize (object);
 
8810
}
 
8811
 
 
8812
static AtkObject*
 
8813
gtk_icon_view_item_accessible_get_parent (AtkObject *obj)
 
8814
{
 
8815
  GtkIconViewItemAccessible *item;
 
8816
 
 
8817
  g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), NULL);
 
8818
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
 
8819
 
 
8820
  if (item->widget)
 
8821
    return gtk_widget_get_accessible (item->widget);
 
8822
  else
 
8823
    return NULL;
 
8824
}
 
8825
 
 
8826
static gint
 
8827
gtk_icon_view_item_accessible_get_index_in_parent (AtkObject *obj)
 
8828
{
 
8829
  GtkIconViewItemAccessible *item;
 
8830
 
 
8831
  g_return_val_if_fail (GTK_IS_ICON_VIEW_ITEM_ACCESSIBLE (obj), 0);
 
8832
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
 
8833
 
 
8834
  return item->item->index; 
 
8835
}
 
8836
 
 
8837
static AtkStateSet *
 
8838
gtk_icon_view_item_accessible_ref_state_set (AtkObject *obj)
 
8839
{
 
8840
  GtkIconViewItemAccessible *item;
 
8841
  GtkIconView *icon_view;
 
8842
 
 
8843
  item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
 
8844
  g_return_val_if_fail (item->state_set, NULL);
 
8845
 
 
8846
  if (!item->widget)
 
8847
    return NULL;
 
8848
 
 
8849
  icon_view = GTK_ICON_VIEW (item->widget);
 
8850
  if (icon_view->priv->cursor_item == item->item)
 
8851
    atk_state_set_add_state (item->state_set, ATK_STATE_FOCUSED);
 
8852
  else
 
8853
    atk_state_set_remove_state (item->state_set, ATK_STATE_FOCUSED);
 
8854
  if (item->item->selected)
 
8855
    atk_state_set_add_state (item->state_set, ATK_STATE_SELECTED);
 
8856
  else
 
8857
    atk_state_set_remove_state (item->state_set, ATK_STATE_SELECTED);
 
8858
 
 
8859
  return g_object_ref (item->state_set);
 
8860
}
 
8861
 
 
8862
static void
 
8863
gtk_icon_view_item_accessible_class_init (AtkObjectClass *klass)
 
8864
{
 
8865
  GObjectClass *gobject_class;
 
8866
 
 
8867
  accessible_item_parent_class = g_type_class_peek_parent (klass);
 
8868
 
 
8869
  gobject_class = (GObjectClass *)klass;
 
8870
 
 
8871
  gobject_class->finalize = gtk_icon_view_item_accessible_finalize;
 
8872
 
 
8873
  klass->get_index_in_parent = gtk_icon_view_item_accessible_get_index_in_parent;
 
8874
  klass->get_parent = gtk_icon_view_item_accessible_get_parent;
 
8875
  klass->ref_state_set = gtk_icon_view_item_accessible_ref_state_set;
 
8876
}
 
8877
 
 
8878
static GType
 
8879
gtk_icon_view_item_accessible_get_type (void)
 
8880
{
 
8881
  static GType type = 0;
 
8882
 
 
8883
  if (!type)
 
8884
    {
 
8885
      const GTypeInfo tinfo =
 
8886
      {
 
8887
        sizeof (GtkIconViewItemAccessibleClass),
 
8888
        (GBaseInitFunc) NULL, /* base init */
 
8889
        (GBaseFinalizeFunc) NULL, /* base finalize */
 
8890
        (GClassInitFunc) gtk_icon_view_item_accessible_class_init, /* class init */
 
8891
        (GClassFinalizeFunc) NULL, /* class finalize */
 
8892
        NULL, /* class data */
 
8893
        sizeof (GtkIconViewItemAccessible), /* instance size */
 
8894
        0, /* nb preallocs */
 
8895
        (GInstanceInitFunc) gtk_icon_view_item_accessible_object_init, /* instance init */
 
8896
        NULL /* value table */
 
8897
      };
 
8898
 
 
8899
      const GInterfaceInfo atk_component_info =
 
8900
      {
 
8901
        (GInterfaceInitFunc) atk_component_item_interface_init,
 
8902
        (GInterfaceFinalizeFunc) NULL,
 
8903
        NULL
 
8904
      };
 
8905
      const GInterfaceInfo atk_action_info =
 
8906
      {
 
8907
        (GInterfaceInitFunc) atk_action_item_interface_init,
 
8908
        (GInterfaceFinalizeFunc) NULL,
 
8909
        NULL
 
8910
      };
 
8911
      const GInterfaceInfo atk_image_info =
 
8912
      {
 
8913
        (GInterfaceInitFunc) atk_image_item_interface_init,
 
8914
        (GInterfaceFinalizeFunc) NULL,
 
8915
        NULL
 
8916
      };
 
8917
      const GInterfaceInfo atk_text_info =
 
8918
      {
 
8919
        (GInterfaceInitFunc) atk_text_item_interface_init,
 
8920
        (GInterfaceFinalizeFunc) NULL,
 
8921
        NULL
 
8922
      };
 
8923
 
 
8924
      type = g_type_register_static (ATK_TYPE_OBJECT,
 
8925
                                     I_("GtkIconViewItemAccessible"), &tinfo, 0);
 
8926
      g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
 
8927
                                   &atk_component_info);
 
8928
      g_type_add_interface_static (type, ATK_TYPE_ACTION,
 
8929
                                   &atk_action_info);
 
8930
      g_type_add_interface_static (type, ATK_TYPE_IMAGE,
 
8931
                                   &atk_image_info);
 
8932
      g_type_add_interface_static (type, ATK_TYPE_TEXT,
 
8933
                                   &atk_text_info);
 
8934
    }
 
8935
 
 
8936
  return type;
 
8937
}
 
8938
 
 
8939
#define GTK_TYPE_ICON_VIEW_ACCESSIBLE      (gtk_icon_view_accessible_get_type ())
 
8940
#define GTK_ICON_VIEW_ACCESSIBLE(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE, GtkIconViewAccessible))
 
8941
#define GTK_IS_ICON_VIEW_ACCESSIBLE(obj)   (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_ICON_VIEW_ACCESSIBLE))
 
8942
 
 
8943
static GType gtk_icon_view_accessible_get_type (void);
 
8944
 
 
8945
typedef struct
 
8946
{
 
8947
   AtkObject parent;
 
8948
} GtkIconViewAccessible;
 
8949
 
 
8950
typedef struct
 
8951
{
 
8952
  AtkObject *item;
 
8953
  gint       index;
 
8954
} GtkIconViewItemAccessibleInfo;
 
8955
 
 
8956
typedef struct
 
8957
{
 
8958
  GList *items;
 
8959
 
 
8960
  GtkAdjustment *old_hadj;
 
8961
  GtkAdjustment *old_vadj;
 
8962
 
 
8963
  GtkTreeModel *model;
 
8964
 
 
8965
} GtkIconViewAccessiblePrivate;
 
8966
 
 
8967
static GtkIconViewAccessiblePrivate *
 
8968
gtk_icon_view_accessible_get_priv (AtkObject *accessible)
 
8969
{
 
8970
  return g_object_get_qdata (G_OBJECT (accessible),
 
8971
                             accessible_private_data_quark);
 
8972
}
 
8973
 
 
8974
static void
 
8975
gtk_icon_view_item_accessible_info_new (AtkObject *accessible,
 
8976
                                        AtkObject *item,
 
8977
                                        gint       index)
 
8978
{
 
8979
  GtkIconViewItemAccessibleInfo *info;
 
8980
  GtkIconViewItemAccessibleInfo *tmp_info;
 
8981
  GtkIconViewAccessiblePrivate *priv;
 
8982
  GList *items;
 
8983
 
 
8984
  info = g_new (GtkIconViewItemAccessibleInfo, 1);
 
8985
  info->item = item;
 
8986
  info->index = index;
 
8987
 
 
8988
  priv = gtk_icon_view_accessible_get_priv (accessible);
 
8989
  items = priv->items;
 
8990
  while (items)
 
8991
    {
 
8992
      tmp_info = items->data;
 
8993
      if (tmp_info->index > index)
 
8994
        break;
 
8995
      items = items->next;
 
8996
    }
 
8997
  priv->items = g_list_insert_before (priv->items, items, info);
 
8998
  priv->old_hadj = NULL;
 
8999
  priv->old_vadj = NULL;
 
9000
}
 
9001
 
 
9002
static gint
 
9003
gtk_icon_view_accessible_get_n_children (AtkObject *accessible)
 
9004
{
 
9005
  GtkIconView *icon_view;
 
9006
  GtkWidget *widget;
 
9007
 
 
9008
  widget = GTK_ACCESSIBLE (accessible)->widget;
 
9009
  if (!widget)
 
9010
      return 0;
 
9011
 
 
9012
  icon_view = GTK_ICON_VIEW (widget);
 
9013
 
 
9014
  return g_list_length (icon_view->priv->items);
 
9015
}
 
9016
 
 
9017
static AtkObject *
 
9018
gtk_icon_view_accessible_find_child (AtkObject *accessible,
 
9019
                                     gint       index)
 
9020
{
 
9021
  GtkIconViewAccessiblePrivate *priv;
 
9022
  GtkIconViewItemAccessibleInfo *info;
 
9023
  GList *items;
 
9024
 
 
9025
  priv = gtk_icon_view_accessible_get_priv (accessible);
 
9026
  items = priv->items;
 
9027
 
 
9028
  while (items)
 
9029
    {
 
9030
      info = items->data;
 
9031
      if (info->index == index)
 
9032
        return info->item;
 
9033
      items = items->next; 
 
9034
    }
 
9035
  return NULL;
 
9036
}
 
9037
 
 
9038
static AtkObject *
 
9039
gtk_icon_view_accessible_ref_child (AtkObject *accessible,
 
9040
                                    gint       index)
 
9041
{
 
9042
  GtkIconView *icon_view;
 
9043
  GtkWidget *widget;
 
9044
  GList *icons;
 
9045
  AtkObject *obj;
 
9046
  GtkIconViewItemAccessible *a11y_item;
 
9047
 
 
9048
  widget = GTK_ACCESSIBLE (accessible)->widget;
 
9049
  if (!widget)
 
9050
    return NULL;
 
9051
 
 
9052
  icon_view = GTK_ICON_VIEW (widget);
 
9053
  icons = g_list_nth (icon_view->priv->items, index);
 
9054
  obj = NULL;
 
9055
  if (icons)
 
9056
    {
 
9057
      GtkIconViewItem *item = icons->data;
 
9058
   
 
9059
      g_return_val_if_fail (item->index == index, NULL);
 
9060
      obj = gtk_icon_view_accessible_find_child (accessible, index);
 
9061
      if (!obj)
 
9062
        {
 
9063
          gchar *text;
 
9064
 
 
9065
          obj = g_object_new (gtk_icon_view_item_accessible_get_type (), NULL);
 
9066
          gtk_icon_view_item_accessible_info_new (accessible,
 
9067
                                                  obj,
 
9068
                                                  index);
 
9069
          obj->role = ATK_ROLE_ICON;
 
9070
          a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (obj);
 
9071
          a11y_item->item = item;
 
9072
          a11y_item->widget = widget;
 
9073
          a11y_item->text_buffer = gtk_text_buffer_new (NULL);
 
9074
 
 
9075
          gtk_icon_view_set_cell_data (icon_view, item);
 
9076
          text = get_text (icon_view, item);
 
9077
          if (text)
 
9078
            {
 
9079
              gtk_text_buffer_set_text (a11y_item->text_buffer, text, -1);
 
9080
              g_free (text);
 
9081
            } 
 
9082
 
 
9083
          gtk_icon_view_item_accessible_set_visibility (a11y_item, FALSE);
 
9084
          g_object_add_weak_pointer (G_OBJECT (widget), (gpointer) &(a11y_item->widget));
 
9085
       }
 
9086
      g_object_ref (obj);
 
9087
    }
 
9088
  return obj;
 
9089
}
 
9090
 
 
9091
static void
 
9092
gtk_icon_view_accessible_traverse_items (GtkIconViewAccessible *view,
 
9093
                                         GList                 *list)
 
9094
{
 
9095
  GtkIconViewAccessiblePrivate *priv;
 
9096
  GtkIconViewItemAccessibleInfo *info;
 
9097
  GtkIconViewItemAccessible *item;
 
9098
  GList *items;
 
9099
  
 
9100
  priv =  gtk_icon_view_accessible_get_priv (ATK_OBJECT (view));
 
9101
  if (priv->items)
 
9102
    {
 
9103
      GtkWidget *widget;
 
9104
      gboolean act_on_item;
 
9105
 
 
9106
      widget = GTK_ACCESSIBLE (view)->widget;
 
9107
      if (widget == NULL)
 
9108
        return;
 
9109
 
 
9110
      items = priv->items;
 
9111
 
 
9112
      act_on_item = (list == NULL);
 
9113
 
 
9114
      while (items)
 
9115
        {
 
9116
 
 
9117
          info = (GtkIconViewItemAccessibleInfo *)items->data;
 
9118
          item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
 
9119
 
 
9120
          if (act_on_item == FALSE && list == items)
 
9121
            act_on_item = TRUE;
 
9122
 
 
9123
          if (act_on_item)
 
9124
            gtk_icon_view_item_accessible_set_visibility (item, TRUE);
 
9125
 
 
9126
          items = items->next;
 
9127
       }
 
9128
   }
 
9129
}
 
9130
 
 
9131
static void
 
9132
gtk_icon_view_accessible_adjustment_changed (GtkAdjustment *adjustment,
 
9133
                                             GtkIconView   *icon_view)
 
9134
{
 
9135
  AtkObject *obj;
 
9136
  GtkIconViewAccessible *view;
 
9137
 
 
9138
  /*
 
9139
   * The scrollbars have changed
 
9140
   */
 
9141
  obj = gtk_widget_get_accessible (GTK_WIDGET (icon_view));
 
9142
  view = GTK_ICON_VIEW_ACCESSIBLE (obj);
 
9143
 
 
9144
  gtk_icon_view_accessible_traverse_items (view, NULL);
 
9145
}
 
9146
 
 
9147
static void
 
9148
gtk_icon_view_accessible_set_scroll_adjustments (GtkWidget      *widget,
 
9149
                                                 GtkAdjustment *hadj,
 
9150
                                                 GtkAdjustment *vadj)
 
9151
{
 
9152
  AtkObject *atk_obj;
 
9153
  GtkIconViewAccessiblePrivate *priv;
 
9154
 
 
9155
  atk_obj = gtk_widget_get_accessible (widget);
 
9156
  priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9157
 
 
9158
  if (priv->old_hadj != hadj)
 
9159
    {
 
9160
      if (priv->old_hadj)
 
9161
        {
 
9162
          g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj),
 
9163
                                        (gpointer *)&priv->old_hadj);
 
9164
          
 
9165
          g_signal_handlers_disconnect_by_func (priv->old_hadj,
 
9166
                                                (gpointer) gtk_icon_view_accessible_adjustment_changed,
 
9167
                                                widget);
 
9168
        }
 
9169
      priv->old_hadj = hadj;
 
9170
      if (priv->old_hadj)
 
9171
        {
 
9172
          g_object_add_weak_pointer (G_OBJECT (priv->old_hadj),
 
9173
                                     (gpointer *)&priv->old_hadj);
 
9174
          g_signal_connect (hadj,
 
9175
                            "value-changed",
 
9176
                            G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
 
9177
                            widget);
 
9178
        }
 
9179
    }
 
9180
  if (priv->old_vadj != vadj)
 
9181
    {
 
9182
      if (priv->old_vadj)
 
9183
        {
 
9184
          g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj),
 
9185
                                        (gpointer *)&priv->old_vadj);
 
9186
          
 
9187
          g_signal_handlers_disconnect_by_func (priv->old_vadj,
 
9188
                                                (gpointer) gtk_icon_view_accessible_adjustment_changed,
 
9189
                                                widget);
 
9190
        }
 
9191
      priv->old_vadj = vadj;
 
9192
      if (priv->old_vadj)
 
9193
        {
 
9194
          g_object_add_weak_pointer (G_OBJECT (priv->old_vadj),
 
9195
                                     (gpointer *)&priv->old_vadj);
 
9196
          g_signal_connect (vadj,
 
9197
                            "value-changed",
 
9198
                            G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
 
9199
                            widget);
 
9200
        }
 
9201
    }
 
9202
}
 
9203
 
 
9204
static void
 
9205
gtk_icon_view_accessible_model_row_changed (GtkTreeModel *tree_model,
 
9206
                                            GtkTreePath  *path,
 
9207
                                            GtkTreeIter  *iter,
 
9208
                                            gpointer      user_data)
 
9209
{
 
9210
  AtkObject *atk_obj;
 
9211
  gint index;
 
9212
  GtkWidget *widget;
 
9213
  GtkIconView *icon_view;
 
9214
  GtkIconViewItem *item;
 
9215
  GtkIconViewAccessible *a11y_view;
 
9216
  GtkIconViewItemAccessible *a11y_item;
 
9217
  const gchar *name;
 
9218
  gchar *text;
 
9219
 
 
9220
  atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
 
9221
  a11y_view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
 
9222
  index = gtk_tree_path_get_indices(path)[0];
 
9223
  a11y_item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (
 
9224
      gtk_icon_view_accessible_find_child (atk_obj, index));
 
9225
 
 
9226
  if (a11y_item)
 
9227
    {
 
9228
      widget = GTK_ACCESSIBLE (atk_obj)->widget;
 
9229
      icon_view = GTK_ICON_VIEW (widget);
 
9230
      item = a11y_item->item;
 
9231
 
 
9232
      name = atk_object_get_name (ATK_OBJECT (a11y_item));
 
9233
 
 
9234
      if (!name || strcmp (name, "") == 0)
 
9235
        {
 
9236
          gtk_icon_view_set_cell_data (icon_view, item);
 
9237
          text = get_text (icon_view, item);
 
9238
          if (text)
 
9239
            {
 
9240
              gtk_text_buffer_set_text (a11y_item->text_buffer, text, -1);
 
9241
              g_free (text);
 
9242
            }
 
9243
        }
 
9244
    }
 
9245
 
 
9246
  g_signal_emit_by_name (atk_obj, "visible-data-changed");
 
9247
 
 
9248
  return;
 
9249
}
 
9250
 
 
9251
static void
 
9252
gtk_icon_view_accessible_model_row_inserted (GtkTreeModel *tree_model,
 
9253
                                             GtkTreePath  *path,
 
9254
                                             GtkTreeIter  *iter,
 
9255
                                             gpointer     user_data)
 
9256
{
 
9257
  GtkIconViewAccessiblePrivate *priv;
 
9258
  GtkIconViewItemAccessibleInfo *info;
 
9259
  GtkIconViewAccessible *view;
 
9260
  GtkIconViewItemAccessible *item;
 
9261
  GList *items;
 
9262
  GList *tmp_list;
 
9263
  AtkObject *atk_obj;
 
9264
  gint index;
 
9265
 
 
9266
  index = gtk_tree_path_get_indices(path)[0];
 
9267
  atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
 
9268
  view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
 
9269
  priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9270
 
 
9271
  items = priv->items;
 
9272
  tmp_list = NULL;
 
9273
  while (items)
 
9274
    {
 
9275
      info = items->data;
 
9276
      item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
 
9277
      if (info->index != item->item->index)
 
9278
        {
 
9279
          if (info->index < index)
 
9280
            g_warning ("Unexpected index value on insertion %d %d", index, info->index);
 
9281
 
 
9282
          if (tmp_list == NULL)
 
9283
            tmp_list = items;
 
9284
   
 
9285
          info->index = item->item->index;
 
9286
        }
 
9287
 
 
9288
      items = items->next;
 
9289
    }
 
9290
  gtk_icon_view_accessible_traverse_items (view, tmp_list);
 
9291
  g_signal_emit_by_name (atk_obj, "children-changed::add",
 
9292
                         index, NULL, NULL);
 
9293
  return;
 
9294
}
 
9295
 
 
9296
static void
 
9297
gtk_icon_view_accessible_model_row_deleted (GtkTreeModel *tree_model,
 
9298
                                            GtkTreePath  *path,
 
9299
                                            gpointer     user_data)
 
9300
{
 
9301
  GtkIconViewAccessiblePrivate *priv;
 
9302
  GtkIconViewItemAccessibleInfo *info;
 
9303
  GtkIconViewAccessible *view;
 
9304
  GtkIconViewItemAccessible *item;
 
9305
  GList *items;
 
9306
  GList *tmp_list;
 
9307
  GList *deleted_item;
 
9308
  AtkObject *atk_obj;
 
9309
  gint index;
 
9310
 
 
9311
  index = gtk_tree_path_get_indices(path)[0];
 
9312
  atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
 
9313
  view = GTK_ICON_VIEW_ACCESSIBLE (atk_obj);
 
9314
  priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9315
 
 
9316
  items = priv->items;
 
9317
  tmp_list = NULL;
 
9318
  deleted_item = NULL;
 
9319
  info = NULL;
 
9320
  while (items)
 
9321
    {
 
9322
      info = items->data;
 
9323
      item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
 
9324
      if (info->index == index)
 
9325
        {
 
9326
          deleted_item = items;
 
9327
        }
 
9328
      if (info->index != item->item->index)
 
9329
        {
 
9330
          if (tmp_list == NULL)
 
9331
            tmp_list = items;
 
9332
            
 
9333
          info->index = item->item->index;
 
9334
        }
 
9335
 
 
9336
      items = items->next;
 
9337
    }
 
9338
  gtk_icon_view_accessible_traverse_items (view, tmp_list);
 
9339
  if (deleted_item)
 
9340
    {
 
9341
      info = deleted_item->data;
 
9342
      gtk_icon_view_item_accessible_add_state (GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item), ATK_STATE_DEFUNCT, TRUE);
 
9343
      g_signal_emit_by_name (atk_obj, "children-changed::remove",
 
9344
                             index, NULL, NULL);
 
9345
      priv->items = g_list_remove_link (priv->items, deleted_item);
 
9346
      g_free (info);
 
9347
    }
 
9348
 
 
9349
  return;
 
9350
}
 
9351
 
 
9352
static gint
 
9353
gtk_icon_view_accessible_item_compare (GtkIconViewItemAccessibleInfo *i1,
 
9354
                                       GtkIconViewItemAccessibleInfo *i2)
 
9355
{
 
9356
  return i1->index - i2->index;
 
9357
}
 
9358
 
 
9359
static void
 
9360
gtk_icon_view_accessible_model_rows_reordered (GtkTreeModel *tree_model,
 
9361
                                               GtkTreePath  *path,
 
9362
                                               GtkTreeIter  *iter,
 
9363
                                               gint         *new_order,
 
9364
                                               gpointer     user_data)
 
9365
{
 
9366
  GtkIconViewAccessiblePrivate *priv;
 
9367
  GtkIconViewItemAccessibleInfo *info;
 
9368
  GtkIconView *icon_view;
 
9369
  GtkIconViewItemAccessible *item;
 
9370
  GList *items;
 
9371
  AtkObject *atk_obj;
 
9372
  gint *order;
 
9373
  gint length, i;
 
9374
 
 
9375
  atk_obj = gtk_widget_get_accessible (GTK_WIDGET (user_data));
 
9376
  icon_view = GTK_ICON_VIEW (user_data);
 
9377
  priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9378
 
 
9379
  length = gtk_tree_model_iter_n_children (tree_model, NULL);
 
9380
 
 
9381
  order = g_new (gint, length);
 
9382
  for (i = 0; i < length; i++)
 
9383
    order [new_order[i]] = i;
 
9384
 
 
9385
  items = priv->items;
 
9386
  while (items)
 
9387
    {
 
9388
      info = items->data;
 
9389
      item = GTK_ICON_VIEW_ITEM_ACCESSIBLE (info->item);
 
9390
      info->index = order[info->index];
 
9391
      item->item = g_list_nth_data (icon_view->priv->items, info->index);
 
9392
      items = items->next;
 
9393
    }
 
9394
  g_free (order);
 
9395
  priv->items = g_list_sort (priv->items, 
 
9396
                             (GCompareFunc)gtk_icon_view_accessible_item_compare);
 
9397
 
 
9398
  return;
 
9399
}
 
9400
 
 
9401
static void
 
9402
gtk_icon_view_accessible_disconnect_model_signals (GtkTreeModel *model,
 
9403
                                                   GtkWidget *widget)
 
9404
{
 
9405
  GObject *obj;
 
9406
 
 
9407
  obj = G_OBJECT (model);
 
9408
  g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_changed, widget);
 
9409
  g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_inserted, widget);
 
9410
  g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_row_deleted, widget);
 
9411
  g_signal_handlers_disconnect_by_func (obj, (gpointer) gtk_icon_view_accessible_model_rows_reordered, widget);
 
9412
}
 
9413
 
 
9414
static void
 
9415
gtk_icon_view_accessible_connect_model_signals (GtkIconView *icon_view)
 
9416
{
 
9417
  GObject *obj;
 
9418
 
 
9419
  obj = G_OBJECT (icon_view->priv->model);
 
9420
  g_signal_connect_data (obj, "row-changed",
 
9421
                         (GCallback) gtk_icon_view_accessible_model_row_changed,
 
9422
                         icon_view, NULL, 0);
 
9423
  g_signal_connect_data (obj, "row-inserted",
 
9424
                         (GCallback) gtk_icon_view_accessible_model_row_inserted, 
 
9425
                         icon_view, NULL, G_CONNECT_AFTER);
 
9426
  g_signal_connect_data (obj, "row-deleted",
 
9427
                         (GCallback) gtk_icon_view_accessible_model_row_deleted, 
 
9428
                         icon_view, NULL, G_CONNECT_AFTER);
 
9429
  g_signal_connect_data (obj, "rows-reordered",
 
9430
                         (GCallback) gtk_icon_view_accessible_model_rows_reordered, 
 
9431
                         icon_view, NULL, G_CONNECT_AFTER);
 
9432
}
 
9433
 
 
9434
static void
 
9435
gtk_icon_view_accessible_clear_cache (GtkIconViewAccessiblePrivate *priv)
 
9436
{
 
9437
  GtkIconViewItemAccessibleInfo *info;
 
9438
  GList *items;
 
9439
 
 
9440
  items = priv->items;
 
9441
  while (items)
 
9442
    {
 
9443
      info = (GtkIconViewItemAccessibleInfo *) items->data;
 
9444
      g_object_unref (info->item);
 
9445
      g_free (items->data);
 
9446
      items = items->next;
 
9447
    }
 
9448
  g_list_free (priv->items);
 
9449
  priv->items = NULL;
 
9450
}
 
9451
 
 
9452
static void
 
9453
gtk_icon_view_accessible_notify_gtk (GObject *obj,
 
9454
                                     GParamSpec *pspec)
 
9455
{
 
9456
  GtkIconView *icon_view;
 
9457
  GtkWidget *widget;
 
9458
  AtkObject *atk_obj;
 
9459
  GtkIconViewAccessiblePrivate *priv;
 
9460
 
 
9461
  if (strcmp (pspec->name, "model") == 0)
 
9462
    {
 
9463
      widget = GTK_WIDGET (obj); 
 
9464
      atk_obj = gtk_widget_get_accessible (widget);
 
9465
      priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9466
      if (priv->model)
 
9467
        {
 
9468
          g_object_remove_weak_pointer (G_OBJECT (priv->model),
 
9469
                                        (gpointer *)&priv->model);
 
9470
          gtk_icon_view_accessible_disconnect_model_signals (priv->model, widget);
 
9471
        }
 
9472
      gtk_icon_view_accessible_clear_cache (priv);
 
9473
 
 
9474
      icon_view = GTK_ICON_VIEW (obj);
 
9475
      priv->model = icon_view->priv->model;
 
9476
      /* If there is no model the GtkIconView is probably being destroyed */
 
9477
      if (priv->model)
 
9478
        {
 
9479
          g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
 
9480
          gtk_icon_view_accessible_connect_model_signals (icon_view);
 
9481
        }
 
9482
    }
 
9483
 
 
9484
  return;
 
9485
}
 
9486
 
 
9487
static void
 
9488
gtk_icon_view_accessible_initialize (AtkObject *accessible,
 
9489
                                     gpointer   data)
 
9490
{
 
9491
  GtkIconViewAccessiblePrivate *priv;
 
9492
  GtkIconView *icon_view;
 
9493
 
 
9494
  if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize)
 
9495
    ATK_OBJECT_CLASS (accessible_parent_class)->initialize (accessible, data);
 
9496
 
 
9497
  priv = g_new0 (GtkIconViewAccessiblePrivate, 1);
 
9498
  g_object_set_qdata (G_OBJECT (accessible),
 
9499
                      accessible_private_data_quark,
 
9500
                      priv);
 
9501
 
 
9502
  icon_view = GTK_ICON_VIEW (data);
 
9503
  if (icon_view->priv->hadjustment)
 
9504
    {
 
9505
      priv->old_hadj = icon_view->priv->hadjustment;
 
9506
      g_object_add_weak_pointer (G_OBJECT (priv->old_hadj), (gpointer *)&priv->old_hadj);
 
9507
      g_signal_connect (icon_view->priv->hadjustment,
 
9508
                        "value-changed",
 
9509
                        G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
 
9510
                        icon_view);
 
9511
    } 
 
9512
  if (icon_view->priv->vadjustment)
 
9513
    {
 
9514
      priv->old_vadj = icon_view->priv->vadjustment;
 
9515
      g_object_add_weak_pointer (G_OBJECT (priv->old_vadj), (gpointer *)&priv->old_vadj);
 
9516
      g_signal_connect (icon_view->priv->vadjustment,
 
9517
                        "value-changed",
 
9518
                        G_CALLBACK (gtk_icon_view_accessible_adjustment_changed),
 
9519
                        icon_view);
 
9520
    }
 
9521
  g_signal_connect_after (data,
 
9522
                          "set-scroll-adjustments",
 
9523
                          G_CALLBACK (gtk_icon_view_accessible_set_scroll_adjustments),
 
9524
                          NULL);
 
9525
  g_signal_connect (data,
 
9526
                    "notify",
 
9527
                    G_CALLBACK (gtk_icon_view_accessible_notify_gtk),
 
9528
                    NULL);
 
9529
 
 
9530
  priv->model = icon_view->priv->model;
 
9531
  if (priv->model)
 
9532
    {
 
9533
      g_object_add_weak_pointer (G_OBJECT (priv->model), (gpointer *)&priv->model);
 
9534
      gtk_icon_view_accessible_connect_model_signals (icon_view);
 
9535
    }
 
9536
                          
 
9537
  accessible->role = ATK_ROLE_LAYERED_PANE;
 
9538
}
 
9539
 
 
9540
static void
 
9541
gtk_icon_view_accessible_finalize (GObject *object)
 
9542
{
 
9543
  GtkIconViewAccessiblePrivate *priv;
 
9544
 
 
9545
  priv = gtk_icon_view_accessible_get_priv (ATK_OBJECT (object));
 
9546
  gtk_icon_view_accessible_clear_cache (priv);
 
9547
 
 
9548
  g_free (priv);
 
9549
 
 
9550
  G_OBJECT_CLASS (accessible_parent_class)->finalize (object);
 
9551
}
 
9552
 
 
9553
static void
 
9554
gtk_icon_view_accessible_destroyed (GtkWidget *widget,
 
9555
                                    GtkAccessible *accessible)
 
9556
{
 
9557
  AtkObject *atk_obj;
 
9558
  GtkIconViewAccessiblePrivate *priv;
 
9559
 
 
9560
  atk_obj = ATK_OBJECT (accessible);
 
9561
  priv = gtk_icon_view_accessible_get_priv (atk_obj);
 
9562
  if (priv->old_hadj)
 
9563
    {
 
9564
      g_object_remove_weak_pointer (G_OBJECT (priv->old_hadj),
 
9565
                                    (gpointer *)&priv->old_hadj);
 
9566
          
 
9567
      g_signal_handlers_disconnect_by_func (priv->old_hadj,
 
9568
                                            (gpointer) gtk_icon_view_accessible_adjustment_changed,
 
9569
                                            widget);
 
9570
      priv->old_hadj = NULL;
 
9571
    }
 
9572
  if (priv->old_vadj)
 
9573
    {
 
9574
      g_object_remove_weak_pointer (G_OBJECT (priv->old_vadj),
 
9575
                                    (gpointer *)&priv->old_vadj);
 
9576
          
 
9577
      g_signal_handlers_disconnect_by_func (priv->old_vadj,
 
9578
                                            (gpointer) gtk_icon_view_accessible_adjustment_changed,
 
9579
                                            widget);
 
9580
      priv->old_vadj = NULL;
 
9581
    }
 
9582
}
 
9583
 
 
9584
static void
 
9585
gtk_icon_view_accessible_connect_widget_destroyed (GtkAccessible *accessible)
 
9586
{
 
9587
  if (accessible->widget)
 
9588
    {
 
9589
      g_signal_connect_after (accessible->widget,
 
9590
                              "destroy",
 
9591
                              G_CALLBACK (gtk_icon_view_accessible_destroyed),
 
9592
                              accessible);
 
9593
    }
 
9594
  GTK_ACCESSIBLE_CLASS (accessible_parent_class)->connect_widget_destroyed (accessible);
 
9595
}
 
9596
 
 
9597
static void
 
9598
gtk_icon_view_accessible_class_init (AtkObjectClass *klass)
 
9599
{
 
9600
  GObjectClass *gobject_class;
 
9601
  GtkAccessibleClass *accessible_class;
 
9602
 
 
9603
  accessible_parent_class = g_type_class_peek_parent (klass);
 
9604
 
 
9605
  gobject_class = (GObjectClass *)klass;
 
9606
  accessible_class = (GtkAccessibleClass *)klass;
 
9607
 
 
9608
  gobject_class->finalize = gtk_icon_view_accessible_finalize;
 
9609
 
 
9610
  klass->get_n_children = gtk_icon_view_accessible_get_n_children;
 
9611
  klass->ref_child = gtk_icon_view_accessible_ref_child;
 
9612
  klass->initialize = gtk_icon_view_accessible_initialize;
 
9613
 
 
9614
  accessible_class->connect_widget_destroyed = gtk_icon_view_accessible_connect_widget_destroyed;
 
9615
 
 
9616
  accessible_private_data_quark = g_quark_from_static_string ("icon_view-accessible-private-data");
 
9617
}
 
9618
 
 
9619
static AtkObject*
 
9620
gtk_icon_view_accessible_ref_accessible_at_point (AtkComponent *component,
 
9621
                                                  gint          x,
 
9622
                                                  gint          y,
 
9623
                                                  AtkCoordType  coord_type)
 
9624
{
 
9625
  GtkWidget *widget;
 
9626
  GtkIconView *icon_view;
 
9627
  GtkIconViewItem *item;
 
9628
  gint x_pos, y_pos;
 
9629
 
 
9630
  widget = GTK_ACCESSIBLE (component)->widget;
 
9631
  if (widget == NULL)
 
9632
  /* State is defunct */
 
9633
    return NULL;
 
9634
 
 
9635
  icon_view = GTK_ICON_VIEW (widget);
 
9636
  atk_component_get_extents (component, &x_pos, &y_pos, NULL, NULL, coord_type);
 
9637
  item = gtk_icon_view_get_item_at_coords (icon_view, x - x_pos, y - y_pos, TRUE, NULL);
 
9638
  if (item)
 
9639
    return gtk_icon_view_accessible_ref_child (ATK_OBJECT (component), item->index);
 
9640
 
 
9641
  return NULL;
 
9642
}
 
9643
 
 
9644
static void
 
9645
atk_component_interface_init (AtkComponentIface *iface)
 
9646
{
 
9647
  iface->ref_accessible_at_point = gtk_icon_view_accessible_ref_accessible_at_point;
 
9648
}
 
9649
 
 
9650
static gboolean
 
9651
gtk_icon_view_accessible_add_selection (AtkSelection *selection,
 
9652
                                        gint i)
 
9653
{
 
9654
  GtkWidget *widget;
 
9655
  GtkIconView *icon_view;
 
9656
  GtkIconViewItem *item;
 
9657
 
 
9658
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9659
  if (widget == NULL)
 
9660
    return FALSE;
 
9661
 
 
9662
  icon_view = GTK_ICON_VIEW (widget);
 
9663
 
 
9664
  item = g_list_nth_data (icon_view->priv->items, i);
 
9665
 
 
9666
  if (!item)
 
9667
    return FALSE;
 
9668
 
 
9669
  gtk_icon_view_select_item (icon_view, item);
 
9670
 
 
9671
  return TRUE;
 
9672
}
 
9673
 
 
9674
static gboolean
 
9675
gtk_icon_view_accessible_clear_selection (AtkSelection *selection)
 
9676
{
 
9677
  GtkWidget *widget;
 
9678
  GtkIconView *icon_view;
 
9679
 
 
9680
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9681
  if (widget == NULL)
 
9682
    return FALSE;
 
9683
 
 
9684
  icon_view = GTK_ICON_VIEW (widget);
 
9685
  gtk_icon_view_unselect_all (icon_view);
 
9686
 
 
9687
  return TRUE;
 
9688
}
 
9689
 
 
9690
static AtkObject*
 
9691
gtk_icon_view_accessible_ref_selection (AtkSelection *selection,
 
9692
                                        gint          i)
 
9693
{
 
9694
  GList *l;
 
9695
  GtkWidget *widget;
 
9696
  GtkIconView *icon_view;
 
9697
  GtkIconViewItem *item;
 
9698
 
 
9699
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9700
  if (widget == NULL)
 
9701
    return NULL;
 
9702
 
 
9703
  icon_view = GTK_ICON_VIEW (widget);
 
9704
 
 
9705
  l = icon_view->priv->items;
 
9706
  while (l)
 
9707
    {
 
9708
      item = l->data;
 
9709
      if (item->selected)
 
9710
        {
 
9711
          if (i == 0)
 
9712
            return atk_object_ref_accessible_child (gtk_widget_get_accessible (widget), item->index);
 
9713
          else
 
9714
            i--;
 
9715
        }
 
9716
      l = l->next;
 
9717
    }
 
9718
 
 
9719
  return NULL;
 
9720
}
 
9721
 
 
9722
static gint
 
9723
gtk_icon_view_accessible_get_selection_count (AtkSelection *selection)
 
9724
{
 
9725
  GtkWidget *widget;
 
9726
  GtkIconView *icon_view;
 
9727
  GtkIconViewItem *item;
 
9728
  GList *l;
 
9729
  gint count;
 
9730
 
 
9731
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9732
  if (widget == NULL)
 
9733
    return 0;
 
9734
 
 
9735
  icon_view = GTK_ICON_VIEW (widget);
 
9736
 
 
9737
  l = icon_view->priv->items;
 
9738
  count = 0;
 
9739
  while (l)
 
9740
    {
 
9741
      item = l->data;
 
9742
 
 
9743
      if (item->selected)
 
9744
        count++;
 
9745
 
 
9746
      l = l->next;
 
9747
    }
 
9748
 
 
9749
  return count;
 
9750
}
 
9751
 
 
9752
static gboolean
 
9753
gtk_icon_view_accessible_is_child_selected (AtkSelection *selection,
 
9754
                                            gint          i)
 
9755
{
 
9756
  GtkWidget *widget;
 
9757
  GtkIconView *icon_view;
 
9758
  GtkIconViewItem *item;
 
9759
 
 
9760
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9761
  if (widget == NULL)
 
9762
    return FALSE;
 
9763
 
 
9764
  icon_view = GTK_ICON_VIEW (widget);
 
9765
 
 
9766
  item = g_list_nth_data (icon_view->priv->items, i);
 
9767
  if (!item)
 
9768
    return FALSE;
 
9769
 
 
9770
  return item->selected;
 
9771
}
 
9772
 
 
9773
static gboolean
 
9774
gtk_icon_view_accessible_remove_selection (AtkSelection *selection,
 
9775
                                           gint          i)
 
9776
{
 
9777
  GtkWidget *widget;
 
9778
  GtkIconView *icon_view;
 
9779
  GtkIconViewItem *item;
 
9780
  GList *l;
 
9781
  gint count;
 
9782
 
 
9783
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9784
  if (widget == NULL)
 
9785
    return FALSE;
 
9786
 
 
9787
  icon_view = GTK_ICON_VIEW (widget);
 
9788
  l = icon_view->priv->items;
 
9789
  count = 0;
 
9790
  while (l)
 
9791
    {
 
9792
      item = l->data;
 
9793
      if (item->selected)
 
9794
        {
 
9795
          if (count == i)
 
9796
            {
 
9797
              gtk_icon_view_unselect_item (icon_view, item);
 
9798
              return TRUE;
 
9799
            }
 
9800
          count++;
 
9801
        }
 
9802
      l = l->next;
 
9803
    }
 
9804
 
 
9805
  return FALSE;
 
9806
}
 
9807
 
 
9808
static gboolean
 
9809
gtk_icon_view_accessible_select_all_selection (AtkSelection *selection)
 
9810
{
 
9811
  GtkWidget *widget;
 
9812
  GtkIconView *icon_view;
 
9813
 
 
9814
  widget = GTK_ACCESSIBLE (selection)->widget;
 
9815
  if (widget == NULL)
 
9816
    return FALSE;
 
9817
 
 
9818
  icon_view = GTK_ICON_VIEW (widget);
 
9819
  gtk_icon_view_select_all (icon_view);
 
9820
  return TRUE;
 
9821
}
 
9822
 
 
9823
static void
 
9824
gtk_icon_view_accessible_selection_interface_init (AtkSelectionIface *iface)
 
9825
{
 
9826
  iface->add_selection = gtk_icon_view_accessible_add_selection;
 
9827
  iface->clear_selection = gtk_icon_view_accessible_clear_selection;
 
9828
  iface->ref_selection = gtk_icon_view_accessible_ref_selection;
 
9829
  iface->get_selection_count = gtk_icon_view_accessible_get_selection_count;
 
9830
  iface->is_child_selected = gtk_icon_view_accessible_is_child_selected;
 
9831
  iface->remove_selection = gtk_icon_view_accessible_remove_selection;
 
9832
  iface->select_all_selection = gtk_icon_view_accessible_select_all_selection;
 
9833
}
 
9834
 
 
9835
static GType
 
9836
gtk_icon_view_accessible_get_type (void)
 
9837
{
 
9838
  static GType type = 0;
 
9839
 
 
9840
  if (!type)
 
9841
    {
 
9842
      GTypeInfo tinfo =
 
9843
      {
 
9844
        0, /* class size */
 
9845
        (GBaseInitFunc) NULL, /* base init */
 
9846
        (GBaseFinalizeFunc) NULL, /* base finalize */
 
9847
        (GClassInitFunc) gtk_icon_view_accessible_class_init,
 
9848
        (GClassFinalizeFunc) NULL, /* class finalize */
 
9849
        NULL, /* class data */
 
9850
        0, /* instance size */
 
9851
        0, /* nb preallocs */
 
9852
        (GInstanceInitFunc) NULL, /* instance init */
 
9853
        NULL /* value table */
 
9854
      };
 
9855
      const GInterfaceInfo atk_component_info =
 
9856
      {
 
9857
        (GInterfaceInitFunc) atk_component_interface_init,
 
9858
        (GInterfaceFinalizeFunc) NULL,
 
9859
        NULL
 
9860
      };
 
9861
      const GInterfaceInfo atk_selection_info =
 
9862
      {
 
9863
        (GInterfaceInitFunc) gtk_icon_view_accessible_selection_interface_init,
 
9864
        (GInterfaceFinalizeFunc) NULL,
 
9865
        NULL
 
9866
      };
 
9867
 
 
9868
      /*
 
9869
       * Figure out the size of the class and instance
 
9870
       * we are deriving from
 
9871
       */
 
9872
      AtkObjectFactory *factory;
 
9873
      GType derived_type;
 
9874
      GTypeQuery query;
 
9875
      GType derived_atk_type;
 
9876
 
 
9877
      derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
 
9878
      factory = atk_registry_get_factory (atk_get_default_registry (), 
 
9879
                                          derived_type);
 
9880
      derived_atk_type = atk_object_factory_get_accessible_type (factory);
 
9881
      g_type_query (derived_atk_type, &query);
 
9882
      tinfo.class_size = query.class_size;
 
9883
      tinfo.instance_size = query.instance_size;
 
9884
 
 
9885
      type = g_type_register_static (derived_atk_type, 
 
9886
                                     I_("GtkIconViewAccessible"), 
 
9887
                                     &tinfo, 0);
 
9888
      g_type_add_interface_static (type, ATK_TYPE_COMPONENT,
 
9889
                                   &atk_component_info);
 
9890
      g_type_add_interface_static (type, ATK_TYPE_SELECTION,
 
9891
                                   &atk_selection_info);
 
9892
    }
 
9893
  return type;
 
9894
}
 
9895
 
 
9896
static AtkObject *
 
9897
gtk_icon_view_accessible_new (GObject *obj)
 
9898
{
 
9899
  AtkObject *accessible;
 
9900
 
 
9901
  g_return_val_if_fail (GTK_IS_WIDGET (obj), NULL);
 
9902
 
 
9903
  accessible = g_object_new (gtk_icon_view_accessible_get_type (), NULL);
 
9904
  atk_object_initialize (accessible, obj);
 
9905
 
 
9906
  return accessible;
 
9907
}
 
9908
 
 
9909
static GType
 
9910
gtk_icon_view_accessible_factory_get_accessible_type (void)
 
9911
{
 
9912
  return gtk_icon_view_accessible_get_type ();
 
9913
}
 
9914
 
 
9915
static AtkObject*
 
9916
gtk_icon_view_accessible_factory_create_accessible (GObject *obj)
 
9917
{
 
9918
  return gtk_icon_view_accessible_new (obj);
 
9919
}
 
9920
 
 
9921
static void
 
9922
gtk_icon_view_accessible_factory_class_init (AtkObjectFactoryClass *klass)
 
9923
{
 
9924
  klass->create_accessible = gtk_icon_view_accessible_factory_create_accessible;
 
9925
  klass->get_accessible_type = gtk_icon_view_accessible_factory_get_accessible_type;
 
9926
}
 
9927
 
 
9928
static GType
 
9929
gtk_icon_view_accessible_factory_get_type (void)
 
9930
{
 
9931
  static GType type = 0;
 
9932
 
 
9933
  if (!type)
 
9934
    {
 
9935
      const GTypeInfo tinfo =
 
9936
      {
 
9937
        sizeof (AtkObjectFactoryClass),
 
9938
        NULL,           /* base_init */
 
9939
        NULL,           /* base_finalize */
 
9940
        (GClassInitFunc) gtk_icon_view_accessible_factory_class_init,
 
9941
        NULL,           /* class_finalize */
 
9942
        NULL,           /* class_data */
 
9943
        sizeof (AtkObjectFactory),
 
9944
        0,             /* n_preallocs */
 
9945
        NULL, NULL
 
9946
      };
 
9947
 
 
9948
      type = g_type_register_static (ATK_TYPE_OBJECT_FACTORY, 
 
9949
                                    I_("GtkIconViewAccessibleFactory"),
 
9950
                                    &tinfo, 0);
 
9951
    }
 
9952
  return type;
 
9953
}
 
9954
 
 
9955
 
 
9956
static AtkObject *
 
9957
gtk_icon_view_get_accessible (GtkWidget *widget)
 
9958
{
 
9959
  static gboolean first_time = TRUE;
 
9960
 
 
9961
  if (first_time)
 
9962
    {
 
9963
      AtkObjectFactory *factory;
 
9964
      AtkRegistry *registry;
 
9965
      GType derived_type; 
 
9966
      GType derived_atk_type; 
 
9967
 
 
9968
      /*
 
9969
       * Figure out whether accessibility is enabled by looking at the
 
9970
       * type of the accessible object which would be created for
 
9971
       * the parent type of GtkIconView.
 
9972
       */
 
9973
      derived_type = g_type_parent (GTK_TYPE_ICON_VIEW);
 
9974
 
 
9975
      registry = atk_get_default_registry ();
 
9976
      factory = atk_registry_get_factory (registry,
 
9977
                                          derived_type);
 
9978
      derived_atk_type = atk_object_factory_get_accessible_type (factory);
 
9979
      if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE)) 
 
9980
        atk_registry_set_factory_type (registry, 
 
9981
                                       GTK_TYPE_ICON_VIEW,
 
9982
                                       gtk_icon_view_accessible_factory_get_type ());
 
9983
      first_time = FALSE;
 
9984
    } 
 
9985
  return GTK_WIDGET_CLASS (gtk_icon_view_parent_class)->get_accessible (widget);
 
9986
}
 
9987
 
 
9988
static gboolean
 
9989
gtk_icon_view_buildable_custom_tag_start (GtkBuildable  *buildable,
 
9990
                                          GtkBuilder    *builder,
 
9991
                                          GObject       *child,
 
9992
                                          const gchar   *tagname,
 
9993
                                          GMarkupParser *parser,
 
9994
                                          gpointer      *data)
 
9995
{
 
9996
  if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
 
9997
                                                tagname, parser, data))
 
9998
    return TRUE;
 
9999
 
 
10000
  return _gtk_cell_layout_buildable_custom_tag_start (buildable, builder, child,
 
10001
                                                      tagname, parser, data);
 
10002
}
 
10003
 
 
10004
static void
 
10005
gtk_icon_view_buildable_custom_tag_end (GtkBuildable *buildable,
 
10006
                                        GtkBuilder   *builder,
 
10007
                                        GObject      *child,
 
10008
                                        const gchar  *tagname,
 
10009
                                        gpointer     *data)
 
10010
{
 
10011
  if (strcmp (tagname, "attributes") == 0)
 
10012
    _gtk_cell_layout_buildable_custom_tag_end (buildable, builder, child, tagname,
 
10013
                                               data);
 
10014
  else
 
10015
    parent_buildable_iface->custom_tag_end (buildable, builder, child, tagname,
 
10016
                                            data);
 
10017
}
 
10018
 
 
10019
 
 
10020
 
 
10021
#define __GTK_ICON_VIEW_C__
 
10022
#include "gtkaliasdef.c"