4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* view_collection.c - a subclass of Collection, used for displaying files */
32 #include "collection.h"
33 #include "view_iface.h"
34 #include "view_collection.h"
39 #include "gui_support.h"
45 #include "display.h" /* XXX */
46 #include "toolbar.h" /* XXX */
47 #include "filer.h" /* XXX */
48 #include "menu.h" /* XXX */
50 #define MIN_ITEM_WIDTH 64
53 /* The handler of the signal handler for scroll events.
54 * This is used to cancel spring loading when autoscrolling is used.
56 static gulong scrolled_signal
= -1;
57 static GtkObject
*scrolled_adj
= NULL
; /* The object watched */
60 static gpointer parent_class
= NULL
;
62 struct _ViewCollectionClass
{
63 GtkViewportClass parent
;
66 struct _ViewCollection
{
69 Collection
*collection
;
70 FilerWindow
*filer_window
; /* Used for styles, etc */
72 int cursor_base
; /* Cursor when minibuffer opened */
75 typedef struct _Template Template
;
79 GdkRectangle leafname
;
83 /* GC for drawing colour filenames */
84 static GdkGC
*type_gc
= NULL
;
86 /* Static prototypes */
87 static void view_collection_finialize(GObject
*object
);
88 static void view_collection_class_init(gpointer gclass
, gpointer data
);
89 static void view_collection_init(GTypeInstance
*object
, gpointer gclass
);
91 static void draw_item(GtkWidget
*widget
,
95 static void fill_template(GdkRectangle
*area
, CollectionItem
*item
,
96 ViewCollection
*view_collection
, Template
*template);
97 static void huge_template(GdkRectangle
*area
, CollectionItem
*colitem
,
98 ViewCollection
*view_collection
, Template
*template);
99 static void large_template(GdkRectangle
*area
, CollectionItem
*colitem
,
100 ViewCollection
*view_collection
, Template
*template);
101 static void small_template(GdkRectangle
*area
, CollectionItem
*colitem
,
102 ViewCollection
*view_collection
, Template
*template);
103 static void huge_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
104 ViewCollection
*view_collection
, Template
*template);
105 static void large_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
106 ViewCollection
*view_collection
, Template
*template);
107 static void small_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
108 ViewCollection
*view_collection
, Template
*template);
109 static gboolean
test_point(Collection
*collection
,
110 int point_x
, int point_y
,
111 CollectionItem
*item
,
112 int width
, int height
,
114 static void draw_string(GtkWidget
*widget
,
116 GdkRectangle
*area
, /* Area available on screen */
117 int width
, /* Width of the full string */
118 GtkStateType selection_state
,
121 static void draw_huge_icon(GtkWidget
*widget
,
126 static void view_collection_iface_init(gpointer giface
, gpointer iface_data
);
127 static gint
coll_motion_notify(GtkWidget
*widget
,
128 GdkEventMotion
*event
,
129 ViewCollection
*view_collection
);
130 static gint
coll_button_release(GtkWidget
*widget
,
131 GdkEventButton
*event
,
132 ViewCollection
*view_collection
);
133 static gint
coll_button_press(GtkWidget
*widget
,
134 GdkEventButton
*event
,
135 ViewCollection
*view_collection
);
136 static void size_allocate(GtkWidget
*w
, GtkAllocation
*a
, gpointer data
);
137 static void style_set(Collection
*collection
,
139 ViewCollection
*view_collection
);
140 static void display_free_colitem(Collection
*collection
,
141 CollectionItem
*colitem
);
142 static void lost_selection(Collection
*collection
,
145 static void selection_changed(Collection
*collection
,
148 static void calc_size(FilerWindow
*filer_window
, CollectionItem
*colitem
,
149 int *width
, int *height
);
150 static void make_iter(ViewCollection
*view_collection
, ViewIter
*iter
,
152 static void make_item_iter(ViewCollection
*vc
, ViewIter
*iter
, int i
);
154 static void view_collection_sort(ViewIface
*view
);
155 static void view_collection_style_changed(ViewIface
*view
, int flags
);
156 static gboolean
view_collection_autoselect(ViewIface
*view
, const gchar
*leaf
);
157 static void view_collection_add_items(ViewIface
*view
, GPtrArray
*items
);
158 static void view_collection_update_items(ViewIface
*view
, GPtrArray
*items
);
159 static void view_collection_delete_if(ViewIface
*view
,
160 gboolean (*test
)(gpointer item
, gpointer data
),
162 static void view_collection_clear(ViewIface
*view
);
163 static void view_collection_select_all(ViewIface
*view
);
164 static void view_collection_clear_selection(ViewIface
*view
);
165 static int view_collection_count_items(ViewIface
*view
);
166 static int view_collection_count_selected(ViewIface
*view
);
167 static void view_collection_show_cursor(ViewIface
*view
);
168 static void view_collection_get_iter(ViewIface
*view
,
169 ViewIter
*iter
, IterFlags flags
);
170 static void view_collection_get_iter_at_point(ViewIface
*view
, ViewIter
*iter
,
172 static void view_collection_cursor_to_iter(ViewIface
*view
, ViewIter
*iter
);
173 static void view_collection_set_selected(ViewIface
*view
,
176 static gboolean
view_collection_get_selected(ViewIface
*view
, ViewIter
*iter
);
177 static void view_collection_select_only(ViewIface
*view
, ViewIter
*iter
);
178 static void view_collection_set_frozen(ViewIface
*view
, gboolean frozen
);
179 static void view_collection_wink_item(ViewIface
*view
, ViewIter
*iter
);
180 static void view_collection_autosize(ViewIface
*view
);
181 static gboolean
view_collection_cursor_visible(ViewIface
*view
);
182 static void view_collection_set_base(ViewIface
*view
, ViewIter
*iter
);
183 static void view_collection_start_lasso_box(ViewIface
*view
,
184 GdkEventButton
*event
);
185 static void view_collection_extend_tip(ViewIface
*view
, ViewIter
*iter
,
188 static DirItem
*iter_next(ViewIter
*iter
);
189 static DirItem
*iter_prev(ViewIter
*iter
);
190 static DirItem
*iter_peek(ViewIter
*iter
);
193 /****************************************************************
194 * EXTERNAL INTERFACE *
195 ****************************************************************/
197 GtkWidget
*view_collection_new(FilerWindow
*filer_window
)
199 ViewCollection
*view_collection
;
201 view_collection
= g_object_new(view_collection_get_type(), NULL
);
202 view_collection
->filer_window
= filer_window
;
204 gtk_range_set_adjustment(GTK_RANGE(filer_window
->scrollbar
),
205 view_collection
->collection
->vadj
);
207 return GTK_WIDGET(view_collection
);
210 GType
view_collection_get_type(void)
212 static GType type
= 0;
216 static const GTypeInfo info
=
218 sizeof (ViewCollectionClass
),
219 NULL
, /* base_init */
220 NULL
, /* base_finalise */
221 view_collection_class_init
,
222 NULL
, /* class_finalise */
223 NULL
, /* class_data */
224 sizeof(ViewCollection
),
228 static const GInterfaceInfo iface_info
=
230 view_collection_iface_init
, NULL
, NULL
233 type
= g_type_register_static(gtk_viewport_get_type(),
234 "ViewCollection", &info
, 0);
235 g_type_add_interface_static(type
, VIEW_TYPE_IFACE
, &iface_info
);
241 /****************************************************************
242 * INTERNAL FUNCTIONS *
243 ****************************************************************/
245 static void view_collection_destroy(GtkObject
*view_collection
)
247 VIEW_COLLECTION(view_collection
)->filer_window
= NULL
;
250 static void view_collection_finialize(GObject
*object
)
252 /* ViewCollection *view_collection = (ViewCollection *) object; */
254 G_OBJECT_CLASS(parent_class
)->finalize(object
);
257 static void view_collection_class_init(gpointer gclass
, gpointer data
)
259 GObjectClass
*object
= (GObjectClass
*) gclass
;
261 parent_class
= g_type_class_peek_parent(gclass
);
263 object
->finalize
= view_collection_finialize
;
264 GTK_OBJECT_CLASS(object
)->destroy
= view_collection_destroy
;
267 static void view_collection_init(GTypeInstance
*object
, gpointer gclass
)
269 ViewCollection
*view_collection
= (ViewCollection
*) object
;
270 GtkViewport
*viewport
= (GtkViewport
*) object
;
271 GtkWidget
*collection
;
274 collection
= collection_new();
275 view_collection
->collection
= COLLECTION(collection
);
277 adj
= view_collection
->collection
->vadj
;
278 gtk_viewport_set_vadjustment(viewport
, adj
);
279 gtk_viewport_set_hadjustment(viewport
, NULL
); /* Or Gtk will crash */
280 gtk_viewport_set_shadow_type(viewport
, GTK_SHADOW_NONE
);
281 gtk_container_add(GTK_CONTAINER(object
), collection
);
282 gtk_widget_show(collection
);
283 gtk_widget_set_size_request(GTK_WIDGET(view_collection
), 4, 4);
285 gtk_container_set_resize_mode(GTK_CONTAINER(viewport
),
286 GTK_RESIZE_IMMEDIATE
);
288 view_collection
->collection
->free_item
= display_free_colitem
;
289 view_collection
->collection
->draw_item
= draw_item
;
290 view_collection
->collection
->test_point
= test_point
;
291 view_collection
->collection
->cb_user_data
= view_collection
;
293 g_signal_connect(collection
, "style_set",
294 G_CALLBACK(style_set
),
297 g_signal_connect(collection
, "lose_selection",
298 G_CALLBACK(lost_selection
), view_collection
);
299 g_signal_connect(collection
, "selection_changed",
300 G_CALLBACK(selection_changed
), view_collection
);
302 g_signal_connect(collection
, "button-release-event",
303 G_CALLBACK(coll_button_release
), view_collection
);
304 g_signal_connect(collection
, "button-press-event",
305 G_CALLBACK(coll_button_press
), view_collection
);
306 g_signal_connect(collection
, "motion-notify-event",
307 G_CALLBACK(coll_motion_notify
), view_collection
);
308 g_signal_connect(viewport
, "size-allocate",
309 G_CALLBACK(size_allocate
), view_collection
);
311 gtk_widget_set_events(collection
,
312 GDK_BUTTON1_MOTION_MASK
| GDK_BUTTON2_MOTION_MASK
|
313 GDK_BUTTON3_MOTION_MASK
| GDK_POINTER_MOTION_MASK
|
314 GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
);
318 static void draw_item(GtkWidget
*widget
,
319 CollectionItem
*colitem
,
323 DirItem
*item
= (DirItem
*) colitem
->data
;
324 gboolean selected
= colitem
->selected
;
326 ViewData
*view
= (ViewData
*) colitem
->view_data
;
327 ViewCollection
*view_collection
= (ViewCollection
*) user_data
;
328 FilerWindow
*filer_window
= view_collection
->filer_window
;
330 g_return_if_fail(view
!= NULL
);
332 fill_template(area
, colitem
, view_collection
, &template);
334 /* Set up GC for coloured file types */
336 type_gc
= gdk_gc_new(widget
->window
);
338 gdk_gc_set_foreground(type_gc
, type_get_colour(item
,
339 &widget
->style
->fg
[GTK_STATE_NORMAL
]));
341 if (template.icon
.width
<= SMALL_WIDTH
&&
342 template.icon
.height
<= SMALL_HEIGHT
)
344 draw_small_icon(widget
->window
, &template.icon
,
345 item
, view
->image
, selected
);
347 else if (template.icon
.width
<= ICON_WIDTH
&&
348 template.icon
.height
<= ICON_HEIGHT
)
350 draw_large_icon(widget
, &template.icon
,
351 item
, view
->image
, selected
);
355 draw_huge_icon(widget
, &template.icon
,
356 item
, view
->image
, selected
);
359 draw_string(widget
, view
->layout
,
362 filer_window
->selection_state
,
365 draw_string(widget
, view
->details
,
367 template.details
.width
,
368 filer_window
->selection_state
,
372 /* A template contains the locations of the three rectangles (for the icon,
373 * name and extra details).
374 * Fill in the empty 'template' with the rectanges for this item.
376 static void fill_template(GdkRectangle
*area
, CollectionItem
*colitem
,
377 ViewCollection
*view_collection
, Template
*template)
379 DisplayStyle style
= view_collection
->filer_window
->display_style
;
380 ViewData
*view
= (ViewData
*) colitem
->view_data
;
384 template->details
.width
= view
->details_width
;
385 template->details
.height
= view
->details_height
;
387 if (style
== SMALL_ICONS
)
388 small_full_template(area
, colitem
,
389 view_collection
, template);
390 else if (style
== LARGE_ICONS
)
391 large_full_template(area
, colitem
,
392 view_collection
, template);
394 huge_full_template(area
, colitem
,
395 view_collection
, template);
399 if (style
== HUGE_ICONS
)
400 huge_template(area
, colitem
,
401 view_collection
, template);
402 else if (style
== LARGE_ICONS
)
403 large_template(area
, colitem
,
404 view_collection
, template);
406 small_template(area
, colitem
,
407 view_collection
, template);
411 static void huge_template(GdkRectangle
*area
, CollectionItem
*colitem
,
412 ViewCollection
*view_collection
, Template
*template)
414 int col_width
= view_collection
->collection
->item_width
;
416 ViewData
*view
= (ViewData
*) colitem
->view_data
;
417 MaskedPixmap
*image
= view
->image
;
421 if (!image
->huge_pixbuf
)
422 pixmap_make_huge(image
);
423 template->icon
.width
= image
->huge_width
;
424 template->icon
.height
= image
->huge_height
;
428 template->icon
.width
= HUGE_WIDTH
* 3 / 2;
429 template->icon
.height
= HUGE_HEIGHT
;
432 template->leafname
.width
= view
->name_width
;
433 template->leafname
.height
= view
->name_height
;
435 text_x
= area
->x
+ ((col_width
- template->leafname
.width
) >> 1);
436 text_y
= area
->y
+ area
->height
- template->leafname
.height
;
438 template->leafname
.x
= text_x
;
439 template->leafname
.y
= text_y
;
441 template->icon
.x
= area
->x
+ ((col_width
- template->icon
.width
) >> 1);
442 template->icon
.y
= template->leafname
.y
- template->icon
.height
- 2;
445 static void large_template(GdkRectangle
*area
, CollectionItem
*colitem
,
446 ViewCollection
*view_collection
, Template
*template)
448 int col_width
= view_collection
->collection
->item_width
;
452 ViewData
*view
= (ViewData
*) colitem
->view_data
;
453 MaskedPixmap
*image
= view
->image
;
459 iwidth
= MIN(image
->width
, ICON_WIDTH
);
460 iheight
= MIN(image
->height
+ 6, ICON_HEIGHT
);
465 iheight
= ICON_HEIGHT
;
467 image_x
= area
->x
+ ((col_width
- iwidth
) >> 1);
469 template->leafname
.width
= view
->name_width
;
470 template->leafname
.height
= view
->name_height
;
472 text_x
= area
->x
+ ((col_width
- template->leafname
.width
) >> 1);
473 text_y
= area
->y
+ ICON_HEIGHT
+ 2;
475 template->leafname
.x
= text_x
;
476 template->leafname
.y
= text_y
;
478 image_y
= text_y
- iheight
;
479 image_y
= MAX(area
->y
, image_y
);
481 template->icon
.x
= image_x
;
482 template->icon
.y
= image_y
;
483 template->icon
.width
= iwidth
;
484 template->icon
.height
= MIN(ICON_HEIGHT
, iheight
);
487 static void small_template(GdkRectangle
*area
, CollectionItem
*colitem
,
488 ViewCollection
*view_collection
, Template
*template)
490 int text_x
= area
->x
+ SMALL_WIDTH
+ 4;
492 int max_text_width
= area
->width
- SMALL_WIDTH
- 4;
493 ViewData
*view
= (ViewData
*) colitem
->view_data
;
495 low_text_y
= area
->y
+ area
->height
/ 2 - view
->name_height
/ 2;
497 template->leafname
.x
= text_x
;
498 template->leafname
.y
= low_text_y
;
499 template->leafname
.width
= MIN(max_text_width
, view
->name_width
);
500 template->leafname
.height
= view
->name_height
;
502 template->icon
.x
= area
->x
;
503 template->icon
.y
= area
->y
+ 1;
504 template->icon
.width
= SMALL_WIDTH
;
505 template->icon
.height
= SMALL_HEIGHT
;
508 static void huge_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
509 ViewCollection
*view_collection
, Template
*template)
511 int max_text_width
= area
->width
- HUGE_WIDTH
- 4;
512 ViewData
*view
= (ViewData
*) colitem
->view_data
;
513 MaskedPixmap
*image
= view
->image
;
517 if (!image
->huge_pixbuf
)
518 pixmap_make_huge(image
);
519 template->icon
.width
= image
->huge_width
;
520 template->icon
.height
= image
->huge_height
;
524 template->icon
.width
= HUGE_WIDTH
* 3 / 2;
525 template->icon
.height
= HUGE_HEIGHT
;
528 template->icon
.x
= area
->x
+ (HUGE_WIDTH
- template->icon
.width
) / 2;
529 template->icon
.y
= area
->y
+ (area
->height
- template->icon
.height
) / 2;
531 template->leafname
.x
= area
->x
+ HUGE_WIDTH
+ 4;
532 template->leafname
.y
= area
->y
+ area
->height
/ 2
533 - (view
->name_height
+ 2 + view
->details_height
) / 2;
534 template->leafname
.width
= MIN(max_text_width
, view
->name_width
);
535 template->leafname
.height
= view
->name_height
;
538 return; /* Not scanned yet */
540 template->details
.x
= template->leafname
.x
;
541 template->details
.y
= template->leafname
.y
+ view
->name_height
+ 2;
544 static void large_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
545 ViewCollection
*view_collection
, Template
*template)
547 int max_text_width
= area
->width
- ICON_WIDTH
- 4;
548 ViewData
*view
= (ViewData
*) colitem
->view_data
;
549 MaskedPixmap
*image
= view
->image
;
553 template->icon
.width
= image
->width
;
554 template->icon
.height
= image
->height
;
558 template->icon
.width
= ICON_WIDTH
;
559 template->icon
.height
= ICON_HEIGHT
;
562 template->icon
.x
= area
->x
+ (ICON_WIDTH
- template->icon
.width
) / 2;
563 template->icon
.y
= area
->y
+ (area
->height
- template->icon
.height
) / 2;
566 template->leafname
.x
= area
->x
+ ICON_WIDTH
+ 4;
567 template->leafname
.y
= area
->y
+ area
->height
/ 2
568 - (view
->name_height
+ 2 + view
->details_height
) / 2;
569 template->leafname
.width
= MIN(max_text_width
, view
->name_width
);
570 template->leafname
.height
= view
->name_height
;
573 return; /* Not scanned yet */
575 template->details
.x
= template->leafname
.x
;
576 template->details
.y
= template->leafname
.y
+ view
->name_height
+ 2;
579 static void small_full_template(GdkRectangle
*area
, CollectionItem
*colitem
,
580 ViewCollection
*view_collection
, Template
*template)
582 int col_width
= view_collection
->collection
->item_width
;
583 ViewData
*view
= (ViewData
*) colitem
->view_data
;
585 small_template(area
, colitem
, view_collection
, template);
588 return; /* Not scanned yet */
590 template->details
.x
= area
->x
+ col_width
- template->details
.width
;
591 template->details
.y
= area
->y
+ area
->height
/ 2 - \
592 view
->details_height
/ 2;
595 #define INSIDE(px, py, area) \
596 (px >= area.x && py >= area.y && \
597 px <= area.x + area.width && py <= area.y + area.height)
599 static gboolean
test_point(Collection
*collection
,
600 int point_x
, int point_y
,
601 CollectionItem
*colitem
,
602 int width
, int height
,
607 ViewData
*view
= (ViewData
*) colitem
->view_data
;
608 ViewCollection
*view_collection
= (ViewCollection
*) user_data
;
613 area
.height
= height
;
615 fill_template(&area
, colitem
, view_collection
, &template);
617 return INSIDE(point_x
, point_y
, template.leafname
) ||
618 INSIDE(point_x
, point_y
, template.icon
) ||
619 (view
->details
&& INSIDE(point_x
, point_y
, template.details
));
622 /* 'box' renders a background box if the string is also selected */
623 static void draw_string(GtkWidget
*widget
,
625 GdkRectangle
*area
, /* Area available on screen */
626 int width
, /* Width of the full string */
627 GtkStateType selection_state
,
632 ? widget
->style
->fg_gc
[selection_state
]
636 gtk_paint_flat_box(widget
->style
, widget
->window
,
637 selection_state
, GTK_SHADOW_NONE
,
638 NULL
, widget
, "text",
640 MIN(width
, area
->width
),
643 if (width
> area
->width
)
645 gdk_gc_set_clip_origin(gc
, 0, 0);
646 gdk_gc_set_clip_rectangle(gc
, area
);
649 gdk_draw_layout(widget
->window
, gc
, area
->x
, area
->y
, layout
);
651 if (width
> area
->width
)
653 static GdkGC
*red_gc
= NULL
;
658 GdkColor red
= {0, 0xffff, 0, 0};
660 red_gc
= gdk_gc_new(widget
->window
);
661 gdk_colormap_alloc_colors(
662 gtk_widget_get_colormap(widget
),
663 &red
, 1, FALSE
, TRUE
, &success
);
664 gdk_gc_set_foreground(red_gc
, &red
);
666 gdk_draw_rectangle(widget
->window
, red_gc
, TRUE
,
667 area
->x
+ area
->width
- 1, area
->y
,
669 gdk_gc_set_clip_rectangle(gc
, NULL
);
673 /* Draw this icon (including any symlink or mount symbol) inside the
676 static void draw_huge_icon(GtkWidget
*widget
,
689 width
= image
->huge_width
;
690 height
= image
->huge_height
;
691 image_x
= area
->x
+ ((area
->width
- width
) >> 1);
692 image_y
= MAX(0, area
->height
- height
- 6);
694 gdk_pixbuf_render_to_drawable_alpha(
695 selected
? image
->huge_pixbuf_lit
696 : image
->huge_pixbuf
,
699 image_x
, area
->y
+ image_y
, /* dest */
701 GDK_PIXBUF_ALPHA_FULL
, 128, /* (unused) */
702 GDK_RGB_DITHER_NORMAL
, 0, 0);
704 if (item
->flags
& ITEM_FLAG_SYMLINK
)
706 gdk_pixbuf_render_to_drawable_alpha(im_symlink
->pixbuf
,
709 image_x
, area
->y
+ 2, /* dest */
711 GDK_PIXBUF_ALPHA_FULL
, 128, /* (unused) */
712 GDK_RGB_DITHER_NORMAL
, 0, 0);
714 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
716 MaskedPixmap
*mp
= item
->flags
& ITEM_FLAG_MOUNTED
720 gdk_pixbuf_render_to_drawable_alpha(mp
->pixbuf
,
723 image_x
, area
->y
+ 2, /* dest */
725 GDK_PIXBUF_ALPHA_FULL
, 128, /* (unused) */
726 GDK_RGB_DITHER_NORMAL
, 0, 0);
730 /* Create the handers for the View interface */
731 static void view_collection_iface_init(gpointer giface
, gpointer iface_data
)
733 ViewIfaceClass
*iface
= giface
;
735 g_assert(G_TYPE_FROM_INTERFACE(iface
) == VIEW_TYPE_IFACE
);
738 iface
->sort
= view_collection_sort
;
739 iface
->style_changed
= view_collection_style_changed
;
740 iface
->autoselect
= view_collection_autoselect
;
741 iface
->add_items
= view_collection_add_items
;
742 iface
->update_items
= view_collection_update_items
;
743 iface
->delete_if
= view_collection_delete_if
;
744 iface
->clear
= view_collection_clear
;
745 iface
->select_all
= view_collection_select_all
;
746 iface
->clear_selection
= view_collection_clear_selection
;
747 iface
->count_items
= view_collection_count_items
;
748 iface
->count_selected
= view_collection_count_selected
;
749 iface
->show_cursor
= view_collection_show_cursor
;
750 iface
->get_iter
= view_collection_get_iter
;
751 iface
->get_iter_at_point
= view_collection_get_iter_at_point
;
752 iface
->cursor_to_iter
= view_collection_cursor_to_iter
;
753 iface
->set_selected
= view_collection_set_selected
;
754 iface
->get_selected
= view_collection_get_selected
;
755 iface
->set_frozen
= view_collection_set_frozen
;
756 iface
->select_only
= view_collection_select_only
;
757 iface
->wink_item
= view_collection_wink_item
;
758 iface
->autosize
= view_collection_autosize
;
759 iface
->cursor_visible
= view_collection_cursor_visible
;
760 iface
->set_base
= view_collection_set_base
;
761 iface
->start_lasso_box
= view_collection_start_lasso_box
;
762 iface
->extend_tip
= view_collection_extend_tip
;
765 static void view_collection_extend_tip(ViewIface
*view
, ViewIter
*iter
,
768 ViewCollection
*view_collection
= (ViewCollection
*) view
;
769 Collection
*collection
= view_collection
->collection
;
770 FilerWindow
*filer_window
= view_collection
->filer_window
;
773 CollectionItem
*colitem
= &collection
->items
[i
];
774 int col
= i
% collection
->columns
;
775 int row
= i
/ collection
->columns
;
776 ViewData
*view_data
= (ViewData
*) colitem
->view_data
;
779 g_return_if_fail(iter
->view_collection
== view_collection
);
780 g_return_if_fail(i
>= 0 && i
< collection
->number_of_items
);
782 /* TODO: What if the window is narrower than 1 column? */
783 if (filer_window
->display_style
== LARGE_ICONS
||
784 filer_window
->display_style
== HUGE_ICONS
)
785 return; /* These wrap rather than truncate */
787 area
.x
= col
* collection
->item_width
;
788 area
.y
= row
* collection
->item_height
;
789 area
.height
= collection
->item_height
;
791 if (col
== collection
->columns
- 1)
792 area
.width
= GTK_WIDGET(collection
)->allocation
.width
- area
.x
;
794 area
.width
= collection
->item_width
;
796 fill_template(&area
, colitem
, view_collection
, &template);
798 if (template.leafname
.width
< view_data
->name_width
)
800 DirItem
*item
= (DirItem
*) collection
->items
[i
].data
;
802 g_string_append(tip
, item
->leafname
);
803 g_string_append_c(tip
, '\n');
807 static gint
coll_motion_notify(GtkWidget
*widget
,
808 GdkEventMotion
*event
,
809 ViewCollection
*view_collection
)
811 return filer_motion_notify(view_collection
->filer_window
, event
);
814 /* Viewport is to be resized, so calculate increments */
815 static void size_allocate(GtkWidget
*w
, GtkAllocation
*a
, gpointer data
)
817 Collection
*col
= ((ViewCollection
*) data
)->collection
;
819 col
->vadj
->step_increment
= col
->item_height
;
820 col
->vadj
->page_increment
= col
->vadj
->page_size
;
823 static gint
coll_button_release(GtkWidget
*widget
,
824 GdkEventButton
*event
,
825 ViewCollection
*view_collection
)
827 if (dnd_motion_release(event
))
829 if (motion_buttons_pressed
== 0 &&
830 view_collection
->collection
->lasso_box
)
832 collection_end_lasso(view_collection
->collection
,
833 event
->button
== 1 ? GDK_SET
: GDK_INVERT
);
838 filer_perform_action(view_collection
->filer_window
, event
);
843 static gint
coll_button_press(GtkWidget
*widget
,
844 GdkEventButton
*event
,
845 ViewCollection
*view_collection
)
847 collection_set_cursor_item(view_collection
->collection
, -1);
849 if (dnd_motion_press(widget
, event
))
850 filer_perform_action(view_collection
->filer_window
, event
);
855 /* Nothing is selected anymore - give up primary */
856 static void lost_selection(Collection
*collection
,
860 ViewCollection
*view_collection
= VIEW_COLLECTION(user_data
);
862 filer_lost_selection(view_collection
->filer_window
, time
);
865 static void selection_changed(Collection
*collection
,
869 ViewCollection
*view_collection
= VIEW_COLLECTION(user_data
);
871 filer_selection_changed(view_collection
->filer_window
, time
);
874 static void display_free_colitem(Collection
*collection
,
875 CollectionItem
*colitem
)
877 ViewData
*view
= (ViewData
*) colitem
->view_data
;
884 g_object_unref(G_OBJECT(view
->layout
));
888 g_object_unref(G_OBJECT(view
->details
));
891 g_object_unref(view
->image
);
896 static void add_item(ViewCollection
*view_collection
, DirItem
*item
)
898 Collection
*collection
= view_collection
->collection
;
899 FilerWindow
*filer_window
= view_collection
->filer_window
;
900 int old_w
= collection
->item_width
;
901 int old_h
= collection
->item_height
;
904 i
= collection_insert(collection
, item
,
905 display_create_viewdata(filer_window
, item
));
907 calc_size(filer_window
, &collection
->items
[i
], &w
, &h
);
909 if (w
> old_w
|| h
> old_h
)
910 collection_set_item_size(collection
,
915 static void style_set(Collection
*collection
,
917 ViewCollection
*view_collection
)
919 view_collection_style_changed(VIEW(view_collection
),
920 VIEW_UPDATE_VIEWDATA
| VIEW_UPDATE_NAME
);
923 /* Return the size needed for this item */
924 static void calc_size(FilerWindow
*filer_window
, CollectionItem
*colitem
,
925 int *width
, int *height
)
927 int pix_width
, pix_height
;
929 DisplayStyle style
= filer_window
->display_style
;
930 ViewData
*view
= (ViewData
*) colitem
->view_data
;
932 if (filer_window
->details_type
== DETAILS_NONE
)
934 if (style
== HUGE_ICONS
)
938 if (!view
->image
->huge_pixbuf
)
939 pixmap_make_huge(view
->image
);
940 pix_width
= view
->image
->huge_width
;
941 pix_height
= view
->image
->huge_height
;
945 pix_width
= HUGE_WIDTH
* 3 / 2;
946 pix_height
= HUGE_HEIGHT
* 3 / 2;
948 *width
= MAX(pix_width
, view
->name_width
) + 4;
949 *height
= view
->name_height
+ pix_height
+ 4;
951 else if (style
== SMALL_ICONS
)
953 w
= MIN(view
->name_width
, o_small_width
.int_value
);
954 *width
= SMALL_WIDTH
+ 12 + w
;
955 *height
= MAX(view
->name_height
, SMALL_HEIGHT
) + 4;
960 pix_width
= view
->image
->width
;
962 pix_width
= ICON_WIDTH
;
963 *width
= MAX(pix_width
, view
->name_width
) + 4;
964 *height
= view
->name_height
+ ICON_HEIGHT
+ 2;
969 w
= view
->details_width
;
970 if (style
== HUGE_ICONS
)
972 *width
= HUGE_WIDTH
+ 12 + MAX(w
, view
->name_width
);
973 *height
= HUGE_HEIGHT
- 4;
975 else if (style
== SMALL_ICONS
)
979 *width
= SMALL_WIDTH
+ view
->name_width
+ 12 + w
;
980 text_height
= MAX(view
->name_height
,
981 view
->details_height
);
982 *height
= MAX(text_height
, SMALL_HEIGHT
) + 4;
986 *width
= ICON_WIDTH
+ 12 + MAX(w
, view
->name_width
);
987 *height
= ICON_HEIGHT
;
992 static void update_item(ViewCollection
*view_collection
, int i
)
994 Collection
*collection
= view_collection
->collection
;
995 int old_w
= collection
->item_width
;
996 int old_h
= collection
->item_height
;
998 CollectionItem
*colitem
;
999 FilerWindow
*filer_window
= view_collection
->filer_window
;
1001 g_return_if_fail(i
>= 0 && i
< collection
->number_of_items
);
1003 colitem
= &collection
->items
[i
];
1005 display_update_view(filer_window
,
1006 (DirItem
*) colitem
->data
,
1007 (ViewData
*) colitem
->view_data
,
1010 calc_size(filer_window
, colitem
, &w
, &h
);
1011 if (w
> old_w
|| h
> old_h
)
1012 collection_set_item_size(collection
,
1016 collection_draw_item(collection
, i
, TRUE
);
1019 /* Implementations of the View interface. See view_iface.c for comments. */
1021 static void view_collection_style_changed(ViewIface
*view
, int flags
)
1023 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1024 FilerWindow
*filer_window
= view_collection
->filer_window
;
1026 Collection
*col
= view_collection
->collection
;
1027 int width
= MIN_ITEM_WIDTH
;
1028 int height
= SMALL_HEIGHT
;
1029 int n
= col
->number_of_items
;
1031 if (n
== 0 && filer_window
->display_style
!= SMALL_ICONS
)
1032 height
= ICON_HEIGHT
;
1034 /* Recalculate all the ViewData structs for this window
1035 * (needed if the text or image has changed in any way) and
1036 * get the size of each item.
1038 for (i
= 0; i
< n
; i
++)
1040 CollectionItem
*ci
= &col
->items
[i
];
1043 if (flags
& (VIEW_UPDATE_VIEWDATA
| VIEW_UPDATE_NAME
))
1044 display_update_view(filer_window
,
1045 (DirItem
*) ci
->data
,
1046 (ViewData
*) ci
->view_data
,
1047 (flags
& VIEW_UPDATE_NAME
) != 0);
1049 calc_size(filer_window
, ci
, &w
, &h
);
1056 collection_set_item_size(col
, width
, height
);
1058 gtk_widget_queue_draw(GTK_WIDGET(view_collection
));
1061 static void view_collection_sort(ViewIface
*view
)
1063 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1065 collection_qsort(view_collection
->collection
,
1066 view_collection
->filer_window
->sort_fn
);
1069 static gboolean
view_collection_autoselect(ViewIface
*view
, const gchar
*leaf
)
1071 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1072 Collection
*col
= view_collection
->collection
;
1075 for (i
= 0; i
< col
->number_of_items
; i
++)
1077 DirItem
*item
= (DirItem
*) col
->items
[i
].data
;
1079 if (strcmp(item
->leafname
, leaf
) == 0)
1081 if (col
->cursor_item
!= -1)
1082 collection_set_cursor_item(col
, i
);
1084 collection_wink_item(col
, i
);
1092 static void view_collection_add_items(ViewIface
*view
, GPtrArray
*items
)
1094 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1095 Collection
*collection
= view_collection
->collection
;
1096 FilerWindow
*filer_window
= view_collection
->filer_window
;
1099 old_num
= collection
->number_of_items
;
1100 for (i
= 0; i
< items
->len
; i
++)
1102 DirItem
*item
= (DirItem
*) items
->pdata
[i
];
1103 char *leafname
= item
->leafname
;
1105 if (leafname
[0] == '.' && !filer_window
->show_hidden
)
1108 add_item(view_collection
, item
);
1111 if (old_num
!= collection
->number_of_items
)
1112 view_collection_sort(view
);
1115 static void view_collection_update_items(ViewIface
*view
, GPtrArray
*items
)
1117 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1118 Collection
*collection
= view_collection
->collection
;
1119 FilerWindow
*filer_window
= view_collection
->filer_window
;
1122 g_return_if_fail(items
->len
> 0);
1124 /* The item data has already been modified, so this gives the
1125 * final sort order...
1127 collection_qsort(collection
, filer_window
->sort_fn
);
1129 for (i
= 0; i
< items
->len
; i
++)
1131 DirItem
*item
= (DirItem
*) items
->pdata
[i
];
1132 const gchar
*leafname
= item
->leafname
;
1135 if (leafname
[0] == '.' && filer_window
->show_hidden
== FALSE
)
1138 j
= collection_find_item(collection
, item
,
1139 filer_window
->sort_fn
);
1142 g_warning("Failed to find '%s'\n", leafname
);
1144 update_item(view_collection
, j
);
1148 static void view_collection_delete_if(ViewIface
*view
,
1149 gboolean (*test
)(gpointer item
, gpointer data
),
1152 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1153 Collection
*collection
= view_collection
->collection
;
1155 collection_delete_if(collection
, test
, data
);
1158 static void view_collection_clear(ViewIface
*view
)
1160 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1161 Collection
*collection
= view_collection
->collection
;
1163 collection_clear(collection
);
1166 static void view_collection_select_all(ViewIface
*view
)
1168 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1169 Collection
*collection
= view_collection
->collection
;
1171 collection_select_all(collection
);
1174 static void view_collection_clear_selection(ViewIface
*view
)
1176 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1177 Collection
*collection
= view_collection
->collection
;
1179 collection_clear_selection(collection
);
1182 static int view_collection_count_items(ViewIface
*view
)
1184 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1185 Collection
*collection
= view_collection
->collection
;
1187 return collection
->number_of_items
;
1190 static int view_collection_count_selected(ViewIface
*view
)
1192 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1193 Collection
*collection
= view_collection
->collection
;
1195 return collection
->number_selected
;
1198 static void view_collection_show_cursor(ViewIface
*view
)
1200 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1201 Collection
*collection
= view_collection
->collection
;
1203 collection_move_cursor(collection
, 0, 0);
1206 /* The first time the next() method is used, this is called */
1207 static DirItem
*iter_init(ViewIter
*iter
)
1209 ViewCollection
*view_collection
= iter
->view_collection
;
1210 Collection
*collection
= view_collection
->collection
;
1212 int n
= collection
->number_of_items
;
1213 int flags
= iter
->flags
;
1215 iter
->peek
= iter_peek
;
1217 if (iter
->n_remaining
== 0)
1220 if (flags
& VIEW_ITER_FROM_CURSOR
)
1222 i
= collection
->cursor_item
;
1224 return NULL
; /* No cursor */
1226 else if (flags
& VIEW_ITER_FROM_BASE
)
1227 i
= view_collection
->cursor_base
;
1229 if (i
< 0 || i
>= n
)
1231 /* Either a normal iteration, or an iteration from an
1232 * invalid starting point.
1234 if (flags
& VIEW_ITER_BACKWARDS
)
1240 if (i
< 0 || i
>= n
)
1241 return NULL
; /* No items at all! */
1243 iter
->next
= flags
& VIEW_ITER_BACKWARDS
? iter_prev
: iter_next
;
1244 iter
->n_remaining
--;
1247 if (flags
& VIEW_ITER_SELECTED
&& !collection
->items
[i
].selected
)
1248 return iter
->next(iter
);
1249 return iter
->peek(iter
);
1251 /* Advance iter to point to the next item and return the new item
1252 * (this saves you calling peek after next each time).
1254 static DirItem
*iter_next(ViewIter
*iter
)
1256 Collection
*collection
= iter
->view_collection
->collection
;
1257 int n
= collection
->number_of_items
;
1260 g_return_val_if_fail(iter
->n_remaining
>= 0, NULL
);
1262 /* i is the last item returned (always valid) */
1264 g_return_val_if_fail(i
>= 0 && i
< n
, NULL
);
1266 while (iter
->n_remaining
)
1269 iter
->n_remaining
--;
1274 g_return_val_if_fail(i
>= 0 && i
< n
, NULL
);
1276 if (iter
->flags
& VIEW_ITER_SELECTED
&&
1277 !collection
->items
[i
].selected
)
1281 return collection
->items
[i
].data
;
1288 /* Like iter_next, but in the other direction */
1289 static DirItem
*iter_prev(ViewIter
*iter
)
1291 Collection
*collection
= iter
->view_collection
->collection
;
1292 int n
= collection
->number_of_items
;
1295 g_return_val_if_fail(iter
->n_remaining
>= 0, NULL
);
1297 /* i is the last item returned (always valid) */
1299 g_return_val_if_fail(i
>= 0 && i
< n
, NULL
);
1301 while (iter
->n_remaining
)
1304 iter
->n_remaining
--;
1307 i
= collection
->number_of_items
- 1;
1309 g_return_val_if_fail(i
>= 0 && i
< n
, NULL
);
1311 if (iter
->flags
& VIEW_ITER_SELECTED
&&
1312 !collection
->items
[i
].selected
)
1316 return collection
->items
[i
].data
;
1323 static DirItem
*iter_peek(ViewIter
*iter
)
1325 Collection
*collection
= iter
->view_collection
->collection
;
1331 g_return_val_if_fail(i
>= 0 && i
< collection
->number_of_items
, NULL
);
1333 return collection
->items
[i
].data
;
1336 static void make_iter(ViewCollection
*view_collection
, ViewIter
*iter
,
1339 Collection
*collection
= view_collection
->collection
;
1341 iter
->view_collection
= view_collection
;
1342 iter
->next
= iter_init
;
1346 iter
->flags
= flags
;
1348 if (flags
& VIEW_ITER_ONE_ONLY
)
1350 iter
->n_remaining
= 1;
1354 iter
->n_remaining
= collection
->number_of_items
;
1357 /* Set the iterator to return 'i' on the next peek() */
1358 static void make_item_iter(ViewCollection
*view_collection
,
1359 ViewIter
*iter
, int i
)
1361 Collection
*collection
= view_collection
->collection
;
1363 g_return_if_fail(i
>= -1 && i
< collection
->number_of_items
);
1365 make_iter(view_collection
, iter
, 0);
1368 iter
->next
= iter_next
;
1369 iter
->peek
= iter_peek
;
1370 iter
->n_remaining
= 0;
1373 static void view_collection_get_iter(ViewIface
*view
,
1374 ViewIter
*iter
, IterFlags flags
)
1376 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1378 make_iter(view_collection
, iter
, flags
);
1381 static void view_collection_get_iter_at_point(ViewIface
*view
, ViewIter
*iter
,
1384 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1385 Collection
*collection
= view_collection
->collection
;
1388 i
= collection_get_item(collection
, x
, y
);
1389 make_item_iter(view_collection
, iter
, i
);
1392 static void view_collection_cursor_to_iter(ViewIface
*view
, ViewIter
*iter
)
1394 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1395 Collection
*collection
= view_collection
->collection
;
1397 g_return_if_fail(iter
== NULL
||
1398 iter
->view_collection
== view_collection
);
1400 collection_set_cursor_item(collection
, iter
? iter
->i
: -1);
1403 static void view_collection_set_selected(ViewIface
*view
,
1407 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1408 Collection
*collection
= view_collection
->collection
;
1410 g_return_if_fail(iter
!= NULL
&&
1411 iter
->view_collection
== view_collection
);
1412 g_return_if_fail(iter
->i
>= 0 && iter
->i
< collection
->number_of_items
);
1415 collection_select_item(collection
, iter
->i
);
1417 collection_unselect_item(collection
, iter
->i
);
1420 static gboolean
view_collection_get_selected(ViewIface
*view
, ViewIter
*iter
)
1422 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1423 Collection
*collection
= view_collection
->collection
;
1425 g_return_val_if_fail(iter
!= NULL
&&
1426 iter
->view_collection
== view_collection
, FALSE
);
1427 g_return_val_if_fail(iter
->i
>= 0 &&
1428 iter
->i
< collection
->number_of_items
, FALSE
);
1430 return collection
->items
[iter
->i
].selected
;
1433 static void view_collection_select_only(ViewIface
*view
, ViewIter
*iter
)
1435 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1436 Collection
*collection
= view_collection
->collection
;
1438 g_return_if_fail(iter
!= NULL
&&
1439 iter
->view_collection
== view_collection
);
1440 g_return_if_fail(iter
->i
>= 0 && iter
->i
< collection
->number_of_items
);
1442 collection_clear_except(collection
, iter
->i
);
1445 static void view_collection_set_frozen(ViewIface
*view
, gboolean frozen
)
1447 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1448 Collection
*collection
= view_collection
->collection
;
1451 collection
->block_selection_changed
++;
1453 collection_unblock_selection_changed(collection
,
1454 gtk_get_current_event_time(), TRUE
);
1457 static void view_collection_wink_item(ViewIface
*view
, ViewIter
*iter
)
1459 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1460 Collection
*collection
= view_collection
->collection
;
1464 collection_wink_item(collection
, -1);
1468 g_return_if_fail(iter
!= NULL
&&
1469 iter
->view_collection
== view_collection
);
1470 g_return_if_fail(iter
->i
>= 0 && iter
->i
< collection
->number_of_items
);
1472 collection_wink_item(collection
, iter
->i
);
1475 static void view_collection_autosize(ViewIface
*view
)
1477 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1478 FilerWindow
*filer_window
= view_collection
->filer_window
;
1479 Collection
*collection
= view_collection
->collection
;
1481 int w
= collection
->item_width
;
1482 int h
= collection
->item_height
;
1485 int max_x
, max_rows
;
1486 const float r
= 2.5;
1490 /* Get the extra height required for the toolbar and minibuffer,
1493 if (o_toolbar
.int_value
!= TOOLBAR_NONE
)
1494 t
= filer_window
->toolbar
->allocation
.height
;
1495 if (filer_window
->message
)
1496 t
+= filer_window
->message
->allocation
.height
;
1497 if (GTK_WIDGET_VISIBLE(filer_window
->minibuffer_area
))
1501 gtk_widget_size_request(filer_window
->minibuffer_area
, &req
);
1502 space
= req
.height
+ 2;
1506 n
= collection
->number_of_items
;
1508 h
= ICON_HEIGHT
* 1.5;
1511 max_x
= (o_filer_size_limit
.int_value
* screen_width
) / 100;
1512 max_rows
= (o_filer_size_limit
.int_value
* screen_height
) / (h
* 100);
1514 /* Aim for a size where
1515 * x = r(y + t + h), (1)
1516 * unless that's too wide.
1518 * t = toolbar (and minibuffer) height
1519 * r = desired (width / height) ratio
1521 * Want to display all items:
1524 * => x(x/r - t - h) = nwh (from 1)
1525 * => xx - x.rt - hr(1 - nw) = 0
1526 * => 2x = rt +/- sqrt(rt.rt + 4hr(nw - 1))
1530 * sqrt(rt.rt + ...) > rt
1532 * So, the +/- must be +:
1534 * => x = (rt + sqrt(rt.rt + 4hr(nw - 1))) / 2
1536 * ( + w - 1 to round up)
1538 x
= (r
* t
+ sqrt(r
*r
*t
*t
+ 4*h
*r
* (n
*w
- 1))) / 2 + w
- 1;
1545 cols
= MAX(cols
, 1);
1547 /* Choose rows to display all items given our chosen x.
1548 * Don't make the window *too* big!
1550 rows
= (n
+ cols
- 1) / cols
;
1551 if (rows
> max_rows
)
1554 /* Leave some room for extra icons, but only in Small Icons mode
1555 * otherwise it takes up too much space.
1556 * Also, don't add space if the minibuffer is open.
1559 space
= filer_window
->display_style
== SMALL_ICONS
? h
: 2;
1561 filer_window_set_size(filer_window
,
1563 h
* MAX(rows
, 1) + space
);
1566 static gboolean
view_collection_cursor_visible(ViewIface
*view
)
1568 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1569 Collection
*collection
= view_collection
->collection
;
1571 return collection
->cursor_item
!= -1;
1574 static void view_collection_set_base(ViewIface
*view
, ViewIter
*iter
)
1576 ViewCollection
*view_collection
= VIEW_COLLECTION(view
);
1578 view_collection
->cursor_base
= iter
->i
;
1581 static void view_collection_start_lasso_box(ViewIface
*view
,
1582 GdkEventButton
*event
)
1584 ViewCollection
*view_collection
= (ViewCollection
*) view
;
1585 Collection
*collection
= view_collection
->collection
;
1587 collection_lasso_box(collection
, event
->x
, event
->y
);