Commit 27b5e3d0 authored by Jim Nelson's avatar Jim Nelson

#2262: Always show master file when Shift key is pressed, even if external edit is in place.

parent 5673e27f
......@@ -26,7 +26,7 @@ public class MimicManager : Object {
return;
try {
writer.write(photo.get_original_pixbuf(Scaling.for_original(), false), Jpeg.Quality.HIGH);
writer.write(photo.get_master_pixbuf(Scaling.for_original(), false), Jpeg.Quality.HIGH);
} catch (Error err) {
this.err = err;
}
......
......@@ -633,7 +633,7 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
bool ctrl_currently_pressed, alt_currently_pressed, shift_currently_pressed,
super_currently_pressed;
get_modifiers(out ctrl_currently_pressed, out alt_currently_pressed,
out shift_currently_pressed, out super_currently_pressed);
out shift_currently_pressed, out super_currently_pressed);
switch (Gdk.keyval_name(event.keyval)) {
case "Control_L":
......@@ -672,7 +672,7 @@ public abstract class Page : Gtk.ScrolledWindow, SidebarPage {
super_pressed = true;
return on_super_pressed(event);
return on_super_pressed(event);
}
return on_app_key_pressed(event);
......
......@@ -117,17 +117,16 @@ public enum ImportResult {
}
}
// Specifies how pixel data is fetched from the backing file on disk. SOURCE mode means "give me
// pixel data that tries to be as faithful to the backing source photo as possible, even if it
// sacrifices a bit of performance," whereas BASELINE means "give me the image most suitable for
// use as a base image when running the transformation pipeline at interactive speeds, even if it
// means I give up some fidelity to the source image."
// Specifies how pixel data is fetched from the backing file on disk. MASTER is the original
// backing photo of any supported photo file format; SOURCE is either the master or the editable
// file, that is, the appropriate reference file for user display; BASELINE is an appropriate source
// file with the proviso that it may be a suitable substitute for the master and/or the editable.
//
// In general, callers want to use the BASELINE unless requirements are specific.
public enum BackingFetchMode {
SOURCE,
BASELINE
// TODO: in the future, we could add MASTER, MIMIC, etc., but these might be too low-level; the
// nice thing about SOURCE and BASELINE are that operate at the level of the programmer's
// intent, not the underlying implementation
BASELINE,
MASTER
}
public class PhotoImportParams {
......@@ -497,6 +496,24 @@ public abstract class TransformablePhoto: PhotoSource {
return (flags & PhotoFileFormatFlags.MIMIC_RECOMMENDED) != 0;
}
private PhotoFileReader get_backing_reader(BackingFetchMode mode) {
switch (mode) {
case BackingFetchMode.MASTER:
return get_master_reader();
case BackingFetchMode.BASELINE:
return get_baseline_reader();
case BackingFetchMode.SOURCE:
return get_source_reader();
default:
error("Unknown backing fetch mode %s", mode.to_string());
return get_baseline_reader();
}
}
private PhotoFileReader get_master_reader() {
lock (readers) {
return readers.master;
......@@ -1934,13 +1951,7 @@ public abstract class TransformablePhoto: PhotoSource {
private Gdk.Pixbuf load_raw_pixbuf(Scaling scaling, Exception exceptions,
BackingFetchMode fetch_mode = BackingFetchMode.BASELINE) throws Error {
PhotoFileReader loader = null;
if (fetch_mode == BackingFetchMode.SOURCE)
loader = get_source_reader();
else if (fetch_mode == BackingFetchMode.BASELINE)
loader = get_baseline_reader();
else
error("unsupported BackingFetchMode enumeration value");
PhotoFileReader loader = get_backing_reader(fetch_mode);
// no scaling, load and get out
if (scaling.is_unscaled()) {
......@@ -1976,9 +1987,9 @@ public abstract class TransformablePhoto: PhotoSource {
return pixbuf;
}
// Returns a raw, untransformed, scaled pixbuf from the source that has been optionally rotated
// Returns a raw, untransformed, scaled pixbuf from the master that has been optionally rotated
// according to its original EXIF settings.
public Gdk.Pixbuf get_original_pixbuf(Scaling scaling, bool rotate = true) throws Error {
public Gdk.Pixbuf get_master_pixbuf(Scaling scaling, bool rotate = true) throws Error {
#if MEASURE_PIPELINE
Timer timer = new Timer();
Timer total_timer = new Timer();
......@@ -1997,7 +2008,7 @@ public abstract class TransformablePhoto: PhotoSource {
}
// load-and-decode and scale
Gdk.Pixbuf pixbuf = load_raw_pixbuf(scaling, Exception.NONE);
Gdk.Pixbuf pixbuf = load_raw_pixbuf(scaling, Exception.NONE, BackingFetchMode.MASTER);
// orientation
#if MEASURE_PIPELINE
......@@ -2008,7 +2019,7 @@ public abstract class TransformablePhoto: PhotoSource {
#if MEASURE_PIPELINE
orientation_time = timer.elapsed();
debug("ORIGINAL PIPELINE %s (%s): orientation=%lf total=%lf", to_string(), scaling.to_string(),
debug("MASTER PIPELINE %s (%s): orientation=%lf total=%lf", to_string(), scaling.to_string(),
orientation_time, total_timer.elapsed());
#endif
......
......@@ -389,7 +389,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
private uint32 last_nav_key = 0;
private bool photo_missing = false;
private PixbufCache cache = null;
private PixbufCache original_cache = null;
private PixbufCache master_cache = null;
private PhotoDragAndDropHandler dnd_handler = null;
private bool enable_interactive_zoom_refresh = false;
private Gdk.Point zoom_pan_start_point;
......@@ -786,13 +786,13 @@ public abstract class EditingHostPage : SinglePhotoPage {
private void on_selection_changed(Gee.Iterable<DataView> selected) {
foreach (DataView view in selected) {
replace_photo(controller, (TransformablePhoto) view.get_source());
replace_photo(controller, (Photo) view.get_source());
break;
}
}
private void rebuild_caches(string caller) {
Scaling scaling = get_canvas_scaling();
Scaling scaling = get_canvas_scaling();
// only rebuild if not the same scaling
if (cache != null && cache.get_scaling().equals(scaling))
......@@ -807,16 +807,20 @@ public abstract class EditingHostPage : SinglePhotoPage {
cache.cancel_all();
}
cache = new PixbufCache(sources, PixbufCache.PhotoType.REGULAR, scaling, PIXBUF_CACHE_COUNT);
cache = new PixbufCache(sources, PixbufCache.PhotoType.NORMAL, scaling, PIXBUF_CACHE_COUNT);
cache.fetched.connect(on_pixbuf_fetched);
original_cache = new PixbufCache(sources, PixbufCache.PhotoType.ORIGINAL, scaling,
ORIGINAL_PIXBUF_CACHE_COUNT);
master_cache = new PixbufCache(sources, PixbufCache.PhotoType.MASTER, scaling,
ORIGINAL_PIXBUF_CACHE_COUNT, master_cache_filter);
if (has_photo())
prefetch_neighbors(controller, get_photo());
}
private bool master_cache_filter(Photo photo) {
return photo.has_transformations() || photo.has_editable();
}
private void on_pixbuf_fetched(TransformablePhoto photo, Gdk.Pixbuf? pixbuf, Error? err) {
// if not of the current photo, nothing more to do
if (!photo.equals(get_photo()))
......@@ -828,7 +832,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
zoom_buffer.update_preview_image(pixbuf);
// if no tool, use the pixbuf directly, otherwise, let the tool decide what should be
// displayed
// displayed
Dimensions max_dim = photo.get_dimensions();
if (current_tool != null) {
try {
......@@ -851,11 +855,9 @@ public abstract class EditingHostPage : SinglePhotoPage {
}
}
private void prefetch_neighbors(ViewCollection controller, TransformablePhoto photo) {
private void prefetch_neighbors(ViewCollection controller, Photo photo) {
cache.prefetch(photo, BackgroundJob.JobPriority.HIGHEST);
if (photo.has_transformations())
original_cache.prefetch(photo, BackgroundJob.JobPriority.LOW);
master_cache.prefetch(photo, BackgroundJob.JobPriority.LOW);
DataSource next_source, prev_source;
if (!controller.get_immediate_neighbors(photo, out next_source, out prev_source))
......@@ -866,45 +868,43 @@ public abstract class EditingHostPage : SinglePhotoPage {
// prefetch the immediate neighbors and their outer neighbors, for plenty of readahead
foreach (DataSource neighbor_source in controller.get_extended_neighbors(photo)) {
TransformablePhoto neighbor = (TransformablePhoto) neighbor_source;
Photo neighbor = (Photo) neighbor_source;
BackgroundJob.JobPriority priority = BackgroundJob.JobPriority.NORMAL;
if (neighbor.equals(next) || neighbor.equals(prev))
priority = BackgroundJob.JobPriority.HIGH;
cache.prefetch(neighbor, priority);
if (neighbor.has_transformations())
original_cache.prefetch(neighbor, BackgroundJob.JobPriority.LOWEST);
master_cache.prefetch(neighbor, BackgroundJob.JobPriority.LOWEST);
}
}
// Cancels prefetches of old neighbors, but does not cancel them if they are the new
// neighbors
private void cancel_prefetch_neighbors(ViewCollection old_controller, TransformablePhoto old_photo,
ViewCollection new_controller, TransformablePhoto new_photo) {
Gee.Set<TransformablePhoto> old_neighbors = (Gee.Set<TransformablePhoto>)
private void cancel_prefetch_neighbors(ViewCollection old_controller, Photo old_photo,
ViewCollection new_controller, Photo new_photo) {
Gee.Set<Photo> old_neighbors = (Gee.Set<Photo>)
old_controller.get_extended_neighbors(old_photo);
Gee.Set<TransformablePhoto> new_neighbors = (Gee.Set<TransformablePhoto>)
Gee.Set<Photo> new_neighbors = (Gee.Set<Photo>)
new_controller.get_extended_neighbors(new_photo);
foreach (TransformablePhoto old_neighbor in old_neighbors) {
foreach (Photo old_neighbor in old_neighbors) {
// cancel prefetch and drop from cache if old neighbor is not part of the new
// neighborhood
if (!new_neighbors.contains(old_neighbor) && !new_photo.equals(old_neighbor)) {
cache.drop(old_neighbor);
original_cache.drop(old_neighbor);
master_cache.drop(old_neighbor);
}
}
// do same for old photo
if (!new_neighbors.contains(old_photo) && !new_photo.equals(old_photo)) {
cache.drop(old_photo);
original_cache.drop(old_photo);
master_cache.drop(old_photo);
}
}
protected void display(ViewCollection controller, TransformablePhoto photo) {
protected void display(ViewCollection controller, Photo photo) {
assert(controller.get_view_for_source(photo) != null);
replace_photo(controller, photo);
......@@ -967,7 +967,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
return true;
}
protected void replace_photo(ViewCollection new_controller, TransformablePhoto new_photo) {
protected void replace_photo(ViewCollection new_controller, Photo new_photo) {
ViewCollection old_controller = this.controller;
controller = new_controller;
......@@ -989,7 +989,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
deactivate_tool();
// swap out new photo and old photo and process change
TransformablePhoto old_photo = get_photo();
Photo old_photo = get_photo();
set_photo(new_photo);
set_page_name(new_photo.get_name());
......@@ -1145,9 +1145,8 @@ public abstract class EditingHostPage : SinglePhotoPage {
private override bool on_shift_pressed(Gdk.EventKey? event) {
// show quick compare of original only if no tool is in use, the original pixbuf is handy
if (current_tool == null && !get_ctrl_pressed() && !get_alt_pressed()) {
if (current_tool == null && !get_ctrl_pressed() && !get_alt_pressed())
swap_in_original();
}
return base.on_shift_pressed(event);
}
......@@ -1174,20 +1173,21 @@ public abstract class EditingHostPage : SinglePhotoPage {
}
private void swap_in_original() {
Gdk.Pixbuf original = original_cache.get_ready_pixbuf(get_photo());
if (original != null) {
// store what's currently displayed only for the duration of the shift pressing
swapped = get_unscaled_pixbuf();
// save the zoom state and cancel zoom so that the user can see all of the original
// photo
if (zoom_slider.get_value() != 0.0) {
save_zoom_state();
cancel_zoom();
}
Gdk.Pixbuf? original = master_cache.get_ready_pixbuf(get_photo());
if (original == null)
return;
// store what's currently displayed only for the duration of the shift pressing
swapped = get_unscaled_pixbuf();
set_pixbuf(original, get_photo().get_original_dimensions());
// save the zoom state and cancel zoom so that the user can see all of the original
// photo
if (zoom_slider.get_value() != 0.0) {
save_zoom_state();
cancel_zoom();
}
set_pixbuf(original, get_photo().get_original_dimensions());
}
private void swap_out_original() {
......@@ -1380,12 +1380,12 @@ public abstract class EditingHostPage : SinglePhotoPage {
private bool on_fetch_original() {
if (has_photo())
original_cache.prefetch(get_photo(), BackgroundJob.JobPriority.LOW);
master_cache.prefetch(get_photo(), BackgroundJob.JobPriority.LOW);
return false;
}
private bool is_panning_possible() {
private bool is_panning_possible() {
// panning is impossible if all the content to be drawn completely fits on the drawing
// canvas
Dimensions content_dim = {0};
......@@ -1891,7 +1891,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
if (next == null)
return;
TransformablePhoto next_photo = next.get_source() as TransformablePhoto;
Photo next_photo = next.get_source() as Photo;
if (next_photo != null)
replace_photo(controller, next_photo);
}
......@@ -1910,7 +1910,7 @@ public abstract class EditingHostPage : SinglePhotoPage {
if (previous == null)
return;
TransformablePhoto previous_photo = previous.get_source() as TransformablePhoto;
Photo previous_photo = previous.get_source() as Photo;
if (previous_photo != null)
replace_photo(controller, previous_photo);
}
......
......@@ -5,21 +5,23 @@
*/
public class PixbufCache : Object {
public delegate bool CacheFilter(Photo photo);
public enum PhotoType {
REGULAR,
ORIGINAL
NORMAL,
MASTER
}
private abstract class FetchJob : BackgroundJob {
public BackgroundJob.JobPriority priority;
public TransformablePhoto photo;
public Photo photo;
public Scaling scaling;
public Gdk.Pixbuf pixbuf = null;
public Error err = null;
private Semaphore completion_semaphore = new Semaphore();
public FetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, TransformablePhoto photo,
public FetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, Photo photo,
Scaling scaling, CompletionCallback callback) {
base(owner, callback, new Cancellable());
......@@ -39,8 +41,8 @@ public class PixbufCache : Object {
}
}
private class RegularFetchJob : FetchJob {
public RegularFetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, TransformablePhoto photo,
private class NormalFetchJob : FetchJob {
public NormalFetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, Photo photo,
Scaling scaling, CompletionCallback callback) {
base(owner, priority, photo, scaling, callback);
}
......@@ -54,15 +56,15 @@ public class PixbufCache : Object {
}
}
private class OriginalFetchJob : FetchJob {
public OriginalFetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, TransformablePhoto photo,
private class MasterFetchJob : FetchJob {
public MasterFetchJob(PixbufCache owner, BackgroundJob.JobPriority priority, Photo photo,
Scaling scaling, CompletionCallback callback) {
base(owner, priority, photo, scaling, callback);
}
public override void execute() {
try {
pixbuf = photo.get_original_pixbuf(scaling);
pixbuf = photo.get_master_pixbuf(scaling);
} catch (Error err) {
this.err = err;
}
......@@ -75,19 +77,20 @@ public class PixbufCache : Object {
private PhotoType type;
private int max_count;
private Scaling scaling;
private Gee.HashMap<TransformablePhoto, Gdk.Pixbuf> cache = new Gee.HashMap<TransformablePhoto,
Gdk.Pixbuf>();
private Gee.ArrayList<TransformablePhoto> lru = new Gee.ArrayList<TransformablePhoto>();
private Gee.HashMap<TransformablePhoto, FetchJob> in_progress = new Gee.HashMap<TransformablePhoto,
FetchJob>();
private CacheFilter? filter;
private Gee.HashMap<Photo, Gdk.Pixbuf> cache = new Gee.HashMap<Photo, Gdk.Pixbuf>();
private Gee.ArrayList<Photo> lru = new Gee.ArrayList<Photo>();
private Gee.HashMap<Photo, FetchJob> in_progress = new Gee.HashMap<Photo, FetchJob>();
public signal void fetched(TransformablePhoto photo, Gdk.Pixbuf? pixbuf, Error? err);
public signal void fetched(Photo photo, Gdk.Pixbuf? pixbuf, Error? err);
public PixbufCache(SourceCollection sources, PhotoType type, Scaling scaling, int max_count) {
public PixbufCache(SourceCollection sources, PhotoType type, Scaling scaling, int max_count,
CacheFilter? filter = null) {
this.sources = sources;
this.type = type;
this.scaling = scaling;
this.max_count = max_count;
this.filter = filter;
assert(max_count > 0);
......@@ -116,13 +119,13 @@ public class PixbufCache : Object {
}
// This call never blocks. Returns null if the pixbuf is not present.
public Gdk.Pixbuf? get_ready_pixbuf(TransformablePhoto photo) {
public Gdk.Pixbuf? get_ready_pixbuf(Photo photo) {
return get_cached(photo);
}
// This call can potentially block if the pixbuf is not in the cache. Once loaded, it will
// be cached. No signal is fired.
public Gdk.Pixbuf? fetch(TransformablePhoto photo) throws Error {
public Gdk.Pixbuf? fetch(Photo photo) throws Error {
Gdk.Pixbuf pixbuf = get_cached(photo);
if (pixbuf != null) {
#if TRACE_PIXBUF_CACHE
......@@ -155,14 +158,14 @@ public class PixbufCache : Object {
// This can be used to clear specific pixbufs from the cache, allowing finer control over what
// pixbufs remain and avoid being dropped when other fetches follow. It implicitly cancels
// any outstanding prefetches for the photo.
public void drop(TransformablePhoto photo) {
public void drop(Photo photo) {
cancel_prefetch(photo);
decache(photo);
}
// This call signals the cache to pre-load the pixbuf for the photo. When loaded the fetched
// signal is fired.
public void prefetch(TransformablePhoto photo,
public void prefetch(Photo photo,
BackgroundJob.JobPriority priority = BackgroundJob.JobPriority.NORMAL, bool force = false) {
if (!force && cache.contains(photo))
return;
......@@ -170,14 +173,17 @@ public class PixbufCache : Object {
if (in_progress.contains(photo))
return;
if (filter != null && !filter(photo))
return;
FetchJob job = null;
switch (type) {
case PhotoType.REGULAR:
job = new RegularFetchJob(this, priority, photo, scaling, on_fetched);
case PhotoType.NORMAL:
job = new NormalFetchJob(this, priority, photo, scaling, on_fetched);
break;
case PhotoType.ORIGINAL:
job = new OriginalFetchJob(this, priority, photo, scaling, on_fetched);
case PhotoType.MASTER:
job = new MasterFetchJob(this, priority, photo, scaling, on_fetched);
break;
default:
......@@ -192,13 +198,13 @@ public class PixbufCache : Object {
// This call signals the cache to pre-load the pixbufs for all supplied photos. Each fires
// the fetch signal as they arrive.
public void prefetch_many(Gee.Collection<TransformablePhoto> photos,
public void prefetch_many(Gee.Collection<Photo> photos,
BackgroundJob.JobPriority priority = BackgroundJob.JobPriority.NORMAL, bool force = false) {
foreach (TransformablePhoto photo in photos)
foreach (Photo photo in photos)
prefetch(photo, priority, force);
}
public bool cancel_prefetch(TransformablePhoto photo) {
public bool cancel_prefetch(Photo photo) {
FetchJob job = in_progress.get(photo);
if (job == null)
return false;
......@@ -249,11 +255,11 @@ public class PixbufCache : Object {
}
private void on_source_altered(DataObject object) {
TransformablePhoto photo = object as TransformablePhoto;
Photo photo = object as Photo;
assert(photo != null);
// only interested if in this cache and not an originals cache, as they never alter
if (!cache.contains(photo) && type != PhotoType.ORIGINAL)
if (!cache.contains(photo) && type != PhotoType.MASTER)
return;
decache(photo);
......@@ -267,14 +273,14 @@ public class PixbufCache : Object {
private void on_sources_removed(Gee.Iterable<DataObject> removed) {
foreach (DataObject object in removed) {
TransformablePhoto photo = object as TransformablePhoto;
Photo photo = object as Photo;
assert(photo != null);
decache(photo);
}
}
private Gdk.Pixbuf? get_cached(TransformablePhoto photo) {
private Gdk.Pixbuf? get_cached(Photo photo) {
Gdk.Pixbuf pixbuf = cache.get(photo);
if (pixbuf == null)
return null;
......@@ -291,7 +297,7 @@ public class PixbufCache : Object {
return pixbuf;
}
private void encache(TransformablePhoto photo, Gdk.Pixbuf pixbuf) {
private void encache(Photo photo, Gdk.Pixbuf pixbuf) {
// if already in cache, remove (means it was re-fetched, probably due to modification)
decache(photo);
......@@ -299,7 +305,7 @@ public class PixbufCache : Object {
lru.insert(0, photo);
while (lru.size > max_count) {
TransformablePhoto cached_photo = lru.remove_at(lru.size - 1);
Photo cached_photo = lru.remove_at(lru.size - 1);
assert(cached_photo != null);
bool removed = cache.unset(cached_photo);
......@@ -309,7 +315,7 @@ public class PixbufCache : Object {
assert(lru.size == cache.size);
}
private void decache(TransformablePhoto photo) {
private void decache(Photo photo) {
if (!cache.remove(photo)) {
assert(!lru.contains(photo));
......
......@@ -15,7 +15,7 @@ class SlideshowPage : SinglePhotoPage {
private SourceCollection sources;
private ViewCollection controller;
private TransformablePhoto current;
private Photo current;
private Gtk.ToolButton play_pause_button;
private Gtk.ToolButton settings_button;
private PixbufCache cache = null;
......@@ -94,7 +94,7 @@ class SlideshowPage : SinglePhotoPage {
}
}
public SlideshowPage(SourceCollection sources, ViewCollection controller, TransformablePhoto start) {
public SlideshowPage(SourceCollection sources, ViewCollection controller, Photo start) {
base(_("Slideshow"), true);
this.sources = sources;
......@@ -143,7 +143,7 @@ class SlideshowPage : SinglePhotoPage {
base.switched_to();
// create a cache for the size of this display
cache = new PixbufCache(sources, PixbufCache.PhotoType.REGULAR, get_canvas_scaling(),
cache = new PixbufCache(sources, PixbufCache.PhotoType.NORMAL, get_canvas_scaling(),
READAHEAD_COUNT);
Gdk.Pixbuf pixbuf;
......@@ -169,7 +169,7 @@ class SlideshowPage : SinglePhotoPage {
exiting = true;
}
private bool get_next_photo(TransformablePhoto start, Direction direction, out TransformablePhoto next,
private bool get_next_photo(Photo start, Direction direction, out Photo next,
out Gdk.Pixbuf next_pixbuf) {
next = start;
......@@ -185,7 +185,7 @@ class SlideshowPage : SinglePhotoPage {
view = (direction == Direction.FORWARD)
? controller.get_next(view)
: controller.get_previous(view);
next = (TransformablePhoto) view.get_source();
next = (Photo) view.get_source();
// An entire slideshow set might be missing, so check for a loop.
if ((next == start && next != current) || next == current) {
......@@ -205,15 +205,14 @@ class SlideshowPage : SinglePhotoPage {
// one normal, and the extended neighbors lowest, to recognize immediate needs
DataSource forward, back;
controller.get_immediate_neighbors(next, out forward, out back);
cache.prefetch((TransformablePhoto) forward, BackgroundJob.JobPriority.HIGHEST);
cache.prefetch((TransformablePhoto) back, BackgroundJob.JobPriority.NORMAL);
cache.prefetch((Photo) forward, BackgroundJob.JobPriority.HIGHEST);
cache.prefetch((Photo) back, BackgroundJob.JobPriority.NORMAL);
Gee.Set<DataSource> neighbors = controller.get_extended_neighbors(next);
neighbors.remove(forward);
neighbors.remove(back);
cache.prefetch_many((Gee.Collection<TransformablePhoto>) neighbors,
BackgroundJob.JobPriority.LOWEST);
cache.prefetch_many((Gee.Collection<Photo>) neighbors, BackgroundJob.JobPriority.LOWEST);
return true;
}
......@@ -238,15 +237,15 @@ class SlideshowPage : SinglePhotoPage {
private void on_previous() {
DataView view = controller.get_view_for_source(current);
advance((TransformablePhoto) controller.get_previous(view).get_source(), Direction.BACKWARD);
advance((Photo) controller.get_previous(view).get_source(), Direction.BACKWARD);
}
private void on_next() {
DataView view = controller.get_view_for_source(current);
advance((TransformablePhoto) controller.get_next(view).get_source(), Direction.FORWARD);
advance((Photo) controller.get_next(view).get_source(), Direction.FORWARD);
}
private void advance(TransformablePhoto photo, Direction direction) {
private void advance(Photo photo, Direction direction) {
current = photo;
// set pixbuf
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment