Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java	(revision 31278)
@@ -12,101 +12,107 @@
 public abstract class MapillaryAbstractImage {
 
-	/** Postion of the picture */
-	public final LatLon latLon;
-	/** Direction of the picture */
-	public final double ca;
-	public boolean isModified = false;
-	/** Temporal position of the picture until it is uplaoded */
-	public LatLon tempLatLon;
-	/**
-	 * When the object is being dragged in the map, the temporal position is
-	 * stored here
-	 */
-	public LatLon movingLatLon;
-	/** Temporal direction of the picture until it is uplaoded */
-	public double tempCa;
-	/**
-	 * When the object direction is being moved in the map, the temporal
-	 * direction is stored here
-	 */
-	protected double movingCa;
+    /** Postion of the picture */
+    public final LatLon latLon;
+    /** Direction of the picture */
+    public final double ca;
+    public boolean isModified = false;
+    /** Temporal position of the picture until it is uplaoded */
+    public LatLon tempLatLon;
+    /**
+     * When the object is being dragged in the map, the temporal position is
+     * stored here
+     */
+    public LatLon movingLatLon;
+    /** Temporal direction of the picture until it is uplaoded */
+    public double tempCa;
+    /**
+     * When the object direction is being moved in the map, the temporal
+     * direction is stored here
+     */
+    protected double movingCa;
 
-	public MapillaryAbstractImage(double lat, double lon, double ca) {
-		this.latLon = new LatLon(lat, lon);
-		this.tempLatLon = this.latLon;
-		this.movingLatLon = this.latLon;
-		this.ca = ca;
-		this.tempCa = ca;
-		this.movingCa = ca;
-	}
+    public MapillaryAbstractImage(double lat, double lon, double ca) {
+        this.latLon = new LatLon(lat, lon);
+        this.tempLatLon = this.latLon;
+        this.movingLatLon = this.latLon;
+        this.ca = ca;
+        this.tempCa = ca;
+        this.movingCa = ca;
+    }
 
-	/**
-	 * Returns whether the object has been modified or not.
-	 * 
-	 * @return true if the object has been modified; false otherwise.
-	 */
-	public boolean isModified() {
-		return this.isModified;
-	}
+    /**
+     * Returns whether the object has been modified or not.
+     * 
+     * @return true if the object has been modified; false otherwise.
+     */
+    public boolean isModified() {
+        return this.isModified;
+    }
 
-	/**
-	 * Returns a LatLon object containing the coordintes of the object.
-	 * 
-	 * @return The LatLon object with the position of the object.
-	 */
-	public LatLon getLatLon() {
-		return movingLatLon;
-	}
+    /**
+     * Returns a LatLon object containing the current coordinates of the object.
+     * When you are dragging the image this changes.
+     * 
+     * @return The LatLon object with the position of the object.
+     */
+    public LatLon getLatLon() {
+        return movingLatLon;
+    }
 
-	public LatLon getTempLatLon() {
-		return tempLatLon;
-	}
+    /**
+     * Returns the last fixed coorditanes of the object.
+     * 
+     * @return
+     */
+    public LatLon getTempLatLon() {
+        return tempLatLon;
+    }
 
-	/**
-	 * Moves the image temporally to another position
-	 * 
-	 * @param pos
-	 */
-	public void move(double x, double y) {
-		this.movingLatLon = new LatLon(this.tempLatLon.getY() + y,
-				this.tempLatLon.getX() + x);
-		this.isModified = true;
-	}
+    /**
+     * Moves the image temporally to another position
+     * 
+     * @param pos
+     */
+    public void move(double x, double y) {
+        this.movingLatLon = new LatLon(this.tempLatLon.getY() + y,
+                this.tempLatLon.getX() + x);
+        this.isModified = true;
+    }
 
-	/**
-	 * Turns the image direction.
-	 * 
-	 * @param ca
-	 */
-	public void turn(double ca) {
-		this.movingCa = this.tempCa + ca;
-		this.isModified = true;
-	}
+    /**
+     * Turns the image direction.
+     * 
+     * @param ca
+     */
+    public void turn(double ca) {
+        this.movingCa = this.tempCa + ca;
+        this.isModified = true;
+    }
 
-	/**
-	 * Called when the mouse button is released, meaning that the picture has
-	 * stopped being dragged.
-	 */
-	public void stopMoving() {
-		this.tempLatLon = this.movingLatLon;
-		this.tempCa = this.movingCa;
-	}
+    /**
+     * Called when the mouse button is released, meaning that the picture has
+     * stopped being dragged.
+     */
+    public void stopMoving() {
+        this.tempLatLon = this.movingLatLon;
+        this.tempCa = this.movingCa;
+    }
 
-	/**
-	 * Returns the direction towards the image has been taken.
-	 * 
-	 * @return The direction of the image (0 means north and goes clockwise).
-	 */
-	public double getCa() {
-		return movingCa;
-	}
+    /**
+     * Returns the direction towards the image has been taken.
+     * 
+     * @return The direction of the image (0 means north and goes clockwise).
+     */
+    public double getCa() {
+        return movingCa;
+    }
 
-	/**
-	 * Returns the last fixed direction of the object.
-	 * 
-	 * @return
-	 */
-	public double getTempCa() {
-		return tempCa;
-	}
+    /**
+     * Returns the last fixed direction of the object.
+     * 
+     * @return
+     */
+    public double getTempCa() {
+        return tempCa;
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java	(revision 31278)
@@ -20,274 +20,274 @@
  */
 public class MapillaryData implements ICachedLoaderListener {
-	public volatile static MapillaryData INSTANCE;
-
-	private final List<MapillaryAbstractImage> images;
-	private MapillaryAbstractImage selectedImage;
-	private MapillaryAbstractImage hoveredImage;
-	private final List<MapillaryAbstractImage> multiSelectedImages;
-
-	private List<MapillaryDataListener> listeners = new ArrayList<>();
-
-	public MapillaryData() {
-		images = new CopyOnWriteArrayList<>();
-		multiSelectedImages = new ArrayList<>();
-		selectedImage = null;
-	}
-
-	public static MapillaryData getInstance() {
-		if (INSTANCE == null) {
-			INSTANCE = new MapillaryData();
-		}
-		return INSTANCE;
-	}
-
-	/**
-	 * Adds a set of MapillaryImages to the object, and then repaints mapView.
-	 * 
-	 * @param images
-	 *            The set of images to be added.
-	 */
-	public synchronized void add(List<MapillaryAbstractImage> images) {
-		for (MapillaryAbstractImage image : images) {
-			add(image);
-		}
-	}
-
-	/**
-	 * Adds an MapillaryImage to the object, and then repaints mapView.
-	 * 
-	 * @param image
-	 *            The image to be added.
-	 */
-	public synchronized void add(MapillaryAbstractImage image) {
-		if (!images.contains(image)) {
-			this.images.add(image);
-		}
-		dataUpdated();
-	}
-
-	public void addListener(MapillaryDataListener lis) {
-		listeners.add(lis);
-	}
-
-	public void removeListener(MapillaryDataListener lis) {
-		listeners.remove(lis);
-	}
-
-	/**
-	 * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
-	 * This is needed for concurrency.
-	 * 
-	 * @param images
-	 *            The set of images to be added.
-	 */
-	public synchronized void addWithoutUpdate(
-			List<MapillaryAbstractImage> images) {
-		for (MapillaryAbstractImage image : images) {
-			addWithoutUpdate(image);
-		}
-	}
-
-	/**
-	 * Sets the image under the mouse cursor.
-	 * 
-	 * @param image
-	 */
-	public void setHoveredImage(MapillaryAbstractImage image) {
-		hoveredImage = image;
-	}
-
-	/**
-	 * Returns the image under the mouse cursor.
-	 * 
-	 * @return
-	 */
-	public MapillaryAbstractImage getHoveredImage() {
-		return hoveredImage;
-	}
-
-	/**
-	 * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
-	 * needed for concurrency.
-	 * 
-	 * @param image
-	 *            The image to be added.
-	 */
-	public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
-		if (!images.contains(image)) {
-			this.images.add(image);
-		}
-	}
-
-	/**
-	 * Repaints mapView object.
-	 */
-	public synchronized void dataUpdated() {
-		Main.map.mapView.repaint();
-	}
-
-	/**
-	 * Returns a List containing all images.
-	 * 
-	 * @return A List object containing all images.
-	 */
-	public List<MapillaryAbstractImage> getImages() {
-		return images;
-	}
-
-	/**
-	 * Returns the MapillaryImage object that is currently selected.
-	 * 
-	 * @return The selected MapillaryImage object.
-	 */
-	public MapillaryAbstractImage getSelectedImage() {
-		return selectedImage;
-	}
-
-	/**
-	 * If the selected MapillaryImage is part of a MapillarySequence then the
-	 * following MapillaryImage is selected. In case there is none, does
-	 * nothing.
-	 */
-	public void selectNext() {
-		if (getSelectedImage() instanceof MapillaryImage) {
-			if (getSelectedImage() == null)
-				return;
-			if (((MapillaryImage) getSelectedImage()).getSequence() == null)
-				return;
-			setSelectedImage(((MapillaryImage) getSelectedImage()).next(), true);
-		}
-	}
-
-	/**
-	 * If the selected MapillaryImage is part of a MapillarySequence then the
-	 * previous MapillaryImage is selected. In case there is none, does nothing.
-	 */
-	public void selectPrevious() {
-		if (getSelectedImage() instanceof MapillaryImage) {
-			if (getSelectedImage() == null)
-				return;
-			if (((MapillaryImage) getSelectedImage()).getSequence() == null)
-				throw new IllegalStateException();
-			setSelectedImage(((MapillaryImage) getSelectedImage()).previous(),
-					true);
-		}
-	}
-
-	/**
-	 * Selects a new image and then starts a new MapillaryImageDownloadThread
-	 * thread in order to download its surrounding thumbnails. If the user does
-	 * ctrl+click, this isn't triggered.
-	 * 
-	 * @param image
-	 *            The MapillaryImage which is going to be selected
-	 */
-	public void setSelectedImage(MapillaryAbstractImage image) {
-		setSelectedImage(image, false);
-	}
-
-	/**
-	 * Selects a new image and then starts a new MapillaryImageDownloadThread
-	 * thread in order to download its surrounding thumbnails. If the user does
-	 * ctrl+click, this isn't triggered. You can choose wheter to center the
-	 * view on the new image or not.
-	 * 
-	 * @param image
-	 * @param zoom
-	 */
-	public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
-		MapillaryAbstractImage oldImage = selectedImage;
-		selectedImage = image;
-		multiSelectedImages.clear();
-		multiSelectedImages.add(image);
-		if (image != null) {
-			if (image instanceof MapillaryImage) {
-				MapillaryImage mapillaryImage = (MapillaryImage) image;
-				if (mapillaryImage.next() != null) {
-					new MapillaryCache(mapillaryImage.next().getKey(),
-							MapillaryCache.Type.THUMBNAIL).submit(this, false);
-					if (mapillaryImage.next().next() != null)
-						new MapillaryCache(mapillaryImage.next().next()
-								.getKey(), MapillaryCache.Type.THUMBNAIL)
-								.submit(this, false);
-				}
-				if (mapillaryImage.previous() != null) {
-					new MapillaryCache(mapillaryImage.previous().getKey(),
-							MapillaryCache.Type.THUMBNAIL).submit(this, false);
-					if (mapillaryImage.previous().previous() != null)
-						new MapillaryCache(mapillaryImage.previous().previous()
-								.getKey(), MapillaryCache.Type.THUMBNAIL)
-								.submit(this, false);
-				}
-			}
-		}
-		if (zoom)
-			Main.map.mapView.zoomTo(MapillaryData.getInstance()
-					.getSelectedImage().getLatLon());
-		if (Main.map != null) {
-			Main.map.mapView.repaint();
-		}
-		fireSelectedImageChanged(oldImage, selectedImage);
-	}
-
-	private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
-			MapillaryAbstractImage newImage) {
-		if (listeners.isEmpty())
-			return;
-		for (MapillaryDataListener lis : listeners)
-			lis.selectedImageChanged(oldImage, newImage);
-	}
-
-	/**
-	 * Adds a MapillaryImage object to the list of selected images, (when ctrl +
-	 * click)
-	 * 
-	 * @param image
-	 *            The MapillaryImage object to be added.
-	 */
-	public void addMultiSelectedImage(MapillaryAbstractImage image) {
-		if (!this.multiSelectedImages.contains(image)) {
-			if (this.getSelectedImage() != null)
-				this.multiSelectedImages.add(image);
-			else
-				this.setSelectedImage(image);
-		}
-		Main.map.mapView.repaint();
-	}
-
-	/**
-	 * Adds a set of MapillaryImage objects to the list of selected images.
-	 * 
-	 * @param images
-	 */
-	public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
-		for (MapillaryAbstractImage image : images)
-			if (!this.multiSelectedImages.contains(image)) {
-				if (this.getSelectedImage() != null)
-					this.multiSelectedImages.add(image);
-				else
-					this.setSelectedImage(image);
-			}
-		Main.map.mapView.repaint();
-	}
-
-	/**
-	 * Returns a list containing all MapillaryImage objects selected with ctrl +
-	 * click
-	 * 
-	 * @return
-	 */
-	public List<MapillaryAbstractImage> getMultiSelectedImages() {
-		return multiSelectedImages;
-	}
-
-	/**
-	 * This is empty because it is used just to make sure that certain images
-	 * have already been downloaded.
-	 */
-	@Override
-	public void loadingFinished(CacheEntry data,
-			CacheEntryAttributes attributes, LoadResult result) {
-		// DO NOTHING
-	}
+    public volatile static MapillaryData INSTANCE;
+
+    private final List<MapillaryAbstractImage> images;
+    private MapillaryAbstractImage selectedImage;
+    private MapillaryAbstractImage hoveredImage;
+    private final List<MapillaryAbstractImage> multiSelectedImages;
+
+    private List<MapillaryDataListener> listeners = new ArrayList<>();
+
+    public MapillaryData() {
+        images = new CopyOnWriteArrayList<>();
+        multiSelectedImages = new ArrayList<>();
+        selectedImage = null;
+    }
+
+    public static MapillaryData getInstance() {
+        if (INSTANCE == null) {
+            INSTANCE = new MapillaryData();
+        }
+        return INSTANCE;
+    }
+
+    /**
+     * Adds a set of MapillaryImages to the object, and then repaints mapView.
+     * 
+     * @param images
+     *            The set of images to be added.
+     */
+    public synchronized void add(List<MapillaryAbstractImage> images) {
+        for (MapillaryAbstractImage image : images) {
+            add(image);
+        }
+    }
+
+    /**
+     * Adds an MapillaryImage to the object, and then repaints mapView.
+     * 
+     * @param image
+     *            The image to be added.
+     */
+    public synchronized void add(MapillaryAbstractImage image) {
+        if (!images.contains(image)) {
+            this.images.add(image);
+        }
+        dataUpdated();
+    }
+
+    public void addListener(MapillaryDataListener lis) {
+        listeners.add(lis);
+    }
+
+    public void removeListener(MapillaryDataListener lis) {
+        listeners.remove(lis);
+    }
+
+    /**
+     * Adds a set of MapillaryImages to the object, but doesn't repaint mapView.
+     * This is needed for concurrency.
+     * 
+     * @param images
+     *            The set of images to be added.
+     */
+    public synchronized void addWithoutUpdate(
+            List<MapillaryAbstractImage> images) {
+        for (MapillaryAbstractImage image : images) {
+            addWithoutUpdate(image);
+        }
+    }
+
+    /**
+     * Sets the image under the mouse cursor.
+     * 
+     * @param image
+     */
+    public void setHoveredImage(MapillaryAbstractImage image) {
+        hoveredImage = image;
+    }
+
+    /**
+     * Returns the image under the mouse cursor.
+     * 
+     * @return
+     */
+    public MapillaryAbstractImage getHoveredImage() {
+        return hoveredImage;
+    }
+
+    /**
+     * Adds a MapillaryImage to the object, but doesn't repaint mapView. This is
+     * needed for concurrency.
+     * 
+     * @param image
+     *            The image to be added.
+     */
+    public synchronized void addWithoutUpdate(MapillaryAbstractImage image) {
+        if (!images.contains(image)) {
+            this.images.add(image);
+        }
+    }
+
+    /**
+     * Repaints mapView object.
+     */
+    public synchronized void dataUpdated() {
+        Main.map.mapView.repaint();
+    }
+
+    /**
+     * Returns a List containing all images.
+     * 
+     * @return A List object containing all images.
+     */
+    public List<MapillaryAbstractImage> getImages() {
+        return images;
+    }
+
+    /**
+     * Returns the MapillaryImage object that is currently selected.
+     * 
+     * @return The selected MapillaryImage object.
+     */
+    public MapillaryAbstractImage getSelectedImage() {
+        return selectedImage;
+    }
+
+    /**
+     * If the selected MapillaryImage is part of a MapillarySequence then the
+     * following MapillaryImage is selected. In case there is none, does
+     * nothing.
+     */
+    public void selectNext() {
+        if (getSelectedImage() instanceof MapillaryImage) {
+            if (getSelectedImage() == null)
+                return;
+            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
+                return;
+            setSelectedImage(((MapillaryImage) getSelectedImage()).next(), true);
+        }
+    }
+
+    /**
+     * If the selected MapillaryImage is part of a MapillarySequence then the
+     * previous MapillaryImage is selected. In case there is none, does nothing.
+     */
+    public void selectPrevious() {
+        if (getSelectedImage() instanceof MapillaryImage) {
+            if (getSelectedImage() == null)
+                return;
+            if (((MapillaryImage) getSelectedImage()).getSequence() == null)
+                throw new IllegalStateException();
+            setSelectedImage(((MapillaryImage) getSelectedImage()).previous(),
+                    true);
+        }
+    }
+
+    /**
+     * Selects a new image and then starts a new MapillaryImageDownloadThread
+     * thread in order to download its surrounding thumbnails. If the user does
+     * ctrl+click, this isn't triggered.
+     * 
+     * @param image
+     *            The MapillaryImage which is going to be selected
+     */
+    public void setSelectedImage(MapillaryAbstractImage image) {
+        setSelectedImage(image, false);
+    }
+
+    /**
+     * Selects a new image and then starts a new MapillaryImageDownloadThread
+     * thread in order to download its surrounding thumbnails. If the user does
+     * ctrl+click, this isn't triggered. You can choose wheter to center the
+     * view on the new image or not.
+     * 
+     * @param image
+     * @param zoom
+     */
+    public void setSelectedImage(MapillaryAbstractImage image, boolean zoom) {
+        MapillaryAbstractImage oldImage = selectedImage;
+        selectedImage = image;
+        multiSelectedImages.clear();
+        multiSelectedImages.add(image);
+        if (image != null) {
+            if (image instanceof MapillaryImage) {
+                MapillaryImage mapillaryImage = (MapillaryImage) image;
+                if (mapillaryImage.next() != null) {
+                    new MapillaryCache(mapillaryImage.next().getKey(),
+                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
+                    if (mapillaryImage.next().next() != null)
+                        new MapillaryCache(mapillaryImage.next().next()
+                                .getKey(), MapillaryCache.Type.THUMBNAIL)
+                                .submit(this, false);
+                }
+                if (mapillaryImage.previous() != null) {
+                    new MapillaryCache(mapillaryImage.previous().getKey(),
+                            MapillaryCache.Type.THUMBNAIL).submit(this, false);
+                    if (mapillaryImage.previous().previous() != null)
+                        new MapillaryCache(mapillaryImage.previous().previous()
+                                .getKey(), MapillaryCache.Type.THUMBNAIL)
+                                .submit(this, false);
+                }
+            }
+        }
+        if (zoom)
+            Main.map.mapView.zoomTo(MapillaryData.getInstance()
+                    .getSelectedImage().getLatLon());
+        if (Main.map != null) {
+            Main.map.mapView.repaint();
+        }
+        fireSelectedImageChanged(oldImage, selectedImage);
+    }
+
+    private void fireSelectedImageChanged(MapillaryAbstractImage oldImage,
+            MapillaryAbstractImage newImage) {
+        if (listeners.isEmpty())
+            return;
+        for (MapillaryDataListener lis : listeners)
+            lis.selectedImageChanged(oldImage, newImage);
+    }
+
+    /**
+     * Adds a MapillaryImage object to the list of selected images, (when ctrl +
+     * click)
+     * 
+     * @param image
+     *            The MapillaryImage object to be added.
+     */
+    public void addMultiSelectedImage(MapillaryAbstractImage image) {
+        if (!this.multiSelectedImages.contains(image)) {
+            if (this.getSelectedImage() != null)
+                this.multiSelectedImages.add(image);
+            else
+                this.setSelectedImage(image);
+        }
+        Main.map.mapView.repaint();
+    }
+
+    /**
+     * Adds a set of MapillaryImage objects to the list of selected images.
+     * 
+     * @param images
+     */
+    public void addMultiSelectedImage(List<MapillaryAbstractImage> images) {
+        for (MapillaryAbstractImage image : images)
+            if (!this.multiSelectedImages.contains(image)) {
+                if (this.getSelectedImage() != null)
+                    this.multiSelectedImages.add(image);
+                else
+                    this.setSelectedImage(image);
+            }
+        Main.map.mapView.repaint();
+    }
+
+    /**
+     * Returns a list containing all MapillaryImage objects selected with ctrl +
+     * click
+     * 
+     * @return
+     */
+    public List<MapillaryAbstractImage> getMultiSelectedImages() {
+        return multiSelectedImages;
+    }
+
+    /**
+     * This is empty because it is used just to make sure that certain images
+     * have already been downloaded.
+     */
+    @Override
+    public void loadingFinished(CacheEntry data,
+            CacheEntryAttributes attributes, LoadResult result) {
+        // DO NOTHING
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java	(revision 31278)
@@ -2,9 +2,10 @@
 
 public interface MapillaryDataListener {
-	/**
-	 * Fired when the selected image is changed by something different from
-	 * manually clicking on the icon.
-	 */
-	public void selectedImageChanged(MapillaryAbstractImage oldImage, MapillaryAbstractImage newImage);
+    /**
+     * Fired when the selected image is changed by something different from
+     * manually clicking on the icon.
+     */
+    public void selectedImageChanged(MapillaryAbstractImage oldImage,
+            MapillaryAbstractImage newImage);
 
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java	(revision 31278)
@@ -14,142 +14,159 @@
  */
 public class MapillaryImage extends MapillaryAbstractImage {
-	/** Unique identifier of the object */
-	private final String key;
-	/** Sequence of pictures containing this object*/
-	private MapillarySequence sequence;
+    /** Unique identifier of the object */
+    private final String key;
+    /** Sequence of pictures containing this object */
+    private MapillarySequence sequence;
 
-	private long capturedAt;
-	private String user;
-	private List<String> signs;
-	private String location;
+    /** Epoch time when the image was taken. */
+    private long capturedAt;
+    /** The user that made the image */
+    private String user;
+    /** Set of traffic signs in the image */
+    private List<String> signs;
+    private String location;
 
-	public String getLocation() {
-		return location;
-	}
+    public String getLocation() {
+        return location;
+    }
 
-	public void setLocation(String location) {
-		this.location = location;
-	}
+    public void setLocation(String location) {
+        this.location = location;
+    }
 
-	/**
-	 * Main contructor of the class MapillaryImage
-	 * 
-	 * @param key
-	 *            The unique identifier of the image.
-	 * @param lat
-	 *            The latitude where it is positioned.
-	 * @param lon
-	 *            The longitude where it is positioned.
-	 * @param ca
-	 *            The direction of the images in degrees, meaning 0 north.
-	 */
-	public MapillaryImage(String key, double lat, double lon, double ca) {
-		super(lat, lon, ca);
-		this.key = key;
-		this.signs = new ArrayList<>();
-	}
+    /**
+     * Main contructor of the class MapillaryImage
+     * 
+     * @param key
+     *            The unique identifier of the image.
+     * @param lat
+     *            The latitude where it is positioned.
+     * @param lon
+     *            The longitude where it is positioned.
+     * @param ca
+     *            The direction of the images in degrees, meaning 0 north.
+     */
+    public MapillaryImage(String key, double lat, double lon, double ca) {
+        super(lat, lon, ca);
+        this.key = key;
+        this.signs = new ArrayList<>();
+    }
 
-	/**
-	 * Returns the unique identifier of the object.
-	 * 
-	 * @return A String containing the unique identifier of the object.
-	 */
-	public String getKey() {
-		return this.key;
-	}
-	
-	public void addSign(String sign) {
-		signs.add(sign);
-	}
-	
-	public List<String> getSigns() {
-		return signs;
-	}
+    /**
+     * Returns the unique identifier of the object.
+     * 
+     * @return A String containing the unique identifier of the object.
+     */
+    public String getKey() {
+        return this.key;
+    }
 
-	public void setCapturedAt(long capturedAt) {
-		this.capturedAt = capturedAt;
-	}
+    /**
+     * Adds a new sign to the set of signs.
+     * 
+     * @param sign
+     */
+    public void addSign(String sign) {
+        signs.add(sign);
+    }
 
-	public long getCapturedAt() {
-		return capturedAt;
-	}
+    public List<String> getSigns() {
+        return signs;
+    }
 
-	public void setUser(String user) {
-		this.user = user;
-	}
+    public void setCapturedAt(long capturedAt) {
+        this.capturedAt = capturedAt;
+    }
 
-	public String getUser() {
-		return user;
-	}
+    public long getCapturedAt() {
+        return capturedAt;
+    }
 
-	/**
-	 * Sets the MapillarySequence object which contains the MapillaryImage.
-	 * 
-	 * @param sequence
-	 *            The MapillarySequence that contains the MapillaryImage.
-	 */
-	public void setSequence(MapillarySequence sequence) {
-		this.sequence = sequence;
-	}
+    public void setUser(String user) {
+        this.user = user;
+    }
 
-	/**
-	 * Returns the sequence which contains this image.
-	 * 
-	 * @return The MapillarySequence object that contains this MapillaryImage.
-	 */
-	public MapillarySequence getSequence() {
-		return this.sequence;
-	}
+    public String getUser() {
+        return user;
+    }
 
-	public String toString() {
-		return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
-				+ this.latLon.lon() + ";ca=" + this.ca + "]";
-	}
+    /**
+     * Sets the MapillarySequence object which contains the MapillaryImage.
+     * 
+     * @param sequence
+     *            The MapillarySequence that contains the MapillaryImage.
+     */
+    public void setSequence(MapillarySequence sequence) {
+        this.sequence = sequence;
+    }
 
-	/**
-	 * If the MapillaryImage belongs to a MapillarySequence, returns the next
-	 * MapillarySequence in it.
-	 * 
-	 * @return The following MapillaryImage, or null if there is none.
-	 */
-	public MapillaryImage next() {
-		if (this.getSequence() == null)
-			return null;
-		return this.getSequence().next(this);
-	}
+    /**
+     * Returns the sequence which contains this image.
+     * 
+     * @return The MapillarySequence object that contains this MapillaryImage.
+     */
+    public MapillarySequence getSequence() {
+        return this.sequence;
+    }
 
-	/**
-	 * If the MapillaryImage belongs to a MapillarySequence, returns the
-	 * previous MapillarySequence in it.
-	 * 
-	 * @return The previous MapillaryImage, or null if there is none.
-	 */
-	public MapillaryImage previous() {
-		if (this.getSequence() == null)
-			return null;
-		return this.getSequence().previous(this);
-	}
-	
-	public String getDate() {
-		return getDate("dd/MM/yyyy - hh:mm:ss");
-	}
-	
-	public String getDate(String format) {
-		Date date = new Date(getCapturedAt());
+    public String toString() {
+        return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
+                + this.latLon.lon() + ";ca=" + this.ca + "]";
+    }
 
-		SimpleDateFormat formatter = new SimpleDateFormat(format);
-		return formatter.format(date);
-	}
+    /**
+     * If the MapillaryImage belongs to a MapillarySequence, returns the next
+     * MapillarySequence in it.
+     * 
+     * @return The following MapillaryImage, or null if there is none.
+     */
+    public MapillaryImage next() {
+        if (this.getSequence() == null)
+            return null;
+        return this.getSequence().next(this);
+    }
 
-	@Override
-	public boolean equals(Object object) {
-		if (object instanceof MapillaryImage)
-			return this.key.equals(((MapillaryImage) object).getKey());
-		return false;
-	}
+    /**
+     * If the MapillaryImage belongs to a MapillarySequence, returns the
+     * previous MapillarySequence in it.
+     * 
+     * @return The previous MapillaryImage, or null if there is none.
+     */
+    public MapillaryImage previous() {
+        if (this.getSequence() == null)
+            return null;
+        return this.getSequence().previous(this);
+    }
 
-	@Override
-	public int hashCode() {
-		return this.key.hashCode();
-	}
+    /**
+     * Returns the date the picture was taken in DMY format.
+     * @return
+     */
+    public String getDate() {
+        return getDate("dd/MM/yyyy - hh:mm:ss");
+    }
+
+    /**
+     * Returns the date the picture was taken in the given format.
+     * @param format
+     * @return
+     */
+    public String getDate(String format) {
+        Date date = new Date(getCapturedAt());
+
+        SimpleDateFormat formatter = new SimpleDateFormat(format);
+        return formatter.format(date);
+    }
+
+    @Override
+    public boolean equals(Object object) {
+        if (object instanceof MapillaryImage)
+            return this.key.equals(((MapillaryImage) object).getKey());
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.key.hashCode();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java	(revision 31278)
@@ -9,41 +9,42 @@
 public class MapillaryImportedImage extends MapillaryAbstractImage {
 
-	/**
-	 * The picture file.
-	 */
-	protected File file;
-	public final String datetimeOriginal;
+    /**
+     * The picture file.
+     */
+    protected File file;
+    public final String datetimeOriginal;
 
-	public MapillaryImportedImage(double lat, double lon, double ca, File file, String datetimeOriginal) {
-		super(lat, lon, ca);
-		this.file = file;
-		System.out.println(datetimeOriginal);
-		this.datetimeOriginal = datetimeOriginal;
-	}
+    public MapillaryImportedImage(double lat, double lon, double ca, File file,
+            String datetimeOriginal) {
+        super(lat, lon, ca);
+        this.file = file;
+        System.out.println(datetimeOriginal);
+        this.datetimeOriginal = datetimeOriginal;
+    }
 
-	/**
-	 * Returns the pictures of the file.
-	 * 
-	 * @return
-	 * @throws IOException
-	 */
-	public BufferedImage getImage() throws IOException {
-		return ImageIO.read(file);
-	}
-	
-	public File getFile() {
-		return file;
-	}
+    /**
+     * Returns the pictures of the file.
+     * 
+     * @return
+     * @throws IOException
+     */
+    public BufferedImage getImage() throws IOException {
+        return ImageIO.read(file);
+    }
 
-	@Override
-	public boolean equals(Object object) {
-		if (object instanceof MapillaryImportedImage)
-			return this.file.equals(((MapillaryImportedImage) object).file);
-		return false;
-	}
+    public File getFile() {
+        return file;
+    }
 
-	@Override
-	public int hashCode() {
-		return this.file.hashCode();
-	}
+    @Override
+    public boolean equals(Object object) {
+        if (object instanceof MapillaryImportedImage)
+            return this.file.equals(((MapillaryImportedImage) object).file);
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.file.hashCode();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31278)
@@ -53,448 +53,454 @@
 
 public class MapillaryLayer extends AbstractModifiableLayer implements
-		DataSetListener, EditLayerChangeListener, LayerChangeListener {
-
-	public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
-			"mapillary.sequence-max-jump-distance", 100);
-
-	public static MapillaryLayer INSTANCE;
-	public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
-	public static MapillaryImage BLUE;
-	public static MapillaryImage RED;
-
-	private final MapillaryData mapillaryData = MapillaryData.getInstance();
-
-	public List<Bounds> bounds;
-
-	private MapillaryToggleDialog mtd;
-	private MapillaryHistoryDialog mhd;
-
-	private MouseAdapter mouseAdapter;
-
-	int highlightPointRadius = Main.pref.getInteger(
-			"mappaint.highlight.radius", 7);
-	private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
-			4);
-
-	public MapillaryLayer() {
-		super(tr("Mapillary Images"));
-		bounds = new ArrayList<>();
-		init();
-	}
-
-	/**
-	 * Initializes the Layer.
-	 */
-	private void init() {
-		MapillaryLayer.INSTANCE = this;
-		startMouseAdapter();
-		try {
-			CACHE = JCSCacheManager.getCache("Mapillary");
-		} catch (IOException e) {
-			Main.error(e);
-		}
-		if (Main.map != null && Main.map.mapView != null) {
-			Main.map.mapView.addMouseListener(mouseAdapter);
-			Main.map.mapView.addMouseMotionListener(mouseAdapter);
-			Main.map.mapView.addLayer(this);
-			MapView.addEditLayerChangeListener(this, false);
-			MapView.addLayerChangeListener(this);
-			Main.map.mapView.getEditLayer().data.addDataSetListener(this);
-			if (mtd == null) {
-				if (MapillaryToggleDialog.INSTANCE == null) {
-					mtd = MapillaryToggleDialog.getInstance();
-					Main.map.addToggleDialog(mtd, false);
-				} else
-					mtd = MapillaryToggleDialog.getInstance();
-			}
-			if (mhd == null) {
-				if (MapillaryHistoryDialog.INSTANCE == null) {
-					mhd = MapillaryHistoryDialog.getInstance();
-					Main.map.addToggleDialog(mhd, false);
-				} else
-					mhd = MapillaryHistoryDialog.getInstance();
-			}
-		}
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, true);
-		Main.map.mapView.setActiveLayer(this);
-		Main.map.repaint();
-	}
-
-	public void startMouseAdapter() {
-		mouseAdapter = new MapillaryMouseAdapter();
-	}
-
-	public synchronized static MapillaryLayer getInstance() {
-		if (MapillaryLayer.INSTANCE == null)
-			MapillaryLayer.INSTANCE = new MapillaryLayer();
-		return MapillaryLayer.INSTANCE;
-	}
-
-	/**
-	 * Downloads all images of the area covered by the OSM data. This is only
-	 * just for automatic download.
-	 */
-	public void download() {
-		checkBigAreas();
-		if (Main.pref.getBoolean("mapillary.download-manually"))
-			return;
-		for (Bounds bounds : Main.map.mapView.getEditLayer().data
-				.getDataSourceBounds()) {
-			if (!this.bounds.contains(bounds)) {
-				this.bounds.add(bounds);
-				new MapillaryDownloader().getImages(bounds.getMin(),
-						bounds.getMax());
-			}
-		}
-	}
-
-	private void checkBigAreas() {
-		double area = 0;
-		for (Bounds bounds : Main.map.mapView.getEditLayer().data
-				.getDataSourceBounds()) {
-			area += bounds.getArea();
-		}
-		if (area > MapillaryDownloadViewAction.MAX_AREA) {
-			Main.pref.put("mapillary.download-manually", true);
-			JOptionPane
-					.showMessageDialog(
-							Main.parent,
-							tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
-		}
-	}
-
-	/**
-	 * Returns the MapillaryData object, which acts as the database of the
-	 * Layer.
-	 * 
-	 * @return
-	 */
-	public MapillaryData getMapillaryData() {
-		return mapillaryData;
-	}
-
-	/**
-	 * Method invoked when the layer is destroyed.
-	 */
-	@Override
-	public void destroy() {
-		MapillaryToggleDialog.getInstance().mapillaryImageDisplay
-				.setImage(null);
-		MapillaryData.getInstance().getImages().clear();
-		MapillaryLayer.INSTANCE = null;
-		MapillaryData.INSTANCE = null;
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, false);
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
-		Main.map.mapView.removeMouseListener(mouseAdapter);
-		Main.map.mapView.removeMouseMotionListener(mouseAdapter);
-		MapView.removeEditLayerChangeListener(this);
-		if (Main.map.mapView.getEditLayer() != null)
-			Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
-		super.destroy();
-	}
-
-	/**
-	 * Returns true any of the images from the database has been modified.
-	 */
-	@Override
-	public boolean isModified() {
-		for (MapillaryAbstractImage image : mapillaryData.getImages())
-			if (image.isModified())
-				return true;
-		return false;
-	}
-
-	/**
-	 * Paints the database in the map.
-	 */
-	@Override
-	public void paint(Graphics2D g, MapView mv, Bounds box) {
-		synchronized (this) {
-			// Draw colored lines
-			MapillaryLayer.BLUE = null;
-			MapillaryLayer.RED = null;
-			MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
-			MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
-			if (mapillaryData.getSelectedImage() != null) {
-				MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
-				Point selected = mv.getPoint(mapillaryData.getSelectedImage()
-						.getLatLon());
-				if (closestImages[0] != null) {
-					MapillaryLayer.BLUE = closestImages[0];
-					g.setColor(Color.BLUE);
-					g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
-							mv.getPoint(closestImages[0].getLatLon()).y,
-							selected.x, selected.y);
-					MapillaryToggleDialog.getInstance().blueButton
-							.setEnabled(true);
-				}
-				if (closestImages[1] != null) {
-					MapillaryLayer.RED = closestImages[1];
-					g.setColor(Color.RED);
-					g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
-							mv.getPoint(closestImages[1].getLatLon()).y,
-							selected.x, selected.y);
-					MapillaryToggleDialog.getInstance().redButton
-							.setEnabled(true);
-				}
-			}
-			g.setColor(Color.WHITE);
-			for (MapillaryAbstractImage imageAbs : mapillaryData.getImages()) {
-				Point p = mv.getPoint(imageAbs.getLatLon());
-				if (imageAbs instanceof MapillaryImage) {
-					MapillaryImage image = (MapillaryImage) imageAbs;
-					Point nextp;
-					if (image.getSequence() != null
-							&& image.getSequence().next(image) != null) {
-						nextp = mv.getPoint(image.getSequence().next(image)
-								.getLatLon());
-						g.drawLine(p.x, p.y, nextp.x, nextp.y);
-					}
-					ImageIcon icon;
-					if (!mapillaryData.getMultiSelectedImages().contains(image))
-						icon = MapillaryPlugin.MAP_ICON;
-					else
-						icon = MapillaryPlugin.MAP_ICON_SELECTED;
-					draw(g, image, icon, p);
-					if (!image.getSigns().isEmpty()) {
-						g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x
-								+ icon.getIconWidth() / 2,
-								p.y - icon.getIconHeight() / 2,
-								Main.map.mapView);
-					}
-				} else if (imageAbs instanceof MapillaryImportedImage) {
-					MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
-					ImageIcon icon;
-					if (!mapillaryData.getMultiSelectedImages().contains(image))
-						icon = MapillaryPlugin.MAP_ICON_IMPORTED;
-					else
-						icon = MapillaryPlugin.MAP_ICON_SELECTED;
-					draw(g, image, icon, p);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Draws the highlight of the icon.
-	 * 
-	 * @param g
-	 * @param p
-	 * @param size
-	 */
-	private void drawPointHighlight(Graphics2D g, Point p, int size) {
-		Color oldColor = g.getColor();
-		Color highlightColor = PaintColors.HIGHLIGHT.get();
-		Color highlightColorTransparent = new Color(highlightColor.getRed(),
-				highlightColor.getGreen(), highlightColor.getBlue(), 100);
-		g.setColor(highlightColorTransparent);
-		int s = size + highlightPointRadius;
-		while (s >= size) {
-			int r = (int) Math.floor(s / 2d);
-			g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
-			s -= highlightStep;
-		}
-		g.setColor(oldColor);
-	}
-
-	/**
-	 * Draws the given icon of an image. Also checks if the mouse is over the
-	 * image.
-	 * 
-	 * @param g
-	 * @param image
-	 * @param icon
-	 * @param p
-	 */
-	private void draw(Graphics2D g, MapillaryAbstractImage image,
-			ImageIcon icon, Point p) {
-		Image imagetemp = icon.getImage();
-		BufferedImage bi = (BufferedImage) imagetemp;
-		int width = icon.getIconWidth();
-		int height = icon.getIconHeight();
-
-		// Rotate the image
-		double rotationRequired = Math.toRadians(image.getCa());
-		double locationX = width / 2;
-		double locationY = height / 2;
-		AffineTransform tx = AffineTransform.getRotateInstance(
-				rotationRequired, locationX, locationY);
-		AffineTransformOp op = new AffineTransformOp(tx,
-				AffineTransformOp.TYPE_BILINEAR);
-
-		g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
-				Main.map.mapView);
-		if (MapillaryData.getInstance().getHoveredImage() == image) {
-			drawPointHighlight(g, p, 16);
-		}
-	}
-
-	@Override
-	public Icon getIcon() {
-		return MapillaryPlugin.ICON16;
-	}
-
-	@Override
-	public boolean isMergable(Layer other) {
-		return false;
-	}
-
-	@Override
-	public void mergeFrom(Layer from) {
-		throw new UnsupportedOperationException(
-				"This layer does not support merging yet");
-	}
-
-	@Override
-	public Action[] getMenuEntries() {
-		List<Action> actions = new ArrayList<>();
-		actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
-		actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
-		actions.add(new LayerListPopup.InfoAction(this));
-		return actions.toArray(new Action[actions.size()]);
-	}
-
-	private MapillaryImage[] getClosestImagesFromDifferentSequences() {
-		if (!(mapillaryData.getSelectedImage() instanceof MapillaryImage))
-			return new MapillaryImage[2];
-		MapillaryImage selected = (MapillaryImage) mapillaryData
-				.getSelectedImage();
-		MapillaryImage[] ret = new MapillaryImage[2];
-		double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
-				SEQUENCE_MAX_JUMP_DISTANCE };
-		LatLon selectedCoords = mapillaryData.getSelectedImage().getLatLon();
-		for (MapillaryAbstractImage imagePrev : mapillaryData.getImages()) {
-			if (!(imagePrev instanceof MapillaryImage))
-				continue;
-			MapillaryImage image = (MapillaryImage) imagePrev;
-			if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
-					&& selected.getSequence() != image.getSequence()) {
-				if ((ret[0] == null && ret[1] == null)
-						|| (image.getLatLon().greatCircleDistance(
-								selectedCoords) < distances[0] && (ret[1] == null || image
-								.getSequence() != ret[1].getSequence()))) {
-					ret[0] = image;
-					distances[0] = image.getLatLon().greatCircleDistance(
-							selectedCoords);
-				} else if ((ret[1] == null || image.getLatLon()
-						.greatCircleDistance(selectedCoords) < distances[1])
-						&& image.getSequence() != ret[0].getSequence()) {
-					ret[1] = image;
-					distances[1] = image.getLatLon().greatCircleDistance(
-							selectedCoords);
-				}
-			}
-		}
-		// Predownloads the thumbnails
-		if (ret[0] != null)
-			new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
-					.submit(MapillaryData.getInstance(), false);
-		if (ret[1] != null)
-			new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
-					.submit(MapillaryData.getInstance(), false);
-		return ret;
-	}
-
-	@Override
-	public Object getInfoComponent() {
-		StringBuilder sb = new StringBuilder();
-		sb.append(tr("Mapillary layer"));
-		sb.append("\n");
-		sb.append(tr("Total images:"));
-		sb.append(" ");
-		sb.append(this.size());
-		sb.append("\n");
-		return sb.toString();
-	}
-
-	@Override
-	public String getToolTipText() {
-		return this.size() + " " + tr("images");
-	}
-
-	private int size() {
-		return mapillaryData.getImages().size();
-	}
-
-	// EditDataLayerChanged
-	@Override
-	public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
-	}
-
-	/**
-	 * When more data is downloaded, a delayed update is thrown, in order to
-	 * wait for the data bounds to be set.
-	 * 
-	 * @param event
-	 */
-	@Override
-	public void dataChanged(DataChangedEvent event) {
-		Main.worker.submit(new delayedDownload());
-	}
-
-	private class delayedDownload extends Thread {
-
-		@Override
-		public void run() {
-			try {
-				sleep(1000);
-			} catch (InterruptedException e) {
-				Main.error(e);
-			}
-			MapillaryLayer.getInstance().download();
-		}
-	}
-
-	@Override
-	public void primitivesAdded(PrimitivesAddedEvent event) {
-	}
-
-	@Override
-	public void primitivesRemoved(PrimitivesRemovedEvent event) {
-	}
-
-	@Override
-	public void tagsChanged(TagsChangedEvent event) {
-	}
-
-	@Override
-	public void nodeMoved(NodeMovedEvent event) {
-	}
-
-	@Override
-	public void wayNodesChanged(WayNodesChangedEvent event) {
-	}
-
-	@Override
-	public void relationMembersChanged(RelationMembersChangedEvent event) {
-	}
-
-	@Override
-	public void otherDatasetChange(AbstractDatasetChangedEvent event) {
-	}
-
-	@Override
-	public void visitBoundingBox(BoundingXYVisitor v) {
-	}
-
-	@Override
-	public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-		if (newLayer == this) {
-			if (MapillaryData.getInstance().getImages().size() > 0)
-				Main.map.statusLine.setHelpText(tr("Total images: {0}",
-						MapillaryData.getInstance().getImages().size()));
-			else
-				Main.map.statusLine.setHelpText(tr("No images found"));
-		}
-	}
-
-	@Override
-	public void layerAdded(Layer newLayer) {
-	}
-
-	@Override
-	public void layerRemoved(Layer oldLayer) {
-	}
+        DataSetListener, EditLayerChangeListener, LayerChangeListener {
+
+    public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
+            "mapillary.sequence-max-jump-distance", 100);
+
+    public static MapillaryLayer INSTANCE;
+    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
+    public static MapillaryImage BLUE;
+    public static MapillaryImage RED;
+
+    private final MapillaryData mapillaryData = MapillaryData.getInstance();
+
+    public List<Bounds> bounds;
+
+    private MapillaryToggleDialog mtd;
+    private MapillaryHistoryDialog mhd;
+
+    private MouseAdapter mouseAdapter;
+
+    int highlightPointRadius = Main.pref.getInteger(
+            "mappaint.highlight.radius", 7);
+    private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
+            4);
+
+    public MapillaryLayer() {
+        super(tr("Mapillary Images"));
+        bounds = new ArrayList<>();
+        init();
+    }
+
+    /**
+     * Initializes the Layer.
+     */
+    private void init() {
+        MapillaryLayer.INSTANCE = this;
+        startMouseAdapter();
+        try {
+            CACHE = JCSCacheManager.getCache("Mapillary");
+        } catch (IOException e) {
+            Main.error(e);
+        }
+        if (Main.map != null && Main.map.mapView != null) {
+            Main.map.mapView.addMouseListener(mouseAdapter);
+            Main.map.mapView.addMouseMotionListener(mouseAdapter);
+            Main.map.mapView.addLayer(this);
+            MapView.addEditLayerChangeListener(this, false);
+            MapView.addLayerChangeListener(this);
+            Main.map.mapView.getEditLayer().data.addDataSetListener(this);
+            if (mtd == null) {
+                if (MapillaryToggleDialog.INSTANCE == null) {
+                    mtd = MapillaryToggleDialog.getInstance();
+                    Main.map.addToggleDialog(mtd, false);
+                } else
+                    mtd = MapillaryToggleDialog.getInstance();
+            }
+            if (mhd == null) {
+                if (MapillaryHistoryDialog.INSTANCE == null) {
+                    mhd = MapillaryHistoryDialog.getInstance();
+                    Main.map.addToggleDialog(mhd, false);
+                } else
+                    mhd = MapillaryHistoryDialog.getInstance();
+            }
+        }
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, true);
+        Main.map.mapView.setActiveLayer(this);
+        Main.map.repaint();
+    }
+
+    public void startMouseAdapter() {
+        mouseAdapter = new MapillaryMouseAdapter();
+    }
+
+    public synchronized static MapillaryLayer getInstance() {
+        if (MapillaryLayer.INSTANCE == null)
+            MapillaryLayer.INSTANCE = new MapillaryLayer();
+        return MapillaryLayer.INSTANCE;
+    }
+
+    /**
+     * Downloads all images of the area covered by the OSM data. This is only
+     * just for automatic download.
+     */
+    public void download() {
+        checkBigAreas();
+        if (Main.pref.getBoolean("mapillary.download-manually"))
+            return;
+        for (Bounds bounds : Main.map.mapView.getEditLayer().data
+                .getDataSourceBounds()) {
+            if (!this.bounds.contains(bounds)) {
+                this.bounds.add(bounds);
+                new MapillaryDownloader().getImages(bounds.getMin(),
+                        bounds.getMax());
+            }
+        }
+    }
+
+    /**
+     * Checks if the area of the OSM data is too big. This means that probably
+     * lots of Mapillary images are going to be downloaded, slowing down the
+     * program too much. To solve this the automatic is stopped, an alert is
+     * shown and you will have to download areas manually.
+     */
+    private void checkBigAreas() {
+        double area = 0;
+        for (Bounds bounds : Main.map.mapView.getEditLayer().data
+                .getDataSourceBounds()) {
+            area += bounds.getArea();
+        }
+        if (area > MapillaryDownloadViewAction.MAX_AREA) {
+            Main.pref.put("mapillary.download-manually", true);
+            JOptionPane
+                    .showMessageDialog(
+                            Main.parent,
+                            tr("The downloaded OSM area is too big. Download mode has been change to manual. You can change this back to automatic in preferences settings."));
+        }
+    }
+
+    /**
+     * Returns the MapillaryData object, which acts as the database of the
+     * Layer.
+     * 
+     * @return
+     */
+    public MapillaryData getMapillaryData() {
+        return mapillaryData;
+    }
+
+    /**
+     * Method invoked when the layer is destroyed.
+     */
+    @Override
+    public void destroy() {
+        MapillaryToggleDialog.getInstance().mapillaryImageDisplay
+                .setImage(null);
+        MapillaryData.getInstance().getImages().clear();
+        MapillaryLayer.INSTANCE = null;
+        MapillaryData.INSTANCE = null;
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.SIGN_MENU, false);
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.ZOOM_MENU, false);
+        Main.map.mapView.removeMouseListener(mouseAdapter);
+        Main.map.mapView.removeMouseMotionListener(mouseAdapter);
+        MapView.removeEditLayerChangeListener(this);
+        if (Main.map.mapView.getEditLayer() != null)
+            Main.map.mapView.getEditLayer().data.removeDataSetListener(this);
+        super.destroy();
+    }
+
+    /**
+     * Returns true any of the images from the database has been modified.
+     */
+    @Override
+    public boolean isModified() {
+        for (MapillaryAbstractImage image : mapillaryData.getImages())
+            if (image.isModified())
+                return true;
+        return false;
+    }
+
+    /**
+     * Paints the database in the map.
+     */
+    @Override
+    public void paint(Graphics2D g, MapView mv, Bounds box) {
+        synchronized (this) {
+            // Draw colored lines
+            MapillaryLayer.BLUE = null;
+            MapillaryLayer.RED = null;
+            MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
+            MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
+            if (mapillaryData.getSelectedImage() != null) {
+                MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
+                Point selected = mv.getPoint(mapillaryData.getSelectedImage()
+                        .getLatLon());
+                if (closestImages[0] != null) {
+                    MapillaryLayer.BLUE = closestImages[0];
+                    g.setColor(Color.BLUE);
+                    g.drawLine(mv.getPoint(closestImages[0].getLatLon()).x,
+                            mv.getPoint(closestImages[0].getLatLon()).y,
+                            selected.x, selected.y);
+                    MapillaryToggleDialog.getInstance().blueButton
+                            .setEnabled(true);
+                }
+                if (closestImages[1] != null) {
+                    MapillaryLayer.RED = closestImages[1];
+                    g.setColor(Color.RED);
+                    g.drawLine(mv.getPoint(closestImages[1].getLatLon()).x,
+                            mv.getPoint(closestImages[1].getLatLon()).y,
+                            selected.x, selected.y);
+                    MapillaryToggleDialog.getInstance().redButton
+                            .setEnabled(true);
+                }
+            }
+            g.setColor(Color.WHITE);
+            for (MapillaryAbstractImage imageAbs : mapillaryData.getImages()) {
+                Point p = mv.getPoint(imageAbs.getLatLon());
+                if (imageAbs instanceof MapillaryImage) {
+                    MapillaryImage image = (MapillaryImage) imageAbs;
+                    Point nextp;
+                    if (image.getSequence() != null
+                            && image.getSequence().next(image) != null) {
+                        nextp = mv.getPoint(image.getSequence().next(image)
+                                .getLatLon());
+                        g.drawLine(p.x, p.y, nextp.x, nextp.y);
+                    }
+                    ImageIcon icon;
+                    if (!mapillaryData.getMultiSelectedImages().contains(image))
+                        icon = MapillaryPlugin.MAP_ICON;
+                    else
+                        icon = MapillaryPlugin.MAP_ICON_SELECTED;
+                    draw(g, image, icon, p);
+                    if (!image.getSigns().isEmpty()) {
+                        g.drawImage(MapillaryPlugin.MAP_SIGN.getImage(), p.x
+                                + icon.getIconWidth() / 2,
+                                p.y - icon.getIconHeight() / 2,
+                                Main.map.mapView);
+                    }
+                } else if (imageAbs instanceof MapillaryImportedImage) {
+                    MapillaryImportedImage image = (MapillaryImportedImage) imageAbs;
+                    ImageIcon icon;
+                    if (!mapillaryData.getMultiSelectedImages().contains(image))
+                        icon = MapillaryPlugin.MAP_ICON_IMPORTED;
+                    else
+                        icon = MapillaryPlugin.MAP_ICON_SELECTED;
+                    draw(g, image, icon, p);
+                }
+            }
+        }
+    }
+
+    /**
+     * Draws the highlight of the icon.
+     * 
+     * @param g
+     * @param p
+     * @param size
+     */
+    private void drawPointHighlight(Graphics2D g, Point p, int size) {
+        Color oldColor = g.getColor();
+        Color highlightColor = PaintColors.HIGHLIGHT.get();
+        Color highlightColorTransparent = new Color(highlightColor.getRed(),
+                highlightColor.getGreen(), highlightColor.getBlue(), 100);
+        g.setColor(highlightColorTransparent);
+        int s = size + highlightPointRadius;
+        while (s >= size) {
+            int r = (int) Math.floor(s / 2d);
+            g.fillRoundRect(p.x - r, p.y - r, s, s, r, r);
+            s -= highlightStep;
+        }
+        g.setColor(oldColor);
+    }
+
+    /**
+     * Draws the given icon of an image. Also checks if the mouse is over the
+     * image.
+     * 
+     * @param g
+     * @param image
+     * @param icon
+     * @param p
+     */
+    private void draw(Graphics2D g, MapillaryAbstractImage image,
+            ImageIcon icon, Point p) {
+        Image imagetemp = icon.getImage();
+        BufferedImage bi = (BufferedImage) imagetemp;
+        int width = icon.getIconWidth();
+        int height = icon.getIconHeight();
+
+        // Rotate the image
+        double rotationRequired = Math.toRadians(image.getCa());
+        double locationX = width / 2;
+        double locationY = height / 2;
+        AffineTransform tx = AffineTransform.getRotateInstance(
+                rotationRequired, locationX, locationY);
+        AffineTransformOp op = new AffineTransformOp(tx,
+                AffineTransformOp.TYPE_BILINEAR);
+
+        g.drawImage(op.filter(bi, null), p.x - (width / 2), p.y - (height / 2),
+                Main.map.mapView);
+        if (MapillaryData.getInstance().getHoveredImage() == image) {
+            drawPointHighlight(g, p, 16);
+        }
+    }
+
+    @Override
+    public Icon getIcon() {
+        return MapillaryPlugin.ICON16;
+    }
+
+    @Override
+    public boolean isMergable(Layer other) {
+        return false;
+    }
+
+    @Override
+    public void mergeFrom(Layer from) {
+        throw new UnsupportedOperationException(
+                "This layer does not support merging yet");
+    }
+
+    @Override
+    public Action[] getMenuEntries() {
+        List<Action> actions = new ArrayList<>();
+        actions.add(LayerListDialog.getInstance().createShowHideLayerAction());
+        actions.add(LayerListDialog.getInstance().createDeleteLayerAction());
+        actions.add(new LayerListPopup.InfoAction(this));
+        return actions.toArray(new Action[actions.size()]);
+    }
+
+    private MapillaryImage[] getClosestImagesFromDifferentSequences() {
+        if (!(mapillaryData.getSelectedImage() instanceof MapillaryImage))
+            return new MapillaryImage[2];
+        MapillaryImage selected = (MapillaryImage) mapillaryData
+                .getSelectedImage();
+        MapillaryImage[] ret = new MapillaryImage[2];
+        double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
+                SEQUENCE_MAX_JUMP_DISTANCE };
+        LatLon selectedCoords = mapillaryData.getSelectedImage().getLatLon();
+        for (MapillaryAbstractImage imagePrev : mapillaryData.getImages()) {
+            if (!(imagePrev instanceof MapillaryImage))
+                continue;
+            MapillaryImage image = (MapillaryImage) imagePrev;
+            if (image.getLatLon().greatCircleDistance(selectedCoords) < SEQUENCE_MAX_JUMP_DISTANCE
+                    && selected.getSequence() != image.getSequence()) {
+                if ((ret[0] == null && ret[1] == null)
+                        || (image.getLatLon().greatCircleDistance(
+                                selectedCoords) < distances[0] && (ret[1] == null || image
+                                .getSequence() != ret[1].getSequence()))) {
+                    ret[0] = image;
+                    distances[0] = image.getLatLon().greatCircleDistance(
+                            selectedCoords);
+                } else if ((ret[1] == null || image.getLatLon()
+                        .greatCircleDistance(selectedCoords) < distances[1])
+                        && image.getSequence() != ret[0].getSequence()) {
+                    ret[1] = image;
+                    distances[1] = image.getLatLon().greatCircleDistance(
+                            selectedCoords);
+                }
+            }
+        }
+        // Predownloads the thumbnails
+        if (ret[0] != null)
+            new MapillaryCache(ret[0].getKey(), MapillaryCache.Type.THUMBNAIL)
+                    .submit(MapillaryData.getInstance(), false);
+        if (ret[1] != null)
+            new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
+                    .submit(MapillaryData.getInstance(), false);
+        return ret;
+    }
+
+    @Override
+    public Object getInfoComponent() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(tr("Mapillary layer"));
+        sb.append("\n");
+        sb.append(tr("Total images:"));
+        sb.append(" ");
+        sb.append(this.size());
+        sb.append("\n");
+        return sb.toString();
+    }
+
+    @Override
+    public String getToolTipText() {
+        return this.size() + " " + tr("images");
+    }
+
+    private int size() {
+        return mapillaryData.getImages().size();
+    }
+
+    // EditDataLayerChanged
+    @Override
+    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+    }
+
+    /**
+     * When more data is downloaded, a delayed update is thrown, in order to
+     * wait for the data bounds to be set.
+     * 
+     * @param event
+     */
+    @Override
+    public void dataChanged(DataChangedEvent event) {
+        Main.worker.submit(new delayedDownload());
+    }
+
+    private class delayedDownload extends Thread {
+
+        @Override
+        public void run() {
+            try {
+                sleep(1000);
+            } catch (InterruptedException e) {
+                Main.error(e);
+            }
+            MapillaryLayer.getInstance().download();
+        }
+    }
+
+    @Override
+    public void primitivesAdded(PrimitivesAddedEvent event) {
+    }
+
+    @Override
+    public void primitivesRemoved(PrimitivesRemovedEvent event) {
+    }
+
+    @Override
+    public void tagsChanged(TagsChangedEvent event) {
+    }
+
+    @Override
+    public void nodeMoved(NodeMovedEvent event) {
+    }
+
+    @Override
+    public void wayNodesChanged(WayNodesChangedEvent event) {
+    }
+
+    @Override
+    public void relationMembersChanged(RelationMembersChangedEvent event) {
+    }
+
+    @Override
+    public void otherDatasetChange(AbstractDatasetChangedEvent event) {
+    }
+
+    @Override
+    public void visitBoundingBox(BoundingXYVisitor v) {
+    }
+
+    @Override
+    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+        if (newLayer == this) {
+            if (MapillaryData.getInstance().getImages().size() > 0)
+                Main.map.statusLine.setHelpText(tr("Total images: {0}",
+                        MapillaryData.getInstance().getImages().size()));
+            else
+                Main.map.statusLine.setHelpText(tr("No images found"));
+        }
+    }
+
+    @Override
+    public void layerAdded(Layer newLayer) {
+    }
+
+    @Override
+    public void layerRemoved(Layer oldLayer) {
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryMouseAdapter.java	(revision 31278)
@@ -22,214 +22,214 @@
  */
 public class MapillaryMouseAdapter extends MouseAdapter {
-	private Point start;
-	private int lastButton;
-	private MapillaryAbstractImage closest;
-	private MapillaryAbstractImage lastClicked;
-	private MapillaryData mapillaryData;
-	private MapillaryRecord record;
-
-	private boolean nothingHighlighted;
-
-	public MapillaryMouseAdapter() {
-		mapillaryData = MapillaryData.getInstance();
-		record = MapillaryRecord.getInstance();
-	}
-
-	@Override
-	public void mousePressed(MouseEvent e) {
-		lastButton = e.getButton();
-		if (e.getButton() != MouseEvent.BUTTON1)
-			return;
-		MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
-		if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
-				&& closestTemp != null) {
-			this.lastClicked = this.closest;
-			MapillaryData.getInstance().setSelectedImage(closestTemp);
-			return;
-		} else if (Main.map.mapView.getActiveLayer() != MapillaryLayer
-				.getInstance())
-			return;
-		if (closestTemp instanceof MapillaryImage || closestTemp == null) {
-			MapillaryImage closest = (MapillaryImage) closestTemp;
-			// Doube click
-			if (e.getClickCount() == 2
-					&& mapillaryData.getSelectedImage() != null
-					&& closest != null) {
-				for (MapillaryAbstractImage img : closest.getSequence()
-						.getImages()) {
-					mapillaryData.addMultiSelectedImage(img);
-				}
-			}
-			this.start = e.getPoint();
-			this.lastClicked = this.closest;
-			this.closest = closest;
-			if (mapillaryData.getMultiSelectedImages().contains(closest))
-				return;
-			// ctrl+click
-			if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
-					&& closest != null)
-				mapillaryData.addMultiSelectedImage(closest);
-			// shift + click
-			else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK)
-					&& this.closest instanceof MapillaryImage
-					&& this.lastClicked instanceof MapillaryImage) {
-				if (this.closest != null
-						&& this.lastClicked != null
-						&& ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked)
-								.getSequence()) {
-					int i = ((MapillaryImage) this.closest).getSequence()
-							.getImages().indexOf(this.closest);
-					int j = ((MapillaryImage) this.lastClicked).getSequence()
-							.getImages().indexOf(this.lastClicked);
-					if (i < j)
-						mapillaryData
-								.addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
-										((MapillaryImage) this.closest)
-												.getSequence().getImages()
-												.subList(i, j + 1)));
-					else
-						mapillaryData
-								.addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
-										((MapillaryImage) this.closest)
-												.getSequence().getImages()
-												.subList(j, i + 1)));
-				}
-				// click
-			} else
-				mapillaryData.setSelectedImage(closest);
-			// If you select an imported image
-		} else if (closestTemp instanceof MapillaryImportedImage) {
-			MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp;
-			this.start = e.getPoint();
-			this.lastClicked = this.closest;
-			this.closest = closest;
-			if (mapillaryData.getMultiSelectedImages().contains(closest))
-				return;
-			if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
-					&& closest != null)
-				mapillaryData.addMultiSelectedImage(closest);
-			else
-				mapillaryData.setSelectedImage(closest);
-		}
-	}
-
-	private MapillaryAbstractImage getClosest(Point clickPoint) {
-		double snapDistance = 10;
-		double minDistance = Double.MAX_VALUE;
-		MapillaryAbstractImage closest = null;
-		for (MapillaryAbstractImage image : mapillaryData.getImages()) {
-			Point imagePoint = Main.map.mapView.getPoint(image.getLatLon());
-			imagePoint.setLocation(imagePoint.getX(), imagePoint.getY());
-			double dist = clickPoint.distanceSq(imagePoint);
-			if (minDistance > dist
-					&& clickPoint.distance(imagePoint) < snapDistance) {
-				minDistance = dist;
-				closest = image;
-			}
-		}
-		return closest;
-	}
-
-	@Override
-	public void mouseDragged(MouseEvent e) {
-		if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance())
-			return;
-
-		if (!Main.pref.getBoolean("mapillary.developer"))
-			for (MapillaryAbstractImage img : MapillaryData.getInstance()
-					.getMultiSelectedImages()) {
-				if (img instanceof MapillaryImage)
-					return;
-			}
-		if (MapillaryData.getInstance().getSelectedImage() != null) {
-			if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) {
-				LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY());
-				LatLon from = Main.map.mapView.getLatLon(start.getX(),
-						start.getY());
-				for (MapillaryAbstractImage img : MapillaryData.getInstance()
-						.getMultiSelectedImages()) {
-
-					img.move(to.getX() - from.getX(), to.getY() - from.getY());
-				}
-				Main.map.repaint();
-			} else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) {
-				this.closest.turn(Math.toDegrees(Math.atan2(
-						(e.getX() - start.x), -(e.getY() - start.y)))
-						- closest.getTempCa());
-				for (MapillaryAbstractImage img : MapillaryData.getInstance()
-						.getMultiSelectedImages()) {
-					img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x),
-							-(e.getY() - start.y))) - closest.getTempCa());
-				}
-				Main.map.repaint();
-			}
-		}
-	}
-
-	@Override
-	public void mouseReleased(MouseEvent e) {
-		if (mapillaryData.getSelectedImage() == null)
-			return;
-		if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData
-				.getSelectedImage().getCa()) {
-			double from = mapillaryData.getSelectedImage().getTempCa();
-			double to = mapillaryData.getSelectedImage().getCa();
-			record.addCommand(new CommandTurnImage(mapillaryData
-					.getMultiSelectedImages(), to - from));
-		} else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData
-				.getSelectedImage().getLatLon()) {
-			LatLon from = mapillaryData.getSelectedImage().getTempLatLon();
-			LatLon to = mapillaryData.getSelectedImage().getLatLon();
-			record.addCommand(new CommandMoveImage(mapillaryData
-					.getMultiSelectedImages(), to.getX() - from.getX(), to
-					.getY() - from.getY()));
-		}
-		for (MapillaryAbstractImage img : mapillaryData
-				.getMultiSelectedImages()) {
-			if (img != null)
-				img.stopMoving();
-		}
-	}
-
-	/**
-	 * Checks if the mouse is over pictures.
-	 */
-	@Override
-	public void mouseMoved(MouseEvent e) {
-		MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
-
-		if (closestTemp != null
-				&& Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
-				&& Main.map.mapModeSelect.getValue("active") == Boolean.TRUE) {
-			Main.map.mapModeSelect.exitMode();
-		} else if (closestTemp == null
-				&& Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
-				&& Main.map.mapModeSelect.getValue("active") == Boolean.FALSE) {
-			Main.map.mapModeSelect.enterMode();
-			nothingHighlighted = false;
-		} else if (Main.map.mapModeSelect.getValue("active") == Boolean.FALSE
-				&& !nothingHighlighted) {
-			for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data
-					.allPrimitives()) {
-				primivitive.setHighlighted(false);
-			}
-			nothingHighlighted = true;
-		}
-
-		// TODO check if it is possible to do this while the OSM data layer is
-		// selected.
-		if (MapillaryData.getInstance().getHoveredImage() != closestTemp
-				&& closestTemp != null) {
-			MapillaryData.getInstance().setHoveredImage(closestTemp);
-			MapillaryToggleDialog.getInstance().setImage(closestTemp);
-			MapillaryToggleDialog.getInstance().updateImage();
-		} else if (MapillaryData.getInstance().getHoveredImage() != closestTemp
-				&& closestTemp == null) {
-			MapillaryData.getInstance().setHoveredImage(null);
-			MapillaryToggleDialog.getInstance().setImage(
-					MapillaryData.getInstance().getSelectedImage());
-			MapillaryToggleDialog.getInstance().updateImage();
-		}
-		MapillaryData.getInstance().dataUpdated();
-	}
+    private Point start;
+    private int lastButton;
+    private MapillaryAbstractImage closest;
+    private MapillaryAbstractImage lastClicked;
+    private MapillaryData mapillaryData;
+    private MapillaryRecord record;
+
+    private boolean nothingHighlighted;
+
+    public MapillaryMouseAdapter() {
+        mapillaryData = MapillaryData.getInstance();
+        record = MapillaryRecord.getInstance();
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+        lastButton = e.getButton();
+        if (e.getButton() != MouseEvent.BUTTON1)
+            return;
+        MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
+        if (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
+                && closestTemp != null) {
+            this.lastClicked = this.closest;
+            MapillaryData.getInstance().setSelectedImage(closestTemp);
+            return;
+        } else if (Main.map.mapView.getActiveLayer() != MapillaryLayer
+                .getInstance())
+            return;
+        if (closestTemp instanceof MapillaryImage || closestTemp == null) {
+            MapillaryImage closest = (MapillaryImage) closestTemp;
+            // Doube click
+            if (e.getClickCount() == 2
+                    && mapillaryData.getSelectedImage() != null
+                    && closest != null) {
+                for (MapillaryAbstractImage img : closest.getSequence()
+                        .getImages()) {
+                    mapillaryData.addMultiSelectedImage(img);
+                }
+            }
+            this.start = e.getPoint();
+            this.lastClicked = this.closest;
+            this.closest = closest;
+            if (mapillaryData.getMultiSelectedImages().contains(closest))
+                return;
+            // ctrl+click
+            if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
+                    && closest != null)
+                mapillaryData.addMultiSelectedImage(closest);
+            // shift + click
+            else if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK)
+                    && this.closest instanceof MapillaryImage
+                    && this.lastClicked instanceof MapillaryImage) {
+                if (this.closest != null
+                        && this.lastClicked != null
+                        && ((MapillaryImage) this.closest).getSequence() == ((MapillaryImage) this.lastClicked)
+                                .getSequence()) {
+                    int i = ((MapillaryImage) this.closest).getSequence()
+                            .getImages().indexOf(this.closest);
+                    int j = ((MapillaryImage) this.lastClicked).getSequence()
+                            .getImages().indexOf(this.lastClicked);
+                    if (i < j)
+                        mapillaryData
+                                .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
+                                        ((MapillaryImage) this.closest)
+                                                .getSequence().getImages()
+                                                .subList(i, j + 1)));
+                    else
+                        mapillaryData
+                                .addMultiSelectedImage(new ArrayList<MapillaryAbstractImage>(
+                                        ((MapillaryImage) this.closest)
+                                                .getSequence().getImages()
+                                                .subList(j, i + 1)));
+                }
+                // click
+            } else
+                mapillaryData.setSelectedImage(closest);
+            // If you select an imported image
+        } else if (closestTemp instanceof MapillaryImportedImage) {
+            MapillaryImportedImage closest = (MapillaryImportedImage) closestTemp;
+            this.start = e.getPoint();
+            this.lastClicked = this.closest;
+            this.closest = closest;
+            if (mapillaryData.getMultiSelectedImages().contains(closest))
+                return;
+            if (e.getModifiers() == (MouseEvent.BUTTON1_MASK | MouseEvent.CTRL_MASK)
+                    && closest != null)
+                mapillaryData.addMultiSelectedImage(closest);
+            else
+                mapillaryData.setSelectedImage(closest);
+        }
+    }
+
+    private MapillaryAbstractImage getClosest(Point clickPoint) {
+        double snapDistance = 10;
+        double minDistance = Double.MAX_VALUE;
+        MapillaryAbstractImage closest = null;
+        for (MapillaryAbstractImage image : mapillaryData.getImages()) {
+            Point imagePoint = Main.map.mapView.getPoint(image.getLatLon());
+            imagePoint.setLocation(imagePoint.getX(), imagePoint.getY());
+            double dist = clickPoint.distanceSq(imagePoint);
+            if (minDistance > dist
+                    && clickPoint.distance(imagePoint) < snapDistance) {
+                minDistance = dist;
+                closest = image;
+            }
+        }
+        return closest;
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+        if (Main.map.mapView.getActiveLayer() != MapillaryLayer.getInstance())
+            return;
+
+        if (!Main.pref.getBoolean("mapillary.developer"))
+            for (MapillaryAbstractImage img : MapillaryData.getInstance()
+                    .getMultiSelectedImages()) {
+                if (img instanceof MapillaryImage)
+                    return;
+            }
+        if (MapillaryData.getInstance().getSelectedImage() != null) {
+            if (lastButton == MouseEvent.BUTTON1 && !e.isShiftDown()) {
+                LatLon to = Main.map.mapView.getLatLon(e.getX(), e.getY());
+                LatLon from = Main.map.mapView.getLatLon(start.getX(),
+                        start.getY());
+                for (MapillaryAbstractImage img : MapillaryData.getInstance()
+                        .getMultiSelectedImages()) {
+
+                    img.move(to.getX() - from.getX(), to.getY() - from.getY());
+                }
+                Main.map.repaint();
+            } else if (lastButton == MouseEvent.BUTTON1 && e.isShiftDown()) {
+                this.closest.turn(Math.toDegrees(Math.atan2(
+                        (e.getX() - start.x), -(e.getY() - start.y)))
+                        - closest.getTempCa());
+                for (MapillaryAbstractImage img : MapillaryData.getInstance()
+                        .getMultiSelectedImages()) {
+                    img.turn(Math.toDegrees(Math.atan2((e.getX() - start.x),
+                            -(e.getY() - start.y))) - closest.getTempCa());
+                }
+                Main.map.repaint();
+            }
+        }
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+        if (mapillaryData.getSelectedImage() == null)
+            return;
+        if (mapillaryData.getSelectedImage().getTempCa() != mapillaryData
+                .getSelectedImage().getCa()) {
+            double from = mapillaryData.getSelectedImage().getTempCa();
+            double to = mapillaryData.getSelectedImage().getCa();
+            record.addCommand(new CommandTurnImage(mapillaryData
+                    .getMultiSelectedImages(), to - from));
+        } else if (mapillaryData.getSelectedImage().getTempLatLon() != mapillaryData
+                .getSelectedImage().getLatLon()) {
+            LatLon from = mapillaryData.getSelectedImage().getTempLatLon();
+            LatLon to = mapillaryData.getSelectedImage().getLatLon();
+            record.addCommand(new CommandMoveImage(mapillaryData
+                    .getMultiSelectedImages(), to.getX() - from.getX(), to
+                    .getY() - from.getY()));
+        }
+        for (MapillaryAbstractImage img : mapillaryData
+                .getMultiSelectedImages()) {
+            if (img != null)
+                img.stopMoving();
+        }
+    }
+
+    /**
+     * Checks if the mouse is over pictures.
+     */
+    @Override
+    public void mouseMoved(MouseEvent e) {
+        MapillaryAbstractImage closestTemp = getClosest(e.getPoint());
+
+        if (closestTemp != null
+                && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
+                && Main.map.mapModeSelect.getValue("active") == Boolean.TRUE) {
+            Main.map.mapModeSelect.exitMode();
+        } else if (closestTemp == null
+                && Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
+                && Main.map.mapModeSelect.getValue("active") == Boolean.FALSE) {
+            Main.map.mapModeSelect.enterMode();
+            nothingHighlighted = false;
+        } else if (Main.map.mapModeSelect.getValue("active") == Boolean.FALSE
+                && !nothingHighlighted) {
+            for (OsmPrimitive primivitive : Main.map.mapView.getEditLayer().data
+                    .allPrimitives()) {
+                primivitive.setHighlighted(false);
+            }
+            nothingHighlighted = true;
+        }
+
+        // TODO check if it is possible to do this while the OSM data layer is
+        // selected.
+        if (MapillaryData.getInstance().getHoveredImage() != closestTemp
+                && closestTemp != null) {
+            MapillaryData.getInstance().setHoveredImage(closestTemp);
+            MapillaryToggleDialog.getInstance().setImage(closestTemp);
+            MapillaryToggleDialog.getInstance().updateImage();
+        } else if (MapillaryData.getInstance().getHoveredImage() != closestTemp
+                && closestTemp == null) {
+            MapillaryData.getInstance().setHoveredImage(null);
+            MapillaryToggleDialog.getInstance().setImage(
+                    MapillaryData.getInstance().getSelectedImage());
+            MapillaryToggleDialog.getInstance().updateImage();
+        }
+        MapillaryData.getInstance().dataUpdated();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31278)
@@ -31,103 +31,103 @@
 public class MapillaryPlugin extends Plugin implements EditLayerChangeListener {
 
-	public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
-			.get();
-	public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
-			.get();
-	public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
-			.get();
-	public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
-			"mapiconselected.png").get();
-	public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
-			"mapiconimported.png").get();
-	public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
-			.get();
-	public static final int ICON_SIZE = 24;
+    public static final ImageIcon ICON24 = new ImageProvider("icon24.png")
+            .get();
+    public static final ImageIcon ICON16 = new ImageProvider("icon16.png")
+            .get();
+    public static final ImageIcon MAP_ICON = new ImageProvider("mapicon.png")
+            .get();
+    public static final ImageIcon MAP_ICON_SELECTED = new ImageProvider(
+            "mapiconselected.png").get();
+    public static final ImageIcon MAP_ICON_IMPORTED = new ImageProvider(
+            "mapiconimported.png").get();
+    public static final ImageIcon MAP_SIGN = new ImageProvider("sign.png")
+            .get();
+    public static final int ICON_SIZE = 24;
 
-	public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
+    public static CacheAccess<String, BufferedImageCacheEntry> CACHE;
 
-	private final MapillaryDownloadAction downloadAction;
-	private final MapillaryExportAction exportAction;
-	private final MapillaryImportAction importAction;
-	private final MapillarySignAction signAction;
-	private final MapillaryZoomAction zoomAction;
-	private final MapillaryDownloadViewAction downloadViewAction;
+    private final MapillaryDownloadAction downloadAction;
+    private final MapillaryExportAction exportAction;
+    private final MapillaryImportAction importAction;
+    private final MapillarySignAction signAction;
+    private final MapillaryZoomAction zoomAction;
+    private final MapillaryDownloadViewAction downloadViewAction;
 
-	public static JMenuItem DOWNLOAD_MENU;
-	public static JMenuItem EXPORT_MENU;
-	public static JMenuItem IMPORT_MENU;
-	public static JMenuItem SIGN_MENU;
-	public static JMenuItem ZOOM_MENU;
-	public static JMenuItem DOWNLOAD_VIEW_MENU;
+    public static JMenuItem DOWNLOAD_MENU;
+    public static JMenuItem EXPORT_MENU;
+    public static JMenuItem IMPORT_MENU;
+    public static JMenuItem SIGN_MENU;
+    public static JMenuItem ZOOM_MENU;
+    public static JMenuItem DOWNLOAD_VIEW_MENU;
 
-	public MapillaryPlugin(PluginInformation info) {
-		super(info);
-		downloadAction = new MapillaryDownloadAction();
-		exportAction = new MapillaryExportAction();
-		importAction = new MapillaryImportAction();
-		signAction = new MapillarySignAction();
-		zoomAction = new MapillaryZoomAction();
-		downloadViewAction = new MapillaryDownloadViewAction();
+    public MapillaryPlugin(PluginInformation info) {
+        super(info);
+        downloadAction = new MapillaryDownloadAction();
+        exportAction = new MapillaryExportAction();
+        importAction = new MapillaryImportAction();
+        signAction = new MapillarySignAction();
+        zoomAction = new MapillaryZoomAction();
+        downloadViewAction = new MapillaryDownloadViewAction();
 
-		DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
-				downloadAction, false);
-		EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
-				false, 14);
-		IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
-				false, 14);
-		SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false);
-		ZOOM_MENU = MainMenu
-				.add(Main.main.menu.viewMenu, zoomAction, false, 15);
-		DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
-				downloadViewAction, false, 14);
-		
-		EXPORT_MENU.setEnabled(false);
-		DOWNLOAD_MENU.setEnabled(false);
-		IMPORT_MENU.setEnabled(false);
-		SIGN_MENU.setEnabled(false);
-		ZOOM_MENU.setEnabled(false);
-		DOWNLOAD_VIEW_MENU.setEnabled(false);
+        DOWNLOAD_MENU = MainMenu.add(Main.main.menu.imageryMenu,
+                downloadAction, false);
+        EXPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, exportAction,
+                false, 14);
+        IMPORT_MENU = MainMenu.add(Main.main.menu.fileMenu, importAction,
+                false, 14);
+        SIGN_MENU = MainMenu.add(Main.main.menu.dataMenu, signAction, false);
+        ZOOM_MENU = MainMenu
+                .add(Main.main.menu.viewMenu, zoomAction, false, 15);
+        DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
+                downloadViewAction, false, 14);
 
-		MapView.addEditLayerChangeListener(this);
-		try {
-			CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
-					this.getPluginDir() + "/cache/");
-		} catch (IOException e) {
-			Main.error(e);
-		}
-	}
+        EXPORT_MENU.setEnabled(false);
+        DOWNLOAD_MENU.setEnabled(false);
+        IMPORT_MENU.setEnabled(false);
+        SIGN_MENU.setEnabled(false);
+        ZOOM_MENU.setEnabled(false);
+        DOWNLOAD_VIEW_MENU.setEnabled(false);
 
-	/**
-	 * Called when the JOSM map frame is created or destroyed.
-	 */
-	@Override
-	public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
-		if (oldFrame == null && newFrame != null) { // map frame added
-		}
-		if (oldFrame != null && newFrame == null) { // map frame destroyed
-			MapillaryToggleDialog.destroyInstance();
-		}
-	}
+        MapView.addEditLayerChangeListener(this);
+        try {
+            CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
+                    this.getPluginDir() + "/cache/");
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
 
-	public static void setMenuEnabled(JMenuItem menu, boolean value) {
-		menu.setEnabled(value);
-	}
+    /**
+     * Called when the JOSM map frame is created or destroyed.
+     */
+    @Override
+    public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+        if (oldFrame == null && newFrame != null) { // map frame added
+        }
+        if (oldFrame != null && newFrame == null) { // map frame destroyed
+            MapillaryToggleDialog.destroyInstance();
+        }
+    }
 
-	@Override
-	public PreferenceSetting getPreferenceSetting() {
-		return new MapillaryPreferenceSetting();
-	}
+    public static void setMenuEnabled(JMenuItem menu, boolean value) {
+        menu.setEnabled(value);
+    }
 
-	@Override
-	public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
-		if (oldLayer == null && newLayer != null) {
-			DOWNLOAD_MENU.setEnabled(true);
-			IMPORT_MENU.setEnabled(true);
-			DOWNLOAD_VIEW_MENU.setEnabled(true);
-		} else if (oldLayer != null && newLayer == null) {
-			DOWNLOAD_MENU.setEnabled(false);
-			IMPORT_MENU.setEnabled(false);
-			DOWNLOAD_VIEW_MENU.setEnabled(false);
-		}
-	}
+    @Override
+    public PreferenceSetting getPreferenceSetting() {
+        return new MapillaryPreferenceSetting();
+    }
+
+    @Override
+    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+        if (oldLayer == null && newLayer != null) {
+            DOWNLOAD_MENU.setEnabled(true);
+            IMPORT_MENU.setEnabled(true);
+            DOWNLOAD_VIEW_MENU.setEnabled(true);
+        } else if (oldLayer != null && newLayer == null) {
+            DOWNLOAD_MENU.setEnabled(false);
+            IMPORT_MENU.setEnabled(false);
+            DOWNLOAD_VIEW_MENU.setEnabled(false);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java	(revision 31278)
@@ -12,116 +12,116 @@
  */
 public class MapillarySequence {
-	private final List<MapillaryImage> images;
-	private final String key;
-	private final long created_at;
+    private final List<MapillaryImage> images;
+    private final String key;
+    private final long created_at;
 
-	public MapillarySequence(String key, long created_at) {
-		this.images = new ArrayList<>();
-		this.key = key;
-		this.created_at = created_at;
-	}
+    public MapillarySequence(String key, long created_at) {
+        this.images = new ArrayList<>();
+        this.key = key;
+        this.created_at = created_at;
+    }
 
-	/**
-	 * Returns all MapillaryImages objects contained by this object.
-	 * 
-	 * @return
-	 */
-	public List<MapillaryImage> getImages() {
-		return this.images;
-	}
+    /**
+     * Returns all MapillaryImages objects contained by this object.
+     * 
+     * @return
+     */
+    public List<MapillaryImage> getImages() {
+        return this.images;
+    }
 
-	public long getCreatedAt() {
-		return created_at;
-	}
+    public long getCreatedAt() {
+        return created_at;
+    }
 
-	/**
-	 * Adds a new MapillaryImage object to this object.
-	 * 
-	 * @param image
-	 */
-	public synchronized void add(MapillaryImage image) {
-		this.images.add(image);
-	}
+    /**
+     * Adds a new MapillaryImage object to this object.
+     * 
+     * @param image
+     */
+    public synchronized void add(MapillaryImage image) {
+        this.images.add(image);
+    }
 
-	public String getKey() {
-		return this.key;
-	}
+    public String getKey() {
+        return this.key;
+    }
 
-	/**
-	 * Adds a set of MapillaryImage objects to this object.
-	 * 
-	 * @param images
-	 */
-	public synchronized void add(List<MapillaryImage> images) {
-		for (MapillaryImage image : images)
-			add(image);
-	}
+    /**
+     * Adds a set of MapillaryImage objects to this object.
+     * 
+     * @param images
+     */
+    public synchronized void add(List<MapillaryImage> images) {
+        for (MapillaryImage image : images)
+            add(image);
+    }
 
-	/**
-	 * Removes a MapillaryImage object from this object.
-	 * 
-	 * @param image
-	 */
-	public void remove(MapillaryImage image) {
-		this.images.remove(image);
-	}
+    /**
+     * Removes a MapillaryImage object from this object.
+     * 
+     * @param image
+     */
+    public void remove(MapillaryImage image) {
+        this.images.remove(image);
+    }
 
-	/**
-	 * Returns the next MapillaryImage in the sequence.
-	 * 
-	 * @param image
-	 * @return
-	 */
-	public MapillaryImage next(MapillaryImage image) {
-		if (!images.contains(image))
-			throw new IllegalArgumentException();
-		int i = images.indexOf(image);
-		if (i == images.size() - 1)
-			return null;
-		else
-			return images.get(i + 1);
-	}
+    /**
+     * Returns the next MapillaryImage in the sequence.
+     * 
+     * @param image
+     * @return
+     */
+    public MapillaryImage next(MapillaryImage image) {
+        if (!images.contains(image))
+            throw new IllegalArgumentException();
+        int i = images.indexOf(image);
+        if (i == images.size() - 1)
+            return null;
+        else
+            return images.get(i + 1);
+    }
 
-	/**
-	 * Returns the previous MapillaryImage in the sequence.
-	 * 
-	 * @param image
-	 * @return
-	 */
-	public MapillaryImage previous(MapillaryImage image) {
-		if (!images.contains(image))
-			throw new IllegalArgumentException();
-		int i = images.indexOf(image);
-		if (i == 0)
-			return null;
-		else
-			return images.get(i - 1);
-	}
+    /**
+     * Returns the previous MapillaryImage in the sequence.
+     * 
+     * @param image
+     * @return
+     */
+    public MapillaryImage previous(MapillaryImage image) {
+        if (!images.contains(image))
+            throw new IllegalArgumentException();
+        int i = images.indexOf(image);
+        if (i == 0)
+            return null;
+        else
+            return images.get(i - 1);
+    }
 
-	/**
-	 * Returns the difference of index between two MapillaryImage objects
-	 * belonging to the same MapillarySequence.
-	 * 
-	 * @param image1
-	 * @param image2
-	 * @return
-	 */
-	public int getDistance(MapillaryImage image1, MapillaryImage image2) {
-		if (!this.images.contains(image1) || !this.images.contains(image2))
-			throw new IllegalArgumentException();
-		return Math.abs(this.images.indexOf(image1)
-				- this.images.indexOf(image2));
-	}
+    /**
+     * Returns the difference of index between two MapillaryImage objects
+     * belonging to the same MapillarySequence.
+     * 
+     * @param image1
+     * @param image2
+     * @return
+     */
+    public int getDistance(MapillaryImage image1, MapillaryImage image2) {
+        if (!this.images.contains(image1) || !this.images.contains(image2))
+            throw new IllegalArgumentException();
+        return Math.abs(this.images.indexOf(image1)
+                - this.images.indexOf(image2));
+    }
 
-	@Override
-	public boolean equals(Object obj) {
-		if (obj instanceof MapillarySequence)
-			return this.getKey().equals(((MapillarySequence) obj).getKey());
-		return false;
-	}
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof MapillarySequence)
+            return this.getKey().equals(((MapillarySequence) obj).getKey());
+        return false;
+    }
 
-	@Override
-	public int hashCode() {
-		return this.key.hashCode();
-	}
+    @Override
+    public int hashCode() {
+        return this.key.hashCode();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java	(revision 31278)
@@ -23,26 +23,26 @@
 public class MapillaryDownloadAction extends JosmAction {
 
-	public MapillaryDownloadAction() {
-		super(tr("Mapillary"), new ImageProvider("icon24.png"),
-				tr("Create Mapillary layer"), Shortcut.registerShortcut(
-						"Mapillary", tr("Start Mapillary layer"),
-						KeyEvent.VK_M, Shortcut.ALT_CTRL_SHIFT), false,
-				"mapillaryDownload", false);
-		this.setEnabled(false);
-	}
+    public MapillaryDownloadAction() {
+        super(tr("Mapillary"), new ImageProvider("icon24.png"),
+                tr("Create Mapillary layer"), Shortcut.registerShortcut(
+                        "Mapillary", tr("Start Mapillary layer"),
+                        KeyEvent.VK_M, Shortcut.ALT_CTRL_SHIFT), false,
+                "mapillaryDownload", false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		if (MapillaryLayer.INSTANCE == null)
-			MapillaryLayer.getInstance().download();
-		else {
-			if (Main.map.mapView.getActiveLayer() != MapillaryLayer
-					.getInstance())
-				Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
-			else
-				Main.map.mapView
-						.setActiveLayer(Main.map.mapView.getEditLayer());
-		}
-	}
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        if (MapillaryLayer.INSTANCE == null)
+            MapillaryLayer.getInstance().download();
+        else {
+            if (Main.map.mapView.getActiveLayer() != MapillaryLayer
+                    .getInstance())
+                Main.map.mapView.setActiveLayer(MapillaryLayer.getInstance());
+            else
+                Main.map.mapView
+                        .setActiveLayer(Main.map.mapView.getEditLayer());
+        }
+    }
 
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java	(revision 31278)
@@ -17,30 +17,30 @@
 public class MapillaryDownloadViewAction extends JosmAction {
 
-	public static double MAX_AREA = Main.pref.getDouble(
-			"mapillary.max-download-area", 0.025);
+    public static double MAX_AREA = Main.pref.getDouble(
+            "mapillary.max-download-area", 0.025);
 
-	public MapillaryDownloadViewAction() {
-		super(tr("Download Mapillary images in current view"),
-				new ImageProvider("icon24.png"),
-				tr("Download Mapillary images in current view"),
-				Shortcut.registerShortcut("Mapillary area",
-						tr("Download Mapillary images in current view"),
-						KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryArea",
-				false);
-		this.setEnabled(false);
-	}
+    public MapillaryDownloadViewAction() {
+        super(tr("Download Mapillary images in current view"),
+                new ImageProvider("icon24.png"),
+                tr("Download Mapillary images in current view"),
+                Shortcut.registerShortcut("Mapillary area",
+                        tr("Download Mapillary images in current view"),
+                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryArea",
+                false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		MapillaryLayer.getInstance();
-		MapillaryLayer.getInstance().bounds.add(Main.map.mapView
-				.getRealBounds());
-		if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) {
-			new MapillaryDownloader().getImages(Main.map.mapView
-					.getRealBounds());
-		} else {
-			JOptionPane.showMessageDialog(Main.parent,
-					tr("This area too big to be downloaded"));
-		}
-	}
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        MapillaryLayer.getInstance();
+        MapillaryLayer.getInstance().bounds.add(Main.map.mapView
+                .getRealBounds());
+        if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) {
+            new MapillaryDownloader().getImages(Main.map.mapView
+                    .getRealBounds());
+        } else {
+            JOptionPane.showMessageDialog(Main.parent,
+                    tr("This area too big to be downloaded"));
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryExportAction.java	(revision 31278)
@@ -32,65 +32,69 @@
 public class MapillaryExportAction extends JosmAction {
 
-	MapillaryExportDialog dialog;
+    MapillaryExportDialog dialog;
 
-	public MapillaryExportAction() {
-		super(tr("Export pictures"), new ImageProvider("icon24.png"),
-				tr("Export pictures"), Shortcut.registerShortcut(
-						"Export Mapillary", tr("Export Mapillary pictures"),
-						KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryExport", false);
-		this.setEnabled(false);
-	}
+    public MapillaryExportAction() {
+        super(tr("Export pictures"), new ImageProvider("icon24.png"),
+                tr("Export pictures"), Shortcut.registerShortcut(
+                        "Export Mapillary", tr("Export Mapillary pictures"),
+                        KeyEvent.VK_M, Shortcut.NONE), false,
+                "mapillaryExport", false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent e) {
-		dialog = new MapillaryExportDialog();
-		JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
-				JOptionPane.OK_CANCEL_OPTION);
-		JDialog dlg = pane.createDialog(Main.parent, tr("Export images"));
-		dlg.setMinimumSize(new Dimension(400, 150));
-		dlg.setVisible(true);
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        dialog = new MapillaryExportDialog();
+        JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
+                JOptionPane.OK_CANCEL_OPTION);
+        JDialog dlg = pane.createDialog(Main.parent, tr("Export images"));
+        dlg.setMinimumSize(new Dimension(400, 150));
+        dlg.setVisible(true);
 
-		// Checks if the inputs are correct and starts the export process.
-		if (pane.getValue() != null
-				&& (int) pane.getValue() == JOptionPane.OK_OPTION
-				&& dialog.chooser != null) {
-			if (dialog.group.isSelected(dialog.all.getModel())) {
-				export(MapillaryData.getInstance().getImages());
-			} else if (dialog.group.isSelected(dialog.sequence.getModel())) {
-				ArrayList<MapillaryAbstractImage> images = new ArrayList<>();
-				for (MapillaryAbstractImage image : MapillaryData.getInstance().getMultiSelectedImages())
-					if (image instanceof MapillaryImage) {
-						if (!images.contains(image))
-							images.addAll(((MapillaryImage) image).getSequence().getImages());
-					}
-					else
-						images.add(image);
-				export(images);
-			} else if (dialog.group.isSelected(dialog.selected.getModel())) {
-				export(MapillaryData.getInstance().getMultiSelectedImages());
-			} 
-		// This option ignores the selected directory.
-		 } else if (dialog.group.isSelected(dialog.rewrite.getModel())) {
-			ArrayList<MapillaryImportedImage> images = new ArrayList<>();
-			for (MapillaryAbstractImage image : MapillaryData.getInstance().getImages())
-				if (image instanceof MapillaryImportedImage) {
-					images.add(((MapillaryImportedImage) image));
-				}
-			try {
-				Main.worker.submit(new Thread(new MapillaryExportManager(images)));
-			} catch (IOException e1) {
-				Main.error(e1);
-			}
-		}
-		dlg.dispose();
-	}
+        // Checks if the inputs are correct and starts the export process.
+        if (pane.getValue() != null
+                && (int) pane.getValue() == JOptionPane.OK_OPTION
+                && dialog.chooser != null) {
+            if (dialog.group.isSelected(dialog.all.getModel())) {
+                export(MapillaryData.getInstance().getImages());
+            } else if (dialog.group.isSelected(dialog.sequence.getModel())) {
+                ArrayList<MapillaryAbstractImage> images = new ArrayList<>();
+                for (MapillaryAbstractImage image : MapillaryData.getInstance()
+                        .getMultiSelectedImages())
+                    if (image instanceof MapillaryImage) {
+                        if (!images.contains(image))
+                            images.addAll(((MapillaryImage) image)
+                                    .getSequence().getImages());
+                    } else
+                        images.add(image);
+                export(images);
+            } else if (dialog.group.isSelected(dialog.selected.getModel())) {
+                export(MapillaryData.getInstance().getMultiSelectedImages());
+            }
+            // This option ignores the selected directory.
+        } else if (dialog.group.isSelected(dialog.rewrite.getModel())) {
+            ArrayList<MapillaryImportedImage> images = new ArrayList<>();
+            for (MapillaryAbstractImage image : MapillaryData.getInstance()
+                    .getImages())
+                if (image instanceof MapillaryImportedImage) {
+                    images.add(((MapillaryImportedImage) image));
+                }
+            try {
+                Main.worker.submit(new Thread(
+                        new MapillaryExportManager(images)));
+            } catch (IOException e1) {
+                Main.error(e1);
+            }
+        }
+        dlg.dispose();
+    }
 
-	/**
-	 * Exports the given images from the database.
-	 */
-	public void export(List<MapillaryAbstractImage> images) {
-		Main.worker.submit(new Thread(new MapillaryExportManager(images,
-				dialog.chooser.getSelectedFile().toString())));
-	}
+    /**
+     * Exports the given images from the database.
+     */
+    public void export(List<MapillaryAbstractImage> images) {
+        Main.worker.submit(new Thread(new MapillaryExportManager(images,
+                dialog.chooser.getSelectedFile().toString())));
+    }
 
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java	(revision 31278)
@@ -38,154 +38,154 @@
 public class MapillaryImportAction extends JosmAction {
 
-	public JFileChooser chooser;
+    public JFileChooser chooser;
 
-	/**
-	 * Amount of pictures without the proper EXIF tags.
-	 */
-	private int noTagsPics = 0;
+    /**
+     * Amount of pictures without the proper EXIF tags.
+     */
+    private int noTagsPics = 0;
 
-	public MapillaryImportAction() {
-		super(tr("Import pictures"), new ImageProvider("icon24.png"),
-				tr("Import local pictures"), Shortcut.registerShortcut(
-						"Import Mapillary",
-						tr("Import pictures into Mapillary layer"),
-						KeyEvent.VK_M, Shortcut.NONE), false,
-				"mapillaryImport", false);
-		this.setEnabled(false);
-	}
+    public MapillaryImportAction() {
+        super(tr("Import pictures"), new ImageProvider("icon24.png"),
+                tr("Import local pictures"), Shortcut.registerShortcut(
+                        "Import Mapillary",
+                        tr("Import pictures into Mapillary layer"),
+                        KeyEvent.VK_M, Shortcut.NONE), false,
+                "mapillaryImport", false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent e) {
-		chooser = new JFileChooser();
-		chooser.setCurrentDirectory(new java.io.File(System
-				.getProperty("user.home")));
-		chooser.setDialogTitle(tr("Select pictures"));
-		chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
-		chooser.setAcceptAllFileFilterUsed(false);
-		chooser.addChoosableFileFilter(new FileNameExtensionFilter("images",
-				"jpg", "jpeg", "png"));
-		chooser.setMultiSelectionEnabled(true);
-		if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) {
-			for (int i = 0; i < chooser.getSelectedFiles().length; i++) {
-				File file = chooser.getSelectedFiles()[i];
-				if (file.isDirectory()) {
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        chooser = new JFileChooser();
+        chooser.setCurrentDirectory(new java.io.File(System
+                .getProperty("user.home")));
+        chooser.setDialogTitle(tr("Select pictures"));
+        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
+        chooser.setAcceptAllFileFilterUsed(false);
+        chooser.addChoosableFileFilter(new FileNameExtensionFilter("images",
+                "jpg", "jpeg", "png"));
+        chooser.setMultiSelectionEnabled(true);
+        if (chooser.showOpenDialog(Main.parent) == JFileChooser.APPROVE_OPTION) {
+            for (int i = 0; i < chooser.getSelectedFiles().length; i++) {
+                File file = chooser.getSelectedFiles()[i];
+                if (file.isDirectory()) {
 
-				} else {
-					if (file.getPath().substring(file.getPath().length() - 4)
-							.equals(".jpg")
-							|| file.getPath()
-									.substring(file.getPath().length() - 5)
-									.equals(".jpeg")) {
-						try {
-							readJPG(file);
-						} catch (ImageReadException ex) {
-							Main.error(ex);
-						} catch (IOException ex) {
-							Main.error(ex);
-						}
-					} else if (file.getPath()
-							.substring(file.getPath().length() - 4)
-							.equals(".png")) {
-						readPNG(file);
-					}
-				}
-			}
-		}
-		MapillaryLayer.getInstance();
-	}
+                } else {
+                    if (file.getPath().substring(file.getPath().length() - 4)
+                            .equals(".jpg")
+                            || file.getPath()
+                                    .substring(file.getPath().length() - 5)
+                                    .equals(".jpeg")) {
+                        try {
+                            readJPG(file);
+                        } catch (ImageReadException ex) {
+                            Main.error(ex);
+                        } catch (IOException ex) {
+                            Main.error(ex);
+                        }
+                    } else if (file.getPath()
+                            .substring(file.getPath().length() - 4)
+                            .equals(".png")) {
+                        readPNG(file);
+                    }
+                }
+            }
+        }
+        MapillaryLayer.getInstance();
+    }
 
-	/**
-	 * Reads a jpg pictures that contains the needed GPS information (position
-	 * and direction) and creates a new icon in that position.
-	 * 
-	 * @param file
-	 * @throws ImageReadException
-	 * @throws IOException
-	 */
-	public void readJPG(File file) throws ImageReadException, IOException {
-		final ImageMetadata metadata = Imaging.getMetadata(file);
-		if (metadata instanceof JpegImageMetadata) {
-			final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
-			final TiffField lat_ref = jpegMetadata
-					.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
-			final TiffField lat = jpegMetadata
-					.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE);
-			final TiffField lon_ref = jpegMetadata
-					.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
-			final TiffField lon = jpegMetadata
-					.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);
-			final TiffField ca = jpegMetadata
-					.findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
-			final TiffField datetimeOriginal = jpegMetadata
-					.findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
-			if (lat_ref == null || lat == null || lon == null
-					|| lon_ref == null) {
-				readNoTags(file);
-			}
-			double latValue = 0;
-			double lonValue = 0;
-			double caValue = 0;
-			if (lat != null && lat.getValue() instanceof RationalNumber[])
-				latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(),
-						lat_ref.getValue().toString());
-			if (lon != null && lon.getValue() instanceof RationalNumber[])
-				lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(),
-						lon_ref.getValue().toString());
-			if (ca != null && ca.getValue() instanceof RationalNumber)
-				caValue = ((RationalNumber) ca.getValue()).doubleValue();
-			if (lat_ref.getValue().toString().equals("S"))
-				latValue = -latValue;
-			if (lon_ref.getValue().toString().equals("W"))
-				lonValue = -lonValue;
-			if (datetimeOriginal != null)
-				MapillaryData.getInstance().add(
-						new MapillaryImportedImage(latValue, lonValue, caValue,
-								file, datetimeOriginal.getStringValue()));
-			else
-				MapillaryData.getInstance().add(
-						new MapillaryImportedImage(latValue, lonValue, caValue,
-								file, currentDate()));
-		}
-	}
+    /**
+     * Reads a jpg pictures that contains the needed GPS information (position
+     * and direction) and creates a new icon in that position.
+     * 
+     * @param file
+     * @throws ImageReadException
+     * @throws IOException
+     */
+    public void readJPG(File file) throws ImageReadException, IOException {
+        final ImageMetadata metadata = Imaging.getMetadata(file);
+        if (metadata instanceof JpegImageMetadata) {
+            final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
+            final TiffField lat_ref = jpegMetadata
+                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF);
+            final TiffField lat = jpegMetadata
+                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LATITUDE);
+            final TiffField lon_ref = jpegMetadata
+                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF);
+            final TiffField lon = jpegMetadata
+                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_LONGITUDE);
+            final TiffField ca = jpegMetadata
+                    .findEXIFValueWithExactMatch(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
+            final TiffField datetimeOriginal = jpegMetadata
+                    .findEXIFValueWithExactMatch(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
+            if (lat_ref == null || lat == null || lon == null
+                    || lon_ref == null) {
+                readNoTags(file);
+            }
+            double latValue = 0;
+            double lonValue = 0;
+            double caValue = 0;
+            if (lat != null && lat.getValue() instanceof RationalNumber[])
+                latValue = DegMinSecToDouble((RationalNumber[]) lat.getValue(),
+                        lat_ref.getValue().toString());
+            if (lon != null && lon.getValue() instanceof RationalNumber[])
+                lonValue = DegMinSecToDouble((RationalNumber[]) lon.getValue(),
+                        lon_ref.getValue().toString());
+            if (ca != null && ca.getValue() instanceof RationalNumber)
+                caValue = ((RationalNumber) ca.getValue()).doubleValue();
+            if (lat_ref.getValue().toString().equals("S"))
+                latValue = -latValue;
+            if (lon_ref.getValue().toString().equals("W"))
+                lonValue = -lonValue;
+            if (datetimeOriginal != null)
+                MapillaryData.getInstance().add(
+                        new MapillaryImportedImage(latValue, lonValue, caValue,
+                                file, datetimeOriginal.getStringValue()));
+            else
+                MapillaryData.getInstance().add(
+                        new MapillaryImportedImage(latValue, lonValue, caValue,
+                                file, currentDate()));
+        }
+    }
 
-	/**
-	 * Reads a image file that doesn't contain the needed GPS information. And
-	 * creates a new icon in the middle of the map.
-	 * 
-	 * @param file
-	 */
-	private void readNoTags(File file) {
-		double HORIZONTAL_DISTANCE = 0.0001;
-		double horDev;
-		if (noTagsPics % 2 == 0)
-			horDev = HORIZONTAL_DISTANCE * noTagsPics / 2;
-		else
-			horDev = -HORIZONTAL_DISTANCE * (noTagsPics + 1) / 2;
-		LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon(
-				Main.map.mapView.getCenter());
-		MapillaryData.getInstance().add(
-				new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0,
-						file, currentDate()));
-		noTagsPics++;
-	}
+    /**
+     * Reads a image file that doesn't contain the needed GPS information. And
+     * creates a new icon in the middle of the map.
+     * 
+     * @param file
+     */
+    private void readNoTags(File file) {
+        double HORIZONTAL_DISTANCE = 0.0001;
+        double horDev;
+        if (noTagsPics % 2 == 0)
+            horDev = HORIZONTAL_DISTANCE * noTagsPics / 2;
+        else
+            horDev = -HORIZONTAL_DISTANCE * (noTagsPics + 1) / 2;
+        LatLon pos = Main.map.mapView.getProjection().eastNorth2latlon(
+                Main.map.mapView.getCenter());
+        MapillaryData.getInstance().add(
+                new MapillaryImportedImage(pos.lat(), pos.lon() + horDev, 0,
+                        file, currentDate()));
+        noTagsPics++;
+    }
 
-	private void readPNG(File file) {
-		readNoTags(file);
-	}
+    private void readPNG(File file) {
+        readNoTags(file);
+    }
 
-	private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) {
-		RationalNumber deg = degMinSec[0];
-		RationalNumber min = degMinSec[1];
-		RationalNumber sec = degMinSec[2];
-		return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue()
-				/ 3600;
-	}
-	
-	private String currentDate() {
-		   Calendar cal = Calendar.getInstance();
+    private double DegMinSecToDouble(RationalNumber[] degMinSec, String ref) {
+        RationalNumber deg = degMinSec[0];
+        RationalNumber min = degMinSec[1];
+        RationalNumber sec = degMinSec[2];
+        return deg.doubleValue() + min.doubleValue() / 60 + sec.doubleValue()
+                / 3600;
+    }
 
-			SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
-			return formatter.format(cal);
-	
-	}
+    private String currentDate() {
+        Calendar cal = Calendar.getInstance();
+
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
+        return formatter.format(cal);
+
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySignAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySignAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillarySignAction.java	(revision 31278)
@@ -20,16 +20,18 @@
 public class MapillarySignAction extends JosmAction {
 
-	public MapillarySignAction() {
-		super(tr("Switch sign/normal mode"), new ImageProvider("icon24sign.png"),
-				tr("Switch sign/normal mode"), Shortcut.registerShortcut(
-						"Mapillary sign", tr("Switch Mapillary plugin's sign mode on/off"),
-						KeyEvent.VK_M, Shortcut.NONE), false,
-				"mapillarySign", false);
-		this.setEnabled(false);
-	}
+    public MapillarySignAction() {
+        super(tr("Switch sign/normal mode"),
+                new ImageProvider("icon24sign.png"),
+                tr("Switch sign/normal mode"), Shortcut.registerShortcut(
+                        "Mapillary sign",
+                        tr("Switch Mapillary plugin's sign mode on/off"),
+                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillarySign",
+                false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent e) {
-		MapillaryToggleDialog.getInstance().switchMode();
-	}
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        MapillaryToggleDialog.getInstance().switchMode();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryZoomAction.java	(revision 31278)
@@ -22,32 +22,32 @@
  */
 public class MapillaryZoomAction extends JosmAction implements
-		MapillaryDataListener {
+        MapillaryDataListener {
 
-	public MapillaryZoomAction() {
-		super(tr("Zoom to selected image"), new ImageProvider("icon24.png"),
-				tr("Zoom to selected image"), Shortcut.registerShortcut(
-						"Zoom Mapillary",
-						tr("Zoom to the currently selected Mapillary image"),
-						KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryZoom",
-				false);
-		MapillaryData.getInstance().addListener(this);
-		this.setEnabled(false);
-	}
+    public MapillaryZoomAction() {
+        super(tr("Zoom to selected image"), new ImageProvider("icon24.png"),
+                tr("Zoom to selected image"), Shortcut.registerShortcut(
+                        "Zoom Mapillary",
+                        tr("Zoom to the currently selected Mapillary image"),
+                        KeyEvent.VK_M, Shortcut.NONE), false, "mapillaryZoom",
+                false);
+        MapillaryData.getInstance().addListener(this);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		if (MapillaryData.getInstance().getSelectedImage() == null)
-			throw new IllegalStateException();
-		Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage()
-				.getLatLon());
-	}
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        if (MapillaryData.getInstance().getSelectedImage() == null)
+            throw new IllegalStateException();
+        Main.map.mapView.zoomTo(MapillaryData.getInstance().getSelectedImage()
+                .getLatLon());
+    }
 
-	@Override
-	public void selectedImageChanged(MapillaryAbstractImage oldImage,
-			MapillaryAbstractImage newImage) {
-		if (oldImage == null && newImage != null)
-			MapillaryPlugin.ZOOM_MENU.setEnabled(true);
-		else if (oldImage != null && newImage == null)
-			MapillaryPlugin.ZOOM_MENU.setEnabled(false);
-	}
+    @Override
+    public void selectedImageChanged(MapillaryAbstractImage oldImage,
+            MapillaryAbstractImage newImage) {
+        if (oldImage == null && newImage != null)
+            MapillaryPlugin.ZOOM_MENU.setEnabled(true);
+        else if (oldImage != null && newImage == null)
+            MapillaryPlugin.ZOOM_MENU.setEnabled(false);
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java	(revision 31278)
@@ -11,58 +11,59 @@
 
 public class MapillaryCache extends
-		JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
+        JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
 
-	private volatile URL url;
-	private volatile String key;
+    private volatile URL url;
+    private volatile String key;
 
-	public static enum Type {
-		FULL_IMAGE, THUMBNAIL
-	}
+    public static enum Type {
+        FULL_IMAGE, THUMBNAIL
+    }
 
-	public MapillaryCache(String key, Type type) {
-		super(MapillaryPlugin.CACHE, 50000, 50000, new HashMap<String, String>());
-		this.key = key;
-		try {
-			if (type == Type.FULL_IMAGE) {
-				url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
-						+ "/thumb-2048.jpg");
-				this.key += ".FULL_IMAGE";
+    public MapillaryCache(String key, Type type) {
+        super(MapillaryPlugin.CACHE, 50000, 50000,
+                new HashMap<String, String>());
+        this.key = key;
+        try {
+            if (type == Type.FULL_IMAGE) {
+                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
+                        + "/thumb-2048.jpg");
+                this.key += ".FULL_IMAGE";
 
-			} else if (type == Type.THUMBNAIL) {
-				url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
-						+ "/thumb-320.jpg");
-				this.key += ".THUMBNAIL";
-			}
-		} catch (MalformedURLException e) {
-			Main.error(e);
-		}
-	}
+            } else if (type == Type.THUMBNAIL) {
+                url = new URL("https://d1cuyjsrcm0gby.cloudfront.net/" + key
+                        + "/thumb-320.jpg");
+                this.key += ".THUMBNAIL";
+            }
+        } catch (MalformedURLException e) {
+            Main.error(e);
+        }
+    }
 
-	@Override
-	public String getCacheKey() {
-		return key;
-	}
+    @Override
+    public String getCacheKey() {
+        return key;
+    }
 
-	@Override
-	public URL getUrl() {
-		return url;
-	}
+    @Override
+    public URL getUrl() {
+        return url;
+    }
 
-	@Override
-	protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
-		return new BufferedImageCacheEntry(content);
-	}
+    @Override
+    protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
+        return new BufferedImageCacheEntry(content);
+    }
 
-	@Override
-	protected boolean isObjectLoadable() {
-		if (cacheData == null)
-			return false;
-		byte[] content = cacheData.getContent();
-		return content != null && content.length > 0;
-	}
+    @Override
+    protected boolean isObjectLoadable() {
+        if (cacheData == null)
+            return false;
+        byte[] content = cacheData.getContent();
+        return content != null && content.length > 0;
+    }
 
-	// @Override
-	protected boolean handleNotFound() {
-		return false;
-	}
+    // @Override
+    protected boolean handleNotFound() {
+        return false;
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandMoveImage.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandMoveImage.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandMoveImage.java	(revision 31278)
@@ -16,43 +16,45 @@
  */
 public class CommandMoveImage extends MapillaryCommand {
-	private double x;
-	private double y;
+    private double x;
+    private double y;
 
-	public CommandMoveImage(List<MapillaryAbstractImage> images, double x, double y) {
-		this.images = new ArrayList<>(images);
-		this.x = x;
-		this.y = y;
-	}
+    public CommandMoveImage(List<MapillaryAbstractImage> images, double x,
+            double y) {
+        this.images = new ArrayList<>(images);
+        this.x = x;
+        this.y = y;
+    }
 
-	@Override
-	public void undo() {
-		for (MapillaryAbstractImage image : images) {
-			image.move(-x, -y);
-			image.stopMoving();
-		}
-		checkModified();
-		Main.map.repaint();
-	}
+    @Override
+    public void undo() {
+        for (MapillaryAbstractImage image : images) {
+            image.move(-x, -y);
+            image.stopMoving();
+        }
+        checkModified();
+        Main.map.repaint();
+    }
 
-	@Override
-	public void redo() {
-		for (MapillaryAbstractImage image : images) {
-			image.move(x, y);
-			image.stopMoving();
-		}
-		checkModified();
-		Main.map.repaint();
-	}
-	
-	public String toString() {
-		return trn("Moved {0} node", "Moved {0} nodes", images.size(), images.size());
-	}
-	
-	@Override
-	public void sum(MapillaryCommand command) {
-		if (command instanceof CommandMoveImage) {
-			this.x += ((CommandMoveImage) command).x;
-			this.y += ((CommandMoveImage) command).y;
-		}
-	}
+    @Override
+    public void redo() {
+        for (MapillaryAbstractImage image : images) {
+            image.move(x, y);
+            image.stopMoving();
+        }
+        checkModified();
+        Main.map.repaint();
+    }
+
+    public String toString() {
+        return trn("Moved {0} node", "Moved {0} nodes", images.size(),
+                images.size());
+    }
+
+    @Override
+    public void sum(MapillaryCommand command) {
+        if (command instanceof CommandMoveImage) {
+            this.x += ((CommandMoveImage) command).x;
+            this.y += ((CommandMoveImage) command).y;
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandTurnImage.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandTurnImage.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/CommandTurnImage.java	(revision 31278)
@@ -16,41 +16,41 @@
  */
 public class CommandTurnImage extends MapillaryCommand {
-	private double ca;
+    private double ca;
 
-	public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) {
-		this.images = new ArrayList<>(images);
-		this.ca = ca;
-	}
+    public CommandTurnImage(List<MapillaryAbstractImage> images, double ca) {
+        this.images = new ArrayList<>(images);
+        this.ca = ca;
+    }
 
-	@Override
-	public void undo() {
-		for (MapillaryAbstractImage image : images) {
-			image.turn(-ca);
-			image.stopMoving();
-		}
-		checkModified();
-		Main.map.repaint();
-	}
+    @Override
+    public void undo() {
+        for (MapillaryAbstractImage image : images) {
+            image.turn(-ca);
+            image.stopMoving();
+        }
+        checkModified();
+        Main.map.repaint();
+    }
 
-	@Override
-	public void redo() {
-		for (MapillaryAbstractImage image : images) {
-			image.turn(ca);
-			image.stopMoving();
-		}
-		checkModified();
-		Main.map.repaint();
-	}
+    @Override
+    public void redo() {
+        for (MapillaryAbstractImage image : images) {
+            image.turn(ca);
+            image.stopMoving();
+        }
+        checkModified();
+        Main.map.repaint();
+    }
 
-	public String toString() {
-		return trn("Turned {0} node", "Turned {0} nodes", this.images.size(),
-				this.images.size());
-	}
+    public String toString() {
+        return trn("Turned {0} node", "Turned {0} nodes", this.images.size(),
+                this.images.size());
+    }
 
-	@Override
-	public void sum(MapillaryCommand command) {
-		if (command instanceof CommandTurnImage) {
-			this.ca += ((CommandTurnImage) command).ca;
-		}
-	}
+    @Override
+    public void sum(MapillaryCommand command) {
+        if (command instanceof CommandTurnImage) {
+            this.ca += ((CommandTurnImage) command).ca;
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryCommand.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryCommand.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryCommand.java	(revision 31278)
@@ -12,25 +12,25 @@
  */
 public abstract class MapillaryCommand {
-	protected List<MapillaryAbstractImage> images;
+    protected List<MapillaryAbstractImage> images;
 
-	public abstract void undo();
+    public abstract void undo();
 
-	public abstract void redo();
+    public abstract void redo();
 
-	/**
-	 * If two equal commands are applied consecutively to the same set of
-	 * images, they are summed in order to reduce them to just one command.
-	 * 
-	 * @param command
-	 */
-	public abstract void sum(MapillaryCommand command);
+    /**
+     * If two equal commands are applied consecutively to the same set of
+     * images, they are summed in order to reduce them to just one command.
+     * 
+     * @param command
+     */
+    public abstract void sum(MapillaryCommand command);
 
-	/**
-	 * Checks if the image has been modified, compairing with its original
-	 * values.
-	 */
-	public void checkModified() {
-		for (MapillaryAbstractImage image : images)
-			image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca);
-	}
+    /**
+     * Checks if the image has been modified, compairing with its original
+     * values.
+     */
+    public void checkModified() {
+        for (MapillaryAbstractImage image : images)
+            image.isModified = (image.tempLatLon == image.latLon || image.tempCa == image.ca);
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecord.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecord.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecord.java	(revision 31278)
@@ -10,80 +10,80 @@
  */
 public class MapillaryRecord {
-	public static MapillaryRecord INSTANCE;
+    public static MapillaryRecord INSTANCE;
 
-	private ArrayList<MapillaryRecordListener> listeners;
+    private ArrayList<MapillaryRecordListener> listeners;
 
-	public ArrayList<MapillaryCommand> commandList;
-	/** Last written command */
-	public int position;
+    public ArrayList<MapillaryCommand> commandList;
+    /** Last written command */
+    public int position;
 
-	public MapillaryRecord() {
-		commandList = new ArrayList<>();
-		position = -1;
-		listeners = new ArrayList<>();
-	}
+    public MapillaryRecord() {
+        commandList = new ArrayList<>();
+        position = -1;
+        listeners = new ArrayList<>();
+    }
 
-	public static synchronized MapillaryRecord getInstance() {
-		if (MapillaryRecord.INSTANCE == null)
-			MapillaryRecord.INSTANCE = new MapillaryRecord();
-		return MapillaryRecord.INSTANCE;
-	}
+    public static synchronized MapillaryRecord getInstance() {
+        if (MapillaryRecord.INSTANCE == null)
+            MapillaryRecord.INSTANCE = new MapillaryRecord();
+        return MapillaryRecord.INSTANCE;
+    }
 
-	public void addListener(MapillaryRecordListener lis) {
-		this.listeners.add(lis);
-	}
+    public void addListener(MapillaryRecordListener lis) {
+        this.listeners.add(lis);
+    }
 
-	public void removeListener(MapillaryRecordListener lis) {
-		this.listeners.remove(lis);
-	}
+    public void removeListener(MapillaryRecordListener lis) {
+        this.listeners.remove(lis);
+    }
 
-	/**
-	 * Adds a new command to the list.
-	 * 
-	 * @param command
-	 */
-	public void addCommand(MapillaryCommand command) {
-		// Checks if it is a continuation of last command
-		if (position != -1
-				&& commandList.get(position).images.equals(command.images)
-				&& commandList.get(position).getClass() == command.getClass()) {
-			commandList.get(position).sum(command);
-			fireRecordChanged();
-			return;
-		}
-		commandList.add(position + 1, command);
-		position++;
-		while (commandList.size() > position + 1) {
-			commandList.remove(position + 1);
-		}
-		fireRecordChanged();
-	}
+    /**
+     * Adds a new command to the list.
+     * 
+     * @param command
+     */
+    public void addCommand(MapillaryCommand command) {
+        // Checks if it is a continuation of last command
+        if (position != -1
+                && commandList.get(position).images.equals(command.images)
+                && commandList.get(position).getClass() == command.getClass()) {
+            commandList.get(position).sum(command);
+            fireRecordChanged();
+            return;
+        }
+        commandList.add(position + 1, command);
+        position++;
+        while (commandList.size() > position + 1) {
+            commandList.remove(position + 1);
+        }
+        fireRecordChanged();
+    }
 
-	/**
-	 * Undo latest command.
-	 */
-	public void undo() {
-		if (position == -1)
-			return;
-		commandList.get(position).undo();
-		position--;
-		fireRecordChanged();
-	}
+    /**
+     * Undo latest command.
+     */
+    public void undo() {
+        if (position == -1)
+            return;
+        commandList.get(position).undo();
+        position--;
+        fireRecordChanged();
+    }
 
-	/**
-	 * Redo latest undoed action.
-	 */
-	public void redo() {
-		if (position + 1 >= commandList.size())
-			return;
-		position++;
-		commandList.get(position).redo();
-		fireRecordChanged();
-	}
+    /**
+     * Redo latest undoed action.
+     */
+    public void redo() {
+        if (position + 1 >= commandList.size())
+            return;
+        position++;
+        commandList.get(position).redo();
+        fireRecordChanged();
+    }
 
-	private void fireRecordChanged() {
-		for (MapillaryRecordListener lis : listeners)
-			if (lis != null)
-				lis.recordChanged();
-	}
+    private void fireRecordChanged() {
+        for (MapillaryRecordListener lis : listeners)
+            if (lis != null)
+                lis.recordChanged();
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecordListener.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecordListener.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/commands/MapillaryRecordListener.java	(revision 31278)
@@ -2,4 +2,4 @@
 
 public interface MapillaryRecordListener {
-	public void recordChanged();
+    public void recordChanged();
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31278)
@@ -15,57 +15,58 @@
 public class MapillaryDownloader {
 
-	public final static String BASE_URL = "https://a.mapillary.com/v2/";
-	public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
+    public final static String BASE_URL = "https://a.mapillary.com/v2/";
+    public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
 
-	private String[] parameters = { "lat", "lon", "distance", "limit",
-			"min_lat", "min_lon", "max_lat", "max_lon" };
+    private String[] parameters = { "lat", "lon", "distance", "limit",
+            "min_lat", "min_lon", "max_lat", "max_lon" };
 
-	public MapillaryDownloader() {
-	}
+    public MapillaryDownloader() {
+    }
 
-	/**
-	 * Gets all the images in a square. It downloads all the images of all the
-	 * sequences that pass through the given rectangle.
-	 * 
-	 * @param minLatLon
-	 *            The minimum latitude and longitude of the rectangle.
-	 * @param maxLatLon
-	 *            The maximum latitude and longitude of the rectangle
-	 */
-	public void getImages(LatLon minLatLon, LatLon maxLatLon) {
-		String url1 = BASE_URL;
-		String url2 = BASE_URL;
-		String url3 = BASE_URL;
-		url1 += "search/im/";
-		url2 += "search/s/";
-		url3 += "search/im/or";
-		ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
-		hash.put("min_lat", minLatLon.lat());
-		hash.put("min_lon", minLatLon.lon());
-		hash.put("max_lat", maxLatLon.lat());
-		hash.put("max_lon", maxLatLon.lon());
-		url1 += buildParameters(hash);
-		url2 += buildParameters(hash);
-		url3 += buildParameters(hash);
-		System.out.println(url2);
-		
-		try {
-			Main.info("MapillaryPlugin GET " + url2);
-			Main.worker.submit(new MapillarySquareDownloadManagerThread(url1, url2, url3));
-		} catch (Exception e) {
-			Main.error(e);
-		}
-	}
-	
-	public void getImages(Bounds bounds) {
-		getImages(bounds.getMin(), bounds.getMax());
-	}
+    /**
+     * Gets all the images in a square. It downloads all the images of all the
+     * sequences that pass through the given rectangle.
+     * 
+     * @param minLatLon
+     *            The minimum latitude and longitude of the rectangle.
+     * @param maxLatLon
+     *            The maximum latitude and longitude of the rectangle
+     */
+    public void getImages(LatLon minLatLon, LatLon maxLatLon) {
+        String url1 = BASE_URL;
+        String url2 = BASE_URL;
+        String url3 = BASE_URL;
+        url1 += "search/im/";
+        url2 += "search/s/";
+        url3 += "search/im/or";
+        ConcurrentHashMap<String, Double> hash = new ConcurrentHashMap<>();
+        hash.put("min_lat", minLatLon.lat());
+        hash.put("min_lon", minLatLon.lon());
+        hash.put("max_lat", maxLatLon.lat());
+        hash.put("max_lon", maxLatLon.lon());
+        url1 += buildParameters(hash);
+        url2 += buildParameters(hash);
+        url3 += buildParameters(hash);
+        System.out.println(url2);
 
-	private String buildParameters(ConcurrentHashMap<String, Double> hash) {
-		String ret = "?client_id=" + CLIENT_ID;
-		for (int i = 0; i < parameters.length; i++)
-			if (hash.get(parameters[i]) != null)
-				ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
-		return ret;
-	}
+        try {
+            Main.info("MapillaryPlugin GET " + url2);
+            Main.worker.submit(new MapillarySquareDownloadManagerThread(url1,
+                    url2, url3));
+        } catch (Exception e) {
+            Main.error(e);
+        }
+    }
+
+    public void getImages(Bounds bounds) {
+        getImages(bounds.getMin(), bounds.getMax());
+    }
+
+    private String buildParameters(ConcurrentHashMap<String, Double> hash) {
+        String ret = "?client_id=" + CLIENT_ID;
+        for (int i = 0; i < parameters.length; i++)
+            if (hash.get(parameters[i]) != null)
+                ret += "&" + parameters[i] + "=" + hash.get(parameters[i]);
+        return ret;
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportDownloadThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportDownloadThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportDownloadThread.java	(revision 31278)
@@ -25,42 +25,42 @@
  */
 public class MapillaryExportDownloadThread implements Runnable,
-		ICachedLoaderListener {
+        ICachedLoaderListener {
 
-	String url;
-	ArrayBlockingQueue<BufferedImage> queue;
-	ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
+    String url;
+    ArrayBlockingQueue<BufferedImage> queue;
+    ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
 
-	ProgressMonitor monitor;
-	MapillaryImage image;
+    ProgressMonitor monitor;
+    MapillaryImage image;
 
-	public MapillaryExportDownloadThread(MapillaryImage image,
-			ArrayBlockingQueue<BufferedImage> queue,
-			ArrayBlockingQueue<MapillaryAbstractImage> queueImages) {
-		url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey()
-				+ "/thumb-2048.jpg";
-		this.queue = queue;
-		this.image = image;
-		this.queueImages = queueImages;
-	}
+    public MapillaryExportDownloadThread(MapillaryImage image,
+            ArrayBlockingQueue<BufferedImage> queue,
+            ArrayBlockingQueue<MapillaryAbstractImage> queueImages) {
+        url = "https://d1cuyjsrcm0gby.cloudfront.net/" + image.getKey()
+                + "/thumb-2048.jpg";
+        this.queue = queue;
+        this.image = image;
+        this.queueImages = queueImages;
+    }
 
-	@Override
-	public void run() {
-		new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE).submit(this,
-				false);
+    @Override
+    public void run() {
+        new MapillaryCache(image.getKey(), MapillaryCache.Type.FULL_IMAGE)
+                .submit(this, false);
 
-	}
+    }
 
-	@Override
-	public void loadingFinished(CacheEntry data,
-			CacheEntryAttributes attributes, LoadResult result) {
-		try {
-			queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent())));
-			queueImages.put(image);
+    @Override
+    public void loadingFinished(CacheEntry data,
+            CacheEntryAttributes attributes, LoadResult result) {
+        try {
+            queue.put(ImageIO.read(new ByteArrayInputStream(data.getContent())));
+            queueImages.put(image);
 
-		} catch (InterruptedException e) {
-			Main.error(e);
-		} catch (IOException e) {
-			Main.error(e);
-		}
-	}
+        } catch (InterruptedException e) {
+            Main.error(e);
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportManager.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportManager.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportManager.java	(revision 31278)
@@ -32,98 +32,100 @@
 public class MapillaryExportManager extends PleaseWaitRunnable {
 
-	ArrayBlockingQueue<BufferedImage> queue;
-	ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
+    ArrayBlockingQueue<BufferedImage> queue;
+    ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
 
-	final int amount;
-	List<MapillaryAbstractImage> images;
-	String path;
+    final int amount;
+    List<MapillaryAbstractImage> images;
+    String path;
 
-	public MapillaryExportManager(List<MapillaryAbstractImage> images,
-			String path) {
-		super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
-				"Exporting Mapillary Images"), true);
-		queue = new ArrayBlockingQueue<>(10);
-		queueImages = new ArrayBlockingQueue<>(10);
+    public MapillaryExportManager(List<MapillaryAbstractImage> images,
+            String path) {
+        super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
+                "Exporting Mapillary Images"), true);
+        queue = new ArrayBlockingQueue<>(10);
+        queueImages = new ArrayBlockingQueue<>(10);
 
-		this.images = images;
-		amount = images.size();
-		this.path = path;
-	}
-	
-	/**
-	 * Constructor used to rewrite imported images.
-	 * @param images
-	 * @throws IOException
-	 */
-	public MapillaryExportManager(List<MapillaryImportedImage> images) throws IOException {
-		super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
-				"Exporting Mapillary Images"), true);
-		queue = new ArrayBlockingQueue<>(10);
-		queueImages = new ArrayBlockingQueue<>(10);
-		for (MapillaryImportedImage image : images) {
-			queue.add(image.getImage());
-			queueImages.add(image);
-		}
-		amount = images.size();		
-	}
+        this.images = images;
+        amount = images.size();
+        this.path = path;
+    }
 
-	@Override
-	protected void cancel() {
-		// TODO Auto-generated method stub
-	}
+    /**
+     * Constructor used to rewrite imported images.
+     * 
+     * @param images
+     * @throws IOException
+     */
+    public MapillaryExportManager(List<MapillaryImportedImage> images)
+            throws IOException {
+        super(tr("Downloading") + "...", new PleaseWaitProgressMonitor(
+                "Exporting Mapillary Images"), true);
+        queue = new ArrayBlockingQueue<>(10);
+        queueImages = new ArrayBlockingQueue<>(10);
+        for (MapillaryImportedImage image : images) {
+            queue.add(image.getImage());
+            queueImages.add(image);
+        }
+        amount = images.size();
+    }
 
-	@Override
-	protected void realRun() throws SAXException, IOException,
-			OsmTransferException {
-		// Starts a writer thread in order to write the pictures on the disk.
-		Thread writer = new Thread(new MapillaryExportWriterThread(path, queue,
-				queueImages, amount, this.getProgressMonitor()));
-		writer.start();
-		if (path == null) {
-			try {
-				writer.join();
-			} catch (InterruptedException e) {
-				Main.error(e);
-			}
-			return;
-		}
-		ThreadPoolExecutor ex = new ThreadPoolExecutor(20, 35, 25,
-				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
-		for (MapillaryAbstractImage image : images) {
-			if (image instanceof MapillaryImage) {
-				try {
-					ex.execute(new MapillaryExportDownloadThread(
-							(MapillaryImage) image, queue, queueImages));
-				} catch (Exception e) {
-					Main.error(e);
-				}
-			} else if (image instanceof MapillaryImportedImage) {
-				try {
-					queue.put(((MapillaryImportedImage) image).getImage());
-					queueImages.put((MapillaryImportedImage) image);
-				} catch (InterruptedException e) {
-					Main.error(e);
-				}
-			}
-			try {
-				// If the queue is full, waits for it to have more space
-				// available before executing anything else.
-				while (ex.getQueue().remainingCapacity() == 0)
-					Thread.sleep(100);
-			} catch (Exception e) {
-				Main.error(e);
-			}
-		}
-		try {
-			writer.join();
-		} catch (InterruptedException e) {
-			Main.error(e);
-		}
+    @Override
+    protected void cancel() {
+        // TODO Auto-generated method stub
+    }
 
-	}
+    @Override
+    protected void realRun() throws SAXException, IOException,
+            OsmTransferException {
+        // Starts a writer thread in order to write the pictures on the disk.
+        Thread writer = new Thread(new MapillaryExportWriterThread(path, queue,
+                queueImages, amount, this.getProgressMonitor()));
+        writer.start();
+        if (path == null) {
+            try {
+                writer.join();
+            } catch (InterruptedException e) {
+                Main.error(e);
+            }
+            return;
+        }
+        ThreadPoolExecutor ex = new ThreadPoolExecutor(20, 35, 25,
+                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10));
+        for (MapillaryAbstractImage image : images) {
+            if (image instanceof MapillaryImage) {
+                try {
+                    ex.execute(new MapillaryExportDownloadThread(
+                            (MapillaryImage) image, queue, queueImages));
+                } catch (Exception e) {
+                    Main.error(e);
+                }
+            } else if (image instanceof MapillaryImportedImage) {
+                try {
+                    queue.put(((MapillaryImportedImage) image).getImage());
+                    queueImages.put((MapillaryImportedImage) image);
+                } catch (InterruptedException e) {
+                    Main.error(e);
+                }
+            }
+            try {
+                // If the queue is full, waits for it to have more space
+                // available before executing anything else.
+                while (ex.getQueue().remainingCapacity() == 0)
+                    Thread.sleep(100);
+            } catch (Exception e) {
+                Main.error(e);
+            }
+        }
+        try {
+            writer.join();
+        } catch (InterruptedException e) {
+            Main.error(e);
+        }
 
-	@Override
-	protected void finish() {
-		// TODO Auto-generated method stub
-	}
+    }
+
+    @Override
+    protected void finish() {
+        // TODO Auto-generated method stub
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java	(revision 31278)
@@ -34,84 +34,85 @@
 public class MapillaryExportWriterThread implements Runnable {
 
-	private final String path;
-	private final ArrayBlockingQueue<BufferedImage> queue;
-	private final ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
-	private final int amount;
-	private final ProgressMonitor monitor;
+    private final String path;
+    private final ArrayBlockingQueue<BufferedImage> queue;
+    private final ArrayBlockingQueue<MapillaryAbstractImage> queueImages;
+    private final int amount;
+    private final ProgressMonitor monitor;
 
-	public MapillaryExportWriterThread(String path,
-			ArrayBlockingQueue<BufferedImage> queue,
-			ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount,
-			ProgressMonitor monitor) {
-		this.path = path;
-		this.queue = queue;
-		this.queueImages = queueImages;
-		this.amount = amount;
-		this.monitor = monitor;
-	}
+    public MapillaryExportWriterThread(String path,
+            ArrayBlockingQueue<BufferedImage> queue,
+            ArrayBlockingQueue<MapillaryAbstractImage> queueImages, int amount,
+            ProgressMonitor monitor) {
+        this.path = path;
+        this.queue = queue;
+        this.queueImages = queueImages;
+        this.amount = amount;
+        this.monitor = monitor;
+    }
 
-	@Override
-	public void run() {
-		monitor.setCustomText("Downloaded 0/" + amount);
-		File tempFile = null;
-		BufferedImage img;
-		MapillaryAbstractImage mimg = null;
-		String finalPath = "";
-		for (int i = 0; i < amount; i++) {
-			try {
-				img = queue.take();
-				mimg = queueImages.take();
-				if (path == null && mimg instanceof MapillaryImportedImage) {
-					String path = ((MapillaryImportedImage) mimg).getFile()
-							.getPath();
-					finalPath = path.substring(0, path.lastIndexOf('.'));
-				} else if (mimg instanceof MapillaryImage)
-					finalPath = path + "/" + ((MapillaryImage) mimg).getKey();
-				else
-					finalPath = path + "/" + i;
-				// Creates a temporal file that is going to be deleted after
-				// writing the EXIF tags.
-				tempFile = new File(finalPath + ".tmp");
-				ImageIO.write(img, "jpg", tempFile);
+    @Override
+    public void run() {
+        monitor.setCustomText("Downloaded 0/" + amount);
+        File tempFile = null;
+        BufferedImage img;
+        MapillaryAbstractImage mimg = null;
+        String finalPath = "";
+        for (int i = 0; i < amount; i++) {
+            try {
+                img = queue.take();
+                mimg = queueImages.take();
+                if (path == null && mimg instanceof MapillaryImportedImage) {
+                    String path = ((MapillaryImportedImage) mimg).getFile()
+                            .getPath();
+                    finalPath = path.substring(0, path.lastIndexOf('.'));
+                } else if (mimg instanceof MapillaryImage)
+                    finalPath = path + "/" + ((MapillaryImage) mimg).getKey();
+                else
+                    finalPath = path + "/" + i;
+                // Creates a temporal file that is going to be deleted after
+                // writing the EXIF tags.
+                tempFile = new File(finalPath + ".tmp");
+                ImageIO.write(img, "jpg", tempFile);
 
-				// Write EXIF tags
-				TiffOutputSet outputSet = new TiffOutputSet();
-				TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory();
-				exifDirectory
-						.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
-								GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
-				exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION,
-						RationalNumber.valueOf(mimg.getCa()));
-				if (mimg instanceof MapillaryImportedImage) {
-					exifDirectory.add(
-							ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
-							((MapillaryImportedImage) mimg).datetimeOriginal);
-				}
-				else if (mimg instanceof MapillaryImage) 
-					exifDirectory.add(
-							ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
-							((MapillaryImage) mimg).getDate("yyyy/MM/dd hh/mm/ss"));
-				outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg
-						.getLatLon().lat());
-				OutputStream os = new BufferedOutputStream(
-						new FileOutputStream(finalPath + ".jpg"));
-				new ExifRewriter().updateExifMetadataLossless(tempFile, os,
-						outputSet);
-				tempFile.delete();
-				os.close();
-			} catch (InterruptedException e) {
-				Main.error(e);
-			} catch (IOException e) {
-				Main.error(e);
-			} catch (ImageWriteException e) {
-				Main.error(e);
-			} catch (ImageReadException e) {
-				Main.error(e);
-			}
+                // Write EXIF tags
+                TiffOutputSet outputSet = new TiffOutputSet();
+                TiffOutputDirectory exifDirectory = outputSet
+                        .getOrCreateExifDirectory();
+                exifDirectory
+                        .add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
+                                GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
+                exifDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION,
+                        RationalNumber.valueOf(mimg.getCa()));
+                if (mimg instanceof MapillaryImportedImage) {
+                    exifDirectory.add(
+                            ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
+                            ((MapillaryImportedImage) mimg).datetimeOriginal);
+                } else if (mimg instanceof MapillaryImage)
+                    exifDirectory.add(
+                            ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
+                            ((MapillaryImage) mimg)
+                                    .getDate("yyyy/MM/dd hh/mm/ss"));
+                outputSet.setGPSInDegrees(mimg.getLatLon().lon(), mimg
+                        .getLatLon().lat());
+                OutputStream os = new BufferedOutputStream(
+                        new FileOutputStream(finalPath + ".jpg"));
+                new ExifRewriter().updateExifMetadataLossless(tempFile, os,
+                        outputSet);
+                tempFile.delete();
+                os.close();
+            } catch (InterruptedException e) {
+                Main.error(e);
+            } catch (IOException e) {
+                Main.error(e);
+            } catch (ImageWriteException e) {
+                Main.error(e);
+            } catch (ImageReadException e) {
+                Main.error(e);
+            }
 
-			// Increases the progress bar.
-			monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount);
-			monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount);
-		}
-	}
+            // Increases the progress bar.
+            monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount);
+            monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java	(revision 31278)
@@ -25,43 +25,43 @@
  */
 public class MapillaryImageInfoDownloaderThread implements Runnable {
-	private final String url;
-	private final ExecutorService ex;
+    private final String url;
+    private final ExecutorService ex;
 
-	public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url) {
-		this.ex = ex;
-		this.url = url;
-	}
+    public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url) {
+        this.ex = ex;
+        this.url = url;
+    }
 
-	public void run() {
-		try {
-			BufferedReader br = new BufferedReader(new InputStreamReader(
-					new URL(url).openStream()));
-			JsonObject jsonobj = Json.createReader(br).readObject();
-			if (!jsonobj.getBoolean("more"))
-				ex.shutdown();
-			JsonArray jsonarr = jsonobj.getJsonArray("ims");
-			JsonObject data;
-			for (int i = 0; i < jsonarr.size(); i++) {
-				data = jsonarr.getJsonObject(i);
-				String key = data.getString("key");
-				for (MapillaryAbstractImage image : MapillaryData.getInstance()
-						.getImages()) {
-					if (image instanceof MapillaryImage) {
-						if (((MapillaryImage) image).getKey().equals(key)) {
-							((MapillaryImage) image).setUser(data
-									.getString("user"));
-							((MapillaryImage) image).setCapturedAt(data
-									.getJsonNumber("captured_at").longValue());
-							((MapillaryImage) image).setLocation(data
-									.getString("location"));
-						}
-					}
-				}
-			}
-		} catch (MalformedURLException e) {
-			Main.error(e);
-		} catch (IOException e) {
-			Main.error(e);
-		}
-	}
+    public void run() {
+        try {
+            BufferedReader br = new BufferedReader(new InputStreamReader(
+                    new URL(url).openStream()));
+            JsonObject jsonobj = Json.createReader(br).readObject();
+            if (!jsonobj.getBoolean("more"))
+                ex.shutdown();
+            JsonArray jsonarr = jsonobj.getJsonArray("ims");
+            JsonObject data;
+            for (int i = 0; i < jsonarr.size(); i++) {
+                data = jsonarr.getJsonObject(i);
+                String key = data.getString("key");
+                for (MapillaryAbstractImage image : MapillaryData.getInstance()
+                        .getImages()) {
+                    if (image instanceof MapillaryImage) {
+                        if (((MapillaryImage) image).getKey().equals(key)) {
+                            ((MapillaryImage) image).setUser(data
+                                    .getString("user"));
+                            ((MapillaryImage) image).setCapturedAt(data
+                                    .getJsonNumber("captured_at").longValue());
+                            ((MapillaryImage) image).setLocation(data
+                                    .getString("location"));
+                        }
+                    }
+                }
+            }
+        } catch (MalformedURLException e) {
+            Main.error(e);
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java	(revision 31278)
@@ -32,93 +32,92 @@
 public class MapillarySequenceDownloadThread implements Runnable {
 
-	private String url;
-	private ExecutorService ex;
-	private List<Bounds> bounds;
+    private String url;
+    private ExecutorService ex;
+    private List<Bounds> bounds;
 
-	public MapillarySequenceDownloadThread(ExecutorService ex, String url) {
-		this.url = url;
-		this.ex = ex;
-		this.bounds = MapillaryLayer.getInstance().bounds;
-	}
+    public MapillarySequenceDownloadThread(ExecutorService ex, String url) {
+        this.url = url;
+        this.ex = ex;
+        this.bounds = MapillaryLayer.getInstance().bounds;
+    }
 
-	public void run() {
-		try {
-			BufferedReader br;
-			br = new BufferedReader(new InputStreamReader(
-					new URL(url).openStream()));
-			JsonObject jsonall = Json.createReader(br).readObject();
+    public void run() {
+        try {
+            BufferedReader br;
+            br = new BufferedReader(new InputStreamReader(
+                    new URL(url).openStream()));
+            JsonObject jsonall = Json.createReader(br).readObject();
 
-			if (!jsonall.getBoolean("more") && !ex.isShutdown())
-				ex.shutdown();
-			JsonArray jsonseq = jsonall.getJsonArray("ss");
-			// At the moment there is a bug with some sequences at Mapillay API,
-			// so if they are wrong he use this variable to skip them.
-			boolean isSequenceWrong = false;
-			for (int i = 0; i < jsonseq.size(); i++) {
-				JsonObject jsonobj = jsonseq.getJsonObject(i);
-				JsonArray cas = jsonobj.getJsonArray("cas");
-				JsonArray coords = jsonobj.getJsonArray("coords");
-				JsonArray keys = jsonobj.getJsonArray("keys");
-				ArrayList<MapillaryImage> images = new ArrayList<>();
-				for (int j = 0; j < cas.size(); j++) {
-					try {
-						images.add(new MapillaryImage(keys.getString(j),
-								coords.getJsonArray(j).getJsonNumber(1)
-										.doubleValue(), coords.getJsonArray(j)
-										.getJsonNumber(0).doubleValue(), cas
-										.getJsonNumber(j).doubleValue()));
-					} catch (IndexOutOfBoundsException e) {
-						Main.warn("Mapillary bug at " + url);
-						isSequenceWrong = true;
-					}
-				}
-				if (isSequenceWrong)
-					break;
-				MapillarySequence sequence = new MapillarySequence(
-						jsonobj.getString("key"), jsonobj.getJsonNumber(
-								"captured_at").longValue());
-								
-				int first = -1;
-				int last = -1;
-				int pos = 0;
+            if (!jsonall.getBoolean("more") && !ex.isShutdown())
+                ex.shutdown();
+            JsonArray jsonseq = jsonall.getJsonArray("ss");
+            // At the moment there is a bug with some sequences at Mapillay API,
+            // so if they are wrong he use this variable to skip them.
+            boolean isSequenceWrong = false;
+            for (int i = 0; i < jsonseq.size(); i++) {
+                JsonObject jsonobj = jsonseq.getJsonObject(i);
+                JsonArray cas = jsonobj.getJsonArray("cas");
+                JsonArray coords = jsonobj.getJsonArray("coords");
+                JsonArray keys = jsonobj.getJsonArray("keys");
+                ArrayList<MapillaryImage> images = new ArrayList<>();
+                for (int j = 0; j < cas.size(); j++) {
+                    try {
+                        images.add(new MapillaryImage(keys.getString(j),
+                                coords.getJsonArray(j).getJsonNumber(1)
+                                        .doubleValue(), coords.getJsonArray(j)
+                                        .getJsonNumber(0).doubleValue(), cas
+                                        .getJsonNumber(j).doubleValue()));
+                    } catch (IndexOutOfBoundsException e) {
+                        Main.warn("Mapillary bug at " + url);
+                        isSequenceWrong = true;
+                    }
+                }
+                if (isSequenceWrong)
+                    break;
+                MapillarySequence sequence = new MapillarySequence(
+                        jsonobj.getString("key"), jsonobj.getJsonNumber(
+                                "captured_at").longValue());
 
-				// Here it gets only those images which are in the downloaded
-				// area.
-				for (MapillaryAbstractImage img : images) {
-					if (first == -1 && isInside(img))
-						first = pos;
-					else if (first != -1 && last == -1
-							&& !isInside(img))
-						last = pos;
-					else if (last != -1 && isInside(img))
-						last = -1;
-					pos++;
-				}
-				if (last == -1) {
-					last = pos;
-				}
-				if (first == -1)
-					continue;
-				List<MapillaryImage> finalImages = images.subList(first, last);
-				for (MapillaryImage img : finalImages) {
-					MapillaryData.getInstance().getImages().remove(img);
-					img.setSequence(sequence);
-				}
-				MapillaryData.getInstance().addWithoutUpdate(
-						new ArrayList<MapillaryAbstractImage>(finalImages));
-				sequence.add(finalImages);
-			}
-		} catch (IOException e) {
-			Main.error("Error reading the url " + url
-					+ " might be a Mapillary problem.");
-		}
-	}
-	
-	private boolean isInside(MapillaryAbstractImage image) {
-		for (int i = 0; i < bounds.size(); i++) {
-			if (bounds.get(i).contains(image.getLatLon()))
-				return true;
-		}
-		return false;
-	}
+                int first = -1;
+                int last = -1;
+                int pos = 0;
+
+                // Here it gets only those images which are in the downloaded
+                // area.
+                for (MapillaryAbstractImage img : images) {
+                    if (first == -1 && isInside(img))
+                        first = pos;
+                    else if (first != -1 && last == -1 && !isInside(img))
+                        last = pos;
+                    else if (last != -1 && isInside(img))
+                        last = -1;
+                    pos++;
+                }
+                if (last == -1) {
+                    last = pos;
+                }
+                if (first == -1)
+                    continue;
+                List<MapillaryImage> finalImages = images.subList(first, last);
+                for (MapillaryImage img : finalImages) {
+                    MapillaryData.getInstance().getImages().remove(img);
+                    img.setSequence(sequence);
+                }
+                MapillaryData.getInstance().addWithoutUpdate(
+                        new ArrayList<MapillaryAbstractImage>(finalImages));
+                sequence.add(finalImages);
+            }
+        } catch (IOException e) {
+            Main.error("Error reading the url " + url
+                    + " might be a Mapillary problem.");
+        }
+    }
+
+    private boolean isInside(MapillaryAbstractImage image) {
+        for (int i = 0; i < bounds.size(); i++) {
+            if (bounds.get(i).contains(image.getLatLon()))
+                return true;
+        }
+        return false;
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java	(revision 31278)
@@ -19,64 +19,65 @@
 public class MapillarySignDownloaderThread implements Runnable {
 
-	private final String url;
-	private final ExecutorService ex;
+    private final String url;
+    private final ExecutorService ex;
 
-	public MapillarySignDownloaderThread(ExecutorService ex, String url) {
-		this.ex = ex;
-		this.url = url;
-	}
+    public MapillarySignDownloaderThread(ExecutorService ex, String url) {
+        this.ex = ex;
+        this.url = url;
+    }
 
-	@Override
-	public void run() {
-		BufferedReader br;
-		try {
-			br = new BufferedReader(new InputStreamReader(
-					new URL(url).openStream()));
-			JsonObject jsonobj = Json.createReader(br).readObject();
-			if (!jsonobj.getBoolean("more")) {
-				ex.shutdown();
-			}
-			JsonArray jsonarr = jsonobj.getJsonArray("ims");
-			for (int i = 0; i < jsonarr.size(); i++) {
-				JsonArray rects = jsonarr.getJsonObject(i)
-						.getJsonArray("rects");
-				JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
-						"rectversions");
-				String key = jsonarr.getJsonObject(i).getString("key");
-				if (rectversions != null) {
-					for (int j = 0; j < rectversions.size(); j++) {
-						rects = rectversions.getJsonObject(j).getJsonArray("rects");
-						for (int k = 0; k < rects.size(); k++) {
-							JsonObject data = rects.getJsonObject(k);
-							for (MapillaryAbstractImage image : MapillaryData
-									.getInstance().getImages())
-								if (image instanceof MapillaryImage
-										&& ((MapillaryImage) image).getKey()
-												.equals(key))
-									((MapillaryImage) image).addSign(data
-											.getString("type"));
-						}
-					}
-				}
+    @Override
+    public void run() {
+        BufferedReader br;
+        try {
+            br = new BufferedReader(new InputStreamReader(
+                    new URL(url).openStream()));
+            JsonObject jsonobj = Json.createReader(br).readObject();
+            if (!jsonobj.getBoolean("more")) {
+                ex.shutdown();
+            }
+            JsonArray jsonarr = jsonobj.getJsonArray("ims");
+            for (int i = 0; i < jsonarr.size(); i++) {
+                JsonArray rects = jsonarr.getJsonObject(i)
+                        .getJsonArray("rects");
+                JsonArray rectversions = jsonarr.getJsonObject(i).getJsonArray(
+                        "rectversions");
+                String key = jsonarr.getJsonObject(i).getString("key");
+                if (rectversions != null) {
+                    for (int j = 0; j < rectversions.size(); j++) {
+                        rects = rectversions.getJsonObject(j).getJsonArray(
+                                "rects");
+                        for (int k = 0; k < rects.size(); k++) {
+                            JsonObject data = rects.getJsonObject(k);
+                            for (MapillaryAbstractImage image : MapillaryData
+                                    .getInstance().getImages())
+                                if (image instanceof MapillaryImage
+                                        && ((MapillaryImage) image).getKey()
+                                                .equals(key))
+                                    ((MapillaryImage) image).addSign(data
+                                            .getString("type"));
+                        }
+                    }
+                }
 
-				// Just one sign on the picture
-				else if (rects != null) {
-					for (int j = 0; j < rects.size(); j++) {
-						JsonObject data = rects.getJsonObject(j);
-						for (MapillaryAbstractImage image : MapillaryData
-								.getInstance().getImages())
-							if (image instanceof MapillaryImage
-									&& ((MapillaryImage) image).getKey()
-											.equals(key))
-								((MapillaryImage) image).addSign(data
-										.getString("type"));
-					}
-				}
-			}
-		} catch (MalformedURLException e) {
-			Main.error(e);
-		} catch (IOException e) {
-			Main.error(e);
-		}
-	}
+                // Just one sign on the picture
+                else if (rects != null) {
+                    for (int j = 0; j < rects.size(); j++) {
+                        JsonObject data = rects.getJsonObject(j);
+                        for (MapillaryAbstractImage image : MapillaryData
+                                .getInstance().getImages())
+                            if (image instanceof MapillaryImage
+                                    && ((MapillaryImage) image).getKey()
+                                            .equals(key))
+                                ((MapillaryImage) image).addSign(data
+                                        .getString("type"));
+                    }
+                }
+            }
+        } catch (MalformedURLException e) {
+            Main.error(e);
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java	(revision 31278)
@@ -21,75 +21,75 @@
 public class MapillarySquareDownloadManagerThread implements Runnable {
 
-	private final String urlImages;
-	private final String urlSequences;
-	private final String urlSigns;
+    private final String urlImages;
+    private final String urlSequences;
+    private final String urlSigns;
 
-	public MapillarySquareDownloadManagerThread(String urlImages,
-			String urlSequences, String urlSigns) {
-		this.urlImages = urlImages;
-		this.urlSequences = urlSequences;
-		this.urlSigns = urlSigns;
-	}
+    public MapillarySquareDownloadManagerThread(String urlImages,
+            String urlSequences, String urlSigns) {
+        this.urlImages = urlImages;
+        this.urlSequences = urlSequences;
+        this.urlSigns = urlSigns;
+    }
 
-	public void run() {
-		Main.map.statusLine.setHelpText("Downloading images from Mapillary");
-		try {
-			downloadSequences();
-			Main.map.statusLine.setHelpText("Downloading image's information");
-			completeImages();
-			Main.map.statusLine.setHelpText("Downloading signs");
-			downloadSigns();
-		} catch (InterruptedException e) {
-			Main.error(e);
-		}
-		if (MapillaryData.getInstance().getImages().size() > 0)
-			Main.map.statusLine.setHelpText(tr("Total images: ")
-					+ MapillaryData.getInstance().getImages().size());
-		else
-			Main.map.statusLine.setHelpText(tr("No images found"));
-		MapillaryData.getInstance().dataUpdated();
-	}
+    public void run() {
+        Main.map.statusLine.setHelpText("Downloading images from Mapillary");
+        try {
+            downloadSequences();
+            Main.map.statusLine.setHelpText("Downloading image's information");
+            completeImages();
+            Main.map.statusLine.setHelpText("Downloading signs");
+            downloadSigns();
+        } catch (InterruptedException e) {
+            Main.error(e);
+        }
+        if (MapillaryData.getInstance().getImages().size() > 0)
+            Main.map.statusLine.setHelpText(tr("Total images: ")
+                    + MapillaryData.getInstance().getImages().size());
+        else
+            Main.map.statusLine.setHelpText(tr("No images found"));
+        MapillaryData.getInstance().dataUpdated();
+    }
 
-	private void downloadSequences() throws InterruptedException {
-		ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
-				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
-		int page = 0;
-		while (!ex.isShutdown()) {
-			ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
-					+ "&page=" + page + "&limit=1"));
-			while (ex.getQueue().remainingCapacity() == 0)
-				Thread.sleep(100);
-			page++;
-		}
-		ex.awaitTermination(15, TimeUnit.SECONDS);
-		MapillaryData.getInstance().dataUpdated();
-	}
+    private void downloadSequences() throws InterruptedException {
+        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
+                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
+        int page = 0;
+        while (!ex.isShutdown()) {
+            ex.execute(new MapillarySequenceDownloadThread(ex, urlSequences
+                    + "&page=" + page + "&limit=1"));
+            while (ex.getQueue().remainingCapacity() == 0)
+                Thread.sleep(100);
+            page++;
+        }
+        ex.awaitTermination(15, TimeUnit.SECONDS);
+        MapillaryData.getInstance().dataUpdated();
+    }
 
-	private void completeImages() throws InterruptedException {
-		ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
-				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
-		int page = 0;
-		while (!ex.isShutdown()) {
-			ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
-					+ "&page=" + page + "&limit=20"));
-			while (ex.getQueue().remainingCapacity() == 0)
-				Thread.sleep(100);
-			page++;
-		}
-		ex.awaitTermination(15, TimeUnit.SECONDS);
-	}
+    private void completeImages() throws InterruptedException {
+        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
+                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
+        int page = 0;
+        while (!ex.isShutdown()) {
+            ex.execute(new MapillaryImageInfoDownloaderThread(ex, urlImages
+                    + "&page=" + page + "&limit=20"));
+            while (ex.getQueue().remainingCapacity() == 0)
+                Thread.sleep(100);
+            page++;
+        }
+        ex.awaitTermination(15, TimeUnit.SECONDS);
+    }
 
-	private void downloadSigns() throws InterruptedException {
-		ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
-				TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
-		int page = 0;
-		while (!ex.isShutdown()) {
-			ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
-					+ "&page=" + page + "&limit=20"));
-			while (ex.getQueue().remainingCapacity() == 0)
-				Thread.sleep(100);
-			page++;
-		}
-		ex.awaitTermination(15, TimeUnit.SECONDS);
-	}
+    private void downloadSigns() throws InterruptedException {
+        ThreadPoolExecutor ex = new ThreadPoolExecutor(3, 5, 25,
+                TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
+        int page = 0;
+        while (!ex.isShutdown()) {
+            ex.execute(new MapillarySignDownloaderThread(ex, urlSigns
+                    + "&page=" + page + "&limit=20"));
+            while (ex.getQueue().remainingCapacity() == 0)
+                Thread.sleep(100);
+            page++;
+        }
+        ex.awaitTermination(15, TimeUnit.SECONDS);
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java	(revision 31278)
@@ -21,106 +21,106 @@
 public class HyperlinkLabel extends JLabel implements ActionListener {
 
-	private String text;
-	private URL url;
+    private String text;
+    private URL url;
 
-	/**
-	 * Creates a new HyperlinlLabel.
-	 */
-	public HyperlinkLabel() {
-		super(tr("View in website"), SwingUtilities.RIGHT);
-		this.addActionListener(this);
-		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+    /**
+     * Creates a new HyperlinlLabel.
+     */
+    public HyperlinkLabel() {
+        super(tr("View in website"), SwingUtilities.RIGHT);
+        this.addActionListener(this);
+        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
 
-		enableEvents(MouseEvent.MOUSE_EVENT_MASK);
-	}
+        enableEvents(MouseEvent.MOUSE_EVENT_MASK);
+    }
 
-	/**
-	 * Sets the text of the label.
-	 */
-	public void setText(String text) {
-		super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
-		this.text = text;
-	}
+    /**
+     * Sets the text of the label.
+     */
+    public void setText(String text) {
+        super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
+        this.text = text;
+    }
 
-	/**
-	 * Sets a new URL, just pass the key of the image or null if there is none.
-	 * 
-	 * @param key
-	 */
-	public void setURL(String key) {
-		if (key == null) {
-			this.url = null;
-			return;
-		}
-		try {
-			this.url = new URL("http://www.mapillary.com/map/im/" + key);
-		} catch (MalformedURLException e) {
-			Main.error(e);
-		}
-	}
+    /**
+     * Sets a new URL, just pass the key of the image or null if there is none.
+     * 
+     * @param key
+     */
+    public void setURL(String key) {
+        if (key == null) {
+            this.url = null;
+            return;
+        }
+        try {
+            this.url = new URL("http://www.mapillary.com/map/im/" + key);
+        } catch (MalformedURLException e) {
+            Main.error(e);
+        }
+    }
 
-	/**
-	 * Returns the text set by the user.
-	 */
-	public String getNormalText() {
-		return text;
-	}
+    /**
+     * Returns the text set by the user.
+     */
+    public String getNormalText() {
+        return text;
+    }
 
-	/**
-	 * Processes mouse events and responds to clicks.
-	 */
-	protected void processMouseEvent(MouseEvent evt) {
-		super.processMouseEvent(evt);
-		if (evt.getID() == MouseEvent.MOUSE_CLICKED)
-			fireActionPerformed(new ActionEvent(this,
-					ActionEvent.ACTION_PERFORMED, getNormalText()));
-	}
+    /**
+     * Processes mouse events and responds to clicks.
+     */
+    protected void processMouseEvent(MouseEvent evt) {
+        super.processMouseEvent(evt);
+        if (evt.getID() == MouseEvent.MOUSE_CLICKED)
+            fireActionPerformed(new ActionEvent(this,
+                    ActionEvent.ACTION_PERFORMED, getNormalText()));
+    }
 
-	/**
-	 * Adds an ActionListener to the list of listeners receiving notifications
-	 * when the label is clicked.
-	 */
-	public void addActionListener(ActionListener listener) {
-		listenerList.add(ActionListener.class, listener);
-	}
+    /**
+     * Adds an ActionListener to the list of listeners receiving notifications
+     * when the label is clicked.
+     */
+    public void addActionListener(ActionListener listener) {
+        listenerList.add(ActionListener.class, listener);
+    }
 
-	/**
-	 * Removes the given ActionListener from the list of listeners receiving
-	 * notifications when the label is clicked.
-	 */
-	public void removeActionListener(ActionListener listener) {
-		listenerList.remove(ActionListener.class, listener);
-	}
+    /**
+     * Removes the given ActionListener from the list of listeners receiving
+     * notifications when the label is clicked.
+     */
+    public void removeActionListener(ActionListener listener) {
+        listenerList.remove(ActionListener.class, listener);
+    }
 
-	/**
-	 * Fires an ActionEvent to all interested listeners.
-	 */
-	protected void fireActionPerformed(ActionEvent evt) {
-		Object[] listeners = listenerList.getListenerList();
-		for (int i = 0; i < listeners.length; i += 2) {
-			if (listeners[i] == ActionListener.class) {
-				ActionListener listener = (ActionListener) listeners[i + 1];
-				listener.actionPerformed(evt);
-			}
-		}
-	}
+    /**
+     * Fires an ActionEvent to all interested listeners.
+     */
+    protected void fireActionPerformed(ActionEvent evt) {
+        Object[] listeners = listenerList.getListenerList();
+        for (int i = 0; i < listeners.length; i += 2) {
+            if (listeners[i] == ActionListener.class) {
+                ActionListener listener = (ActionListener) listeners[i + 1];
+                listener.actionPerformed(evt);
+            }
+        }
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent e) {
-		if (this.url == null)
-			return;
-		Desktop desktop = Desktop.getDesktop();
-		try {
-			desktop.browse(url.toURI());
-		} catch (IOException | URISyntaxException ex) {
-			ex.printStackTrace();
-		} catch (UnsupportedOperationException ex) {
-			Runtime runtime = Runtime.getRuntime();
-			try {
-				runtime.exec("xdg-open " + url);
-			} catch (IOException exc) {
-				exc.printStackTrace();
-			}
-		}
-	}
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        if (this.url == null)
+            return;
+        Desktop desktop = Desktop.getDesktop();
+        try {
+            desktop.browse(url.toURI());
+        } catch (IOException | URISyntaxException ex) {
+            ex.printStackTrace();
+        } catch (UnsupportedOperationException ex) {
+            Runtime runtime = Runtime.getRuntime();
+            try {
+                runtime.exec("xdg-open " + url);
+            } catch (IOException exc) {
+                exc.printStackTrace();
+            }
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryExportDialog.java	(revision 31278)
@@ -27,81 +27,81 @@
 public class MapillaryExportDialog extends JPanel implements ActionListener {
 
-	protected JOptionPane optionPane;
-	/** Button to export all downloaded images. */
-	public JRadioButton all;
-	/**
-	 * Button to export all images in the sequence of the selected
-	 * MapillaryImage.
-	 */
-	public JRadioButton sequence;
-	/**
-	 * Button to export all images belonging to the selected MapillaryImage
-	 * objects.
-	 */
-	public JRadioButton selected;
-	public JRadioButton rewrite;
-	public ButtonGroup group;
-	protected JButton choose;
-	protected JLabel path;
-	public JFileChooser chooser;
-	protected String exportDirectory;
+    protected JOptionPane optionPane;
+    /** Button to export all downloaded images. */
+    public JRadioButton all;
+    /**
+     * Button to export all images in the sequence of the selected
+     * MapillaryImage.
+     */
+    public JRadioButton sequence;
+    /**
+     * Button to export all images belonging to the selected MapillaryImage
+     * objects.
+     */
+    public JRadioButton selected;
+    public JRadioButton rewrite;
+    public ButtonGroup group;
+    protected JButton choose;
+    protected JLabel path;
+    public JFileChooser chooser;
+    protected String exportDirectory;
 
-	public MapillaryExportDialog() {
-		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+    public MapillaryExportDialog() {
+        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
 
-		group = new ButtonGroup();
-		all = new JRadioButton(tr("Export all images"));
-		sequence = new JRadioButton(tr("Export selected sequence"));
-		selected = new JRadioButton(tr("Export selected images"));
-		rewrite = new JRadioButton(tr("Rewrite imported images"));
-		group.add(all);
-		group.add(sequence);
-		group.add(selected);
-		group.add(rewrite);
-		// Some options are disabled depending on the circumstances
-		if (MapillaryData.getInstance().getSelectedImage() == null
-				|| !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData
-						.getInstance().getSelectedImage()).getSequence() != null)) {
-			sequence.setEnabled(false);
-		}
-		if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) {
-			selected.setEnabled(false);
-		}
-		path = new JLabel(tr("Select a folder"));
-		choose = new JButton(tr("Explore"));
-		choose.addActionListener(this);
+        group = new ButtonGroup();
+        all = new JRadioButton(tr("Export all images"));
+        sequence = new JRadioButton(tr("Export selected sequence"));
+        selected = new JRadioButton(tr("Export selected images"));
+        rewrite = new JRadioButton(tr("Rewrite imported images"));
+        group.add(all);
+        group.add(sequence);
+        group.add(selected);
+        group.add(rewrite);
+        // Some options are disabled depending on the circumstances
+        if (MapillaryData.getInstance().getSelectedImage() == null
+                || !(MapillaryData.getInstance().getSelectedImage() instanceof MapillaryImage && ((MapillaryImage) MapillaryData
+                        .getInstance().getSelectedImage()).getSequence() != null)) {
+            sequence.setEnabled(false);
+        }
+        if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) {
+            selected.setEnabled(false);
+        }
+        path = new JLabel(tr("Select a folder"));
+        choose = new JButton(tr("Explore"));
+        choose.addActionListener(this);
 
-		// All options belong to the same jpanel so the are in line.
-		JPanel jpanel = new JPanel();
-		jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
-		jpanel.add(all);
-		jpanel.add(sequence);
-		jpanel.add(selected);
-		jpanel.add(rewrite);
-		jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
-		path.setAlignmentX(Component.CENTER_ALIGNMENT);
-		choose.setAlignmentX(Component.CENTER_ALIGNMENT);
+        // All options belong to the same jpanel so the are in line.
+        JPanel jpanel = new JPanel();
+        jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
+        jpanel.add(all);
+        jpanel.add(sequence);
+        jpanel.add(selected);
+        jpanel.add(rewrite);
+        jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+        path.setAlignmentX(Component.CENTER_ALIGNMENT);
+        choose.setAlignmentX(Component.CENTER_ALIGNMENT);
 
-		add(jpanel);
-		add(path);
-		add(choose);
-	}
+        add(jpanel);
+        add(path);
+        add(choose);
+    }
 
-	/**
-	 * Creates the folder choser GUI.
-	 */
-	@Override
-	public void actionPerformed(ActionEvent e) {
-		chooser = new JFileChooser();
-		chooser.setCurrentDirectory(new java.io.File(System
-				.getProperty("user.home")));
-		chooser.setDialogTitle(tr("Select a directory"));
-		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-		chooser.setAcceptAllFileFilterUsed(false);
+    /**
+     * Creates the folder choser GUI.
+     */
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        chooser = new JFileChooser();
+        chooser.setCurrentDirectory(new java.io.File(System
+                .getProperty("user.home")));
+        chooser.setDialogTitle(tr("Select a directory"));
+        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+        chooser.setAcceptAllFileFilterUsed(false);
 
-		if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
-			path.setText(chooser.getSelectedFile().toString());
-			this.updateUI();
-		}
-	}
+        if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+            path.setText(chooser.getSelectedFile().toString());
+            this.updateUI();
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryHistoryDialog.java	(revision 31278)
@@ -31,142 +31,142 @@
 
 public class MapillaryHistoryDialog extends ToggleDialog implements
-		MapillaryRecordListener {
+        MapillaryRecordListener {
 
-	public static MapillaryHistoryDialog INSTANCE;
+    public static MapillaryHistoryDialog INSTANCE;
 
-	private final DefaultTreeModel undoTreeModel = new DefaultTreeModel(
-			new DefaultMutableTreeNode());
-	private final DefaultTreeModel redoTreeModel = new DefaultTreeModel(
-			new DefaultMutableTreeNode());
-	private final JTree undoTree = new JTree(undoTreeModel);
-	private final JTree redoTree = new JTree(redoTreeModel);
+    private final DefaultTreeModel undoTreeModel = new DefaultTreeModel(
+            new DefaultMutableTreeNode());
+    private final DefaultTreeModel redoTreeModel = new DefaultTreeModel(
+            new DefaultMutableTreeNode());
+    private final JTree undoTree = new JTree(undoTreeModel);
+    private final JTree redoTree = new JTree(redoTreeModel);
 
-	private JSeparator separator = new JSeparator();
-	private Component spacer = Box.createRigidArea(new Dimension(0, 3));
+    private JSeparator separator = new JSeparator();
+    private Component spacer = Box.createRigidArea(new Dimension(0, 3));
 
-	private SideButton undoButton;
-	private SideButton redoButton;
+    private SideButton undoButton;
+    private SideButton redoButton;
 
-	public MapillaryHistoryDialog() {
-		super(tr("Mapillary history"), "mapillaryhistory.png",
-				tr("Open Mapillary history dialog"),  Shortcut.registerShortcut(
-						tr("Mapillary history"),
-						tr("Open Mapillary history dialog"), KeyEvent.VK_M,
-						Shortcut.NONE), 200);
+    public MapillaryHistoryDialog() {
+        super(tr("Mapillary history"), "mapillaryhistory.png",
+                tr("Open Mapillary history dialog"), Shortcut.registerShortcut(
+                        tr("Mapillary history"),
+                        tr("Open Mapillary history dialog"), KeyEvent.VK_M,
+                        Shortcut.NONE), 200);
 
-		MapillaryRecord.getInstance().addListener(this);
+        MapillaryRecord.getInstance().addListener(this);
 
-		undoTree.expandRow(0);
-		undoTree.setShowsRootHandles(true);
-		undoTree.setRootVisible(false);
-		undoTree.setCellRenderer(new MapillaryCellRenderer());
-		redoTree.expandRow(0);
-		redoTree.setCellRenderer(new MapillaryCellRenderer());
-		redoTree.setShowsRootHandles(true);
-		redoTree.setRootVisible(false);
+        undoTree.expandRow(0);
+        undoTree.setShowsRootHandles(true);
+        undoTree.setRootVisible(false);
+        undoTree.setCellRenderer(new MapillaryCellRenderer());
+        redoTree.expandRow(0);
+        redoTree.setCellRenderer(new MapillaryCellRenderer());
+        redoTree.setShowsRootHandles(true);
+        redoTree.setRootVisible(false);
 
-		JPanel treesPanel = new JPanel(new GridBagLayout());
-		treesPanel.add(spacer, GBC.eol());
-		spacer.setVisible(false);
-		treesPanel.add(undoTree, GBC.eol().fill(GBC.HORIZONTAL));
-		separator.setVisible(false);
-		treesPanel.add(separator, GBC.eol().fill(GBC.HORIZONTAL));
-		treesPanel.add(redoTree, GBC.eol().fill(GBC.HORIZONTAL));
-		treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), GBC.std()
-				.weight(0, 1));
-		treesPanel.setBackground(redoTree.getBackground());
+        JPanel treesPanel = new JPanel(new GridBagLayout());
+        treesPanel.add(spacer, GBC.eol());
+        spacer.setVisible(false);
+        treesPanel.add(undoTree, GBC.eol().fill(GBC.HORIZONTAL));
+        separator.setVisible(false);
+        treesPanel.add(separator, GBC.eol().fill(GBC.HORIZONTAL));
+        treesPanel.add(redoTree, GBC.eol().fill(GBC.HORIZONTAL));
+        treesPanel.add(Box.createRigidArea(new Dimension(0, 0)), GBC.std()
+                .weight(0, 1));
+        treesPanel.setBackground(redoTree.getBackground());
 
-		undoButton = new SideButton(new UndoAction());
-		redoButton = new SideButton(new RedoAction());
+        undoButton = new SideButton(new UndoAction());
+        redoButton = new SideButton(new RedoAction());
 
-		createLayout(treesPanel, true,
-				Arrays.asList(new SideButton[] { undoButton, redoButton }));
-	}
+        createLayout(treesPanel, true,
+                Arrays.asList(new SideButton[] { undoButton, redoButton }));
+    }
 
-	public static MapillaryHistoryDialog getInstance() {
-		if (INSTANCE == null)
-			INSTANCE = new MapillaryHistoryDialog();
-		return INSTANCE;
-	}
+    public static MapillaryHistoryDialog getInstance() {
+        if (INSTANCE == null)
+            INSTANCE = new MapillaryHistoryDialog();
+        return INSTANCE;
+    }
 
-	private void buildTree() {
-		redoButton.setEnabled(true);
-		undoButton.setEnabled(true);
-		ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList;
-		int position = MapillaryRecord.getInstance().position;
-		ArrayList<MapillaryCommand> undoCommands = new ArrayList<>();
-		if (position >= 0)
-			undoCommands = new ArrayList<>(commands.subList(0, position + 1));
-		else
-			undoButton.setEnabled(false);
-		ArrayList<MapillaryCommand> redoCommands = new ArrayList<>();
-		if (commands.size() > 0 && position + 1 < commands.size())
-			redoCommands = new ArrayList<>(commands.subList(position + 1,
-					commands.size()));
-		else
-			redoButton.setEnabled(false);
+    private void buildTree() {
+        redoButton.setEnabled(true);
+        undoButton.setEnabled(true);
+        ArrayList<MapillaryCommand> commands = MapillaryRecord.getInstance().commandList;
+        int position = MapillaryRecord.getInstance().position;
+        ArrayList<MapillaryCommand> undoCommands = new ArrayList<>();
+        if (position >= 0)
+            undoCommands = new ArrayList<>(commands.subList(0, position + 1));
+        else
+            undoButton.setEnabled(false);
+        ArrayList<MapillaryCommand> redoCommands = new ArrayList<>();
+        if (commands.size() > 0 && position + 1 < commands.size())
+            redoCommands = new ArrayList<>(commands.subList(position + 1,
+                    commands.size()));
+        else
+            redoButton.setEnabled(false);
 
-		DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode();
-		DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode();
+        DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode();
+        DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode();
 
-		for (MapillaryCommand command : undoCommands) {
-			if (command != null)
-				undoRoot.add(new DefaultMutableTreeNode(command.toString()));
-		}
-		for (MapillaryCommand command : redoCommands) {
-			if (command != null)
-				redoRoot.add(new DefaultMutableTreeNode(command.toString()));
-		}
+        for (MapillaryCommand command : undoCommands) {
+            if (command != null)
+                undoRoot.add(new DefaultMutableTreeNode(command.toString()));
+        }
+        for (MapillaryCommand command : redoCommands) {
+            if (command != null)
+                redoRoot.add(new DefaultMutableTreeNode(command.toString()));
+        }
 
-		separator
-				.setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty());
-		spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty());
+        separator
+                .setVisible(!undoCommands.isEmpty() || !redoCommands.isEmpty());
+        spacer.setVisible(undoCommands.isEmpty() && !redoCommands.isEmpty());
 
-		undoTreeModel.setRoot(undoRoot);
-		redoTreeModel.setRoot(redoRoot);
-	}
+        undoTreeModel.setRoot(undoRoot);
+        redoTreeModel.setRoot(redoRoot);
+    }
 
-	@Override
-	public void recordChanged() {
-		buildTree();
-	}
+    @Override
+    public void recordChanged() {
+        buildTree();
+    }
 
-	private class UndoAction extends AbstractAction {
+    private class UndoAction extends AbstractAction {
 
-		public UndoAction() {
-			putValue(NAME, tr("Undo"));
-			putValue(SMALL_ICON, ImageProvider.get("undo"));
-		}
+        public UndoAction() {
+            putValue(NAME, tr("Undo"));
+            putValue(SMALL_ICON, ImageProvider.get("undo"));
+        }
 
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			MapillaryRecord.getInstance().undo();
-		}
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            MapillaryRecord.getInstance().undo();
+        }
 
-	}
+    }
 
-	private class RedoAction extends AbstractAction {
-		public RedoAction() {
-			putValue(NAME, tr("Redo"));
-			putValue(SMALL_ICON, ImageProvider.get("redo"));
-		}
+    private class RedoAction extends AbstractAction {
+        public RedoAction() {
+            putValue(NAME, tr("Redo"));
+            putValue(SMALL_ICON, ImageProvider.get("redo"));
+        }
 
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			MapillaryRecord.getInstance().redo();
-		}
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            MapillaryRecord.getInstance().redo();
+        }
 
-	}
+    }
 
-	private static class MapillaryCellRenderer extends DefaultTreeCellRenderer {
-		@Override
-		public Component getTreeCellRendererComponent(JTree tree, Object value,
-				boolean sel, boolean expanded, boolean leaf, int row,
-				boolean hasFocus) {
-			super.getTreeCellRendererComponent(tree, value, sel, expanded,
-					leaf, row, hasFocus);
-			setIcon(ImageProvider.get("data/node.png"));
-			return this;
-		}
-	}
+    private static class MapillaryCellRenderer extends DefaultTreeCellRenderer {
+        @Override
+        public Component getTreeCellRendererComponent(JTree tree, Object value,
+                boolean sel, boolean expanded, boolean leaf, int row,
+                boolean hasFocus) {
+            super.getTreeCellRendererComponent(tree, value, sel, expanded,
+                    leaf, row, hasFocus);
+            setIcon(ImageProvider.get("data/node.png"));
+            return this;
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryImageDisplay.java	(revision 31278)
@@ -33,495 +33,498 @@
 public class MapillaryImageDisplay extends JComponent {
 
-	private static final int DRAG_BUTTON = Main.pref.getInteger("mapillary.picture-drag-button", 3);
-	private static final int OPTION_BUTTON = Main.pref.getInteger("mapillary.picture-option-button", 2);
-	private static final int ZOOM_BUTTON = Main.pref.getInteger("mapillary.picture-zoom-button", 1);
-
-	/** The image currently displayed */
-	private transient BufferedImage image = null;
-
-	/**
-	 * The rectangle (in image coordinates) of the image that is visible. This
-	 * rectangle is calculated each time the zoom is modified
-	 */
-	private Rectangle visibleRect = null;
-
-	/**
-	 * When a selection is done, the rectangle of the selection (in image
-	 * coordinates)
-	 */
-	private Rectangle selectedRect = null;
-
-	public HyperlinkLabel hyperlink;
-
-	private class ImgDisplayMouseListener implements MouseListener,
-			MouseWheelListener, MouseMotionListener {
-		private boolean mouseIsDragging = false;
-		private long lastTimeForMousePoint = 0L;
-		private Point mousePointInImg = null;
-
-		/**
-		 * Zoom in and out, trying to preserve the point of the image that was
-		 * under the mouse cursor at the same place
-		 */
-		@Override
-		public void mouseWheelMoved(MouseWheelEvent e) {
-			Image image;
-			Rectangle visibleRect;
-			synchronized (MapillaryImageDisplay.this) {
-				image = MapillaryImageDisplay.this.image;
-				visibleRect = MapillaryImageDisplay.this.visibleRect;
-			}
-			mouseIsDragging = false;
-			selectedRect = null;
-			if (image == null)
-				return;
-			// Calculate the mouse cursor position in image coordinates, so that
-			// we can center the zoom
-			// on that mouse position.
-			// To avoid issues when the user tries to zoom in on the image
-			// borders, this point is not calculated
-			// again if there was less than 1.5seconds since the last event.
-			if (e.getWhen() - lastTimeForMousePoint > 1500
-					|| mousePointInImg == null) {
-				lastTimeForMousePoint = e.getWhen();
-				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-			}
-			// Applicate the zoom to the visible rectangle in image coordinates
-			if (e.getWheelRotation() > 0) {
-				visibleRect.width = visibleRect.width * 3 / 2;
-				visibleRect.height = visibleRect.height * 3 / 2;
-			} else {
-				visibleRect.width = visibleRect.width * 2 / 3;
-				visibleRect.height = visibleRect.height * 2 / 3;
-			}
-			// Check that the zoom doesn't exceed 2:1
-			if (visibleRect.width < getSize().width / 2) {
-				visibleRect.width = getSize().width / 2;
-			}
-			if (visibleRect.height < getSize().height / 2) {
-				visibleRect.height = getSize().height / 2;
-			}
-			// Set the same ratio for the visible rectangle and the display area
-			int hFact = visibleRect.height * getSize().width;
-			int wFact = visibleRect.width * getSize().height;
-			if (hFact > wFact) {
-				visibleRect.width = hFact / getSize().height;
-			} else {
-				visibleRect.height = wFact / getSize().width;
-			}
-			// The size of the visible rectangle is limited by the image size.
-			checkVisibleRectSize(image, visibleRect);
-			// Set the position of the visible rectangle, so that the mouse
-			// cursor doesn't move on the image.
-			Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-			visibleRect.x = mousePointInImg.x
-					+ ((drawRect.x - e.getX()) * visibleRect.width)
-					/ drawRect.width;
-			visibleRect.y = mousePointInImg.y
-					+ ((drawRect.y - e.getY()) * visibleRect.height)
-					/ drawRect.height;
-			// The position is also limited by the image size
-			checkVisibleRectPos(image, visibleRect);
-			synchronized (MapillaryImageDisplay.this) {
-				MapillaryImageDisplay.this.visibleRect = visibleRect;
-			}
-			MapillaryImageDisplay.this.repaint();
-		}
-
-		/** Center the display on the point that has been clicked */
-		@Override
-		public void mouseClicked(MouseEvent e) {
-			// Move the center to the clicked point.
-			Image image;
-			Rectangle visibleRect;
-			synchronized (MapillaryImageDisplay.this) {
-				image = MapillaryImageDisplay.this.image;
-				visibleRect = MapillaryImageDisplay.this.visibleRect;
-			}
-			if (image == null)
-				return;
-			if (e.getButton() == OPTION_BUTTON) {
-				if (!MapillaryImageDisplay.this.visibleRect
-						.equals(new Rectangle(0, 0, image.getWidth(null), image
-								.getHeight(null))))
-					// Zooms to 1:1
-					MapillaryImageDisplay.this.visibleRect = new Rectangle(0,
-							0, image.getWidth(null), image.getHeight(null));
-				else
-					// Zooms to best fit.
-					MapillaryImageDisplay.this.visibleRect = new Rectangle(
-							0,
-							(image.getHeight(null) - (image.getWidth(null) * getHeight())
-									/ getWidth()) / 2, image.getWidth(null),
-							(image.getWidth(null) * getHeight()) / getWidth());
-				MapillaryImageDisplay.this.repaint();
-				return;
-			} else if (e.getButton() != DRAG_BUTTON)
-				return;
-			// Calculate the translation to set the clicked point the center of
-			// the view.
-			Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
-			Point center = getCenterImgCoord(visibleRect);
-			visibleRect.x += click.x - center.x;
-			visibleRect.y += click.y - center.y;
-			checkVisibleRectPos(image, visibleRect);
-			synchronized (MapillaryImageDisplay.this) {
-				MapillaryImageDisplay.this.visibleRect = visibleRect;
-			}
-			MapillaryImageDisplay.this.repaint();
-		}
-
-		/**
-		 * Initialize the dragging, either with button 1 (simple dragging) or
-		 * button 3 (selection of a picture part)
-		 */
-		@Override
-		public void mousePressed(MouseEvent e) {
-			if (image == null) {
-				mouseIsDragging = false;
-				selectedRect = null;
-				return;
-			}
-			Image image;
-			Rectangle visibleRect;
-			synchronized (MapillaryImageDisplay.this) {
-				image = MapillaryImageDisplay.this.image;
-				visibleRect = MapillaryImageDisplay.this.visibleRect;
-			}
-			if (image == null)
-				return;
-			if (e.getButton() == DRAG_BUTTON) {
-				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-				mouseIsDragging = true;
-				selectedRect = null;
-			} else if (e.getButton() == ZOOM_BUTTON) {
-				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
-				checkPointInVisibleRect(mousePointInImg, visibleRect);
-				mouseIsDragging = false;
-				selectedRect = new Rectangle(mousePointInImg.x,
-						mousePointInImg.y, 0, 0);
-				MapillaryImageDisplay.this.repaint();
-			} else {
-				mouseIsDragging = false;
-				selectedRect = null;
-			}
-		}
-
-		@Override
-		public void mouseDragged(MouseEvent e) {
-			if (!mouseIsDragging && selectedRect == null)
-				return;
-			Image image;
-			Rectangle visibleRect;
-			synchronized (MapillaryImageDisplay.this) {
-				image = MapillaryImageDisplay.this.image;
-				visibleRect = MapillaryImageDisplay.this.visibleRect;
-			}
-			if (image == null) {
-				mouseIsDragging = false;
-				selectedRect = null;
-				return;
-			}
-			if (mouseIsDragging) {
-				Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
-				visibleRect.x += mousePointInImg.x - p.x;
-				visibleRect.y += mousePointInImg.y - p.y;
-				checkVisibleRectPos(image, visibleRect);
-				synchronized (MapillaryImageDisplay.this) {
-					MapillaryImageDisplay.this.visibleRect = visibleRect;
-				}
-				MapillaryImageDisplay.this.repaint();
-			} else if (selectedRect != null) {
-				Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
-				checkPointInVisibleRect(p, visibleRect);
-				Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
-						: mousePointInImg.x, p.y < mousePointInImg.y ? p.y
-						: mousePointInImg.y,
-						p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x
-								- mousePointInImg.x,
-						p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
-								- mousePointInImg.y);
-				checkVisibleRectSize(image, rect);
-				checkVisibleRectPos(image, rect);
-				MapillaryImageDisplay.this.selectedRect = rect;
-				MapillaryImageDisplay.this.repaint();
-			}
-		}
-
-		@Override
-		public void mouseReleased(MouseEvent e) {
-			if (!mouseIsDragging && selectedRect == null)
-				return;
-			Image image;
-			synchronized (MapillaryImageDisplay.this) {
-				image = MapillaryImageDisplay.this.image;
-			}
-			if (image == null) {
-				mouseIsDragging = false;
-				selectedRect = null;
-				return;
-			}
-			if (mouseIsDragging) {
-				mouseIsDragging = false;
-			} else if (selectedRect != null) {
-				int oldWidth = selectedRect.width;
-				int oldHeight = selectedRect.height;
-				// Check that the zoom doesn't exceed 2:1
-				if (selectedRect.width < getSize().width / 2) {
-					selectedRect.width = getSize().width / 2;
-				}
-				if (selectedRect.height < getSize().height / 2) {
-					selectedRect.height = getSize().height / 2;
-				}
-				// Set the same ratio for the visible rectangle and the display
-				// area
-				int hFact = selectedRect.height * getSize().width;
-				int wFact = selectedRect.width * getSize().height;
-				if (hFact > wFact) {
-					selectedRect.width = hFact / getSize().height;
-				} else {
-					selectedRect.height = wFact / getSize().width;
-				}
-				// Keep the center of the selection
-				if (selectedRect.width != oldWidth) {
-					selectedRect.x -= (selectedRect.width - oldWidth) / 2;
-				}
-				if (selectedRect.height != oldHeight) {
-					selectedRect.y -= (selectedRect.height - oldHeight) / 2;
-				}
-				checkVisibleRectSize(image, selectedRect);
-				checkVisibleRectPos(image, selectedRect);
-				synchronized (MapillaryImageDisplay.this) {
-					MapillaryImageDisplay.this.visibleRect = selectedRect;
-				}
-				selectedRect = null;
-				MapillaryImageDisplay.this.repaint();
-			}
-		}
-
-		@Override
-		public void mouseEntered(MouseEvent e) {
-		}
-
-		@Override
-		public void mouseExited(MouseEvent e) {
-		}
-
-		@Override
-		public void mouseMoved(MouseEvent e) {
-		}
-
-		private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
-			if (p.x < visibleRect.x) {
-				p.x = visibleRect.x;
-			}
-			if (p.x > visibleRect.x + visibleRect.width) {
-				p.x = visibleRect.x + visibleRect.width;
-			}
-			if (p.y < visibleRect.y) {
-				p.y = visibleRect.y;
-			}
-			if (p.y > visibleRect.y + visibleRect.height) {
-				p.y = visibleRect.y + visibleRect.height;
-			}
-		}
-	}
-
-	public MapillaryImageDisplay() {
-		ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
-		addMouseListener(mouseListener);
-		addMouseWheelListener(mouseListener);
-		addMouseMotionListener(mouseListener);
-		this.setLayout(new BorderLayout());
-		JPanel southPanel = new JPanel();
-		southPanel.setLayout(new BorderLayout());
-		hyperlink = new HyperlinkLabel();
-		southPanel.add(hyperlink, BorderLayout.EAST);
-		southPanel.setOpaque(false);
-
-		add(southPanel, BorderLayout.SOUTH);
-	}
-
-	/**
-	 * Sets a new picture to be displayed.
-	 * 
-	 * @param image
-	 */
-	public void setImage(BufferedImage image) {
-		synchronized (this) {
-			this.image = image;
-			selectedRect = null;
-			if (image != null)
-				this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
-						image.getHeight(null));
-		}
-		repaint();
-	}
-
-	/**
-	 * Returns the picture that is being displayerd
-	 * 
-	 * @return
-	 */
-	public BufferedImage getImage() {
-		return this.image;
-	}
-
-	/**
-	 * Paints the visible part of the picture.
-	 */
-	public void paintComponent(Graphics g) {
-		Image image;
-		Rectangle visibleRect;
-		synchronized (this) {
-			image = this.image;
-			visibleRect = this.visibleRect;
-		}
-		if (image == null) {
-			g.setColor(Color.black);
-			String noImageStr = tr("No image");
-			Rectangle2D noImageSize = g.getFontMetrics(g.getFont())
-					.getStringBounds(noImageStr, g);
-			Dimension size = getSize();
-			g.drawString(noImageStr,
-					(int) ((size.width - noImageSize.getWidth()) / 2),
-					(int) ((size.height - noImageSize.getHeight()) / 2));
-		} else {
-			Rectangle target = calculateDrawImageRectangle(visibleRect);
-			g.drawImage(image, target.x, target.y, target.x + target.width,
-					target.y + target.height, visibleRect.x, visibleRect.y,
-					visibleRect.x + visibleRect.width, visibleRect.y
-							+ visibleRect.height, null);
-			if (selectedRect != null) {
-				Point topLeft = img2compCoord(visibleRect, selectedRect.x,
-						selectedRect.y);
-				Point bottomRight = img2compCoord(visibleRect, selectedRect.x
-						+ selectedRect.width, selectedRect.y
-						+ selectedRect.height);
-				g.setColor(new Color(128, 128, 128, 180));
-				g.fillRect(target.x, target.y, target.width, topLeft.y
-						- target.y);
-				g.fillRect(target.x, target.y, topLeft.x - target.x,
-						target.height);
-				g.fillRect(bottomRight.x, target.y, target.x + target.width
-						- bottomRight.x, target.height);
-				g.fillRect(target.x, bottomRight.y, target.width, target.y
-						+ target.height - bottomRight.y);
-				g.setColor(Color.black);
-				g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
-						bottomRight.y - topLeft.y);
-			}
-		}
-	}
-
-	private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
-		Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-		return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
-				/ visibleRect.width, drawRect.y
-				+ ((yImg - visibleRect.y) * drawRect.height)
-				/ visibleRect.height);
-	}
-
-	private final Point comp2imgCoord(Rectangle visibleRect, int xComp,
-			int yComp) {
-		Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
-		return new Point(visibleRect.x
-				+ ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
-				visibleRect.y + ((yComp - drawRect.y) * visibleRect.height)
-						/ drawRect.height);
-	}
-
-	private final Point getCenterImgCoord(Rectangle visibleRect) {
-		return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y
-				+ visibleRect.height / 2);
-	}
-
-	private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
-		return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0,
-				getSize().width, getSize().height));
-	}
-
-	/**
-	 * calculateDrawImageRectangle
-	 *
-	 * @param imgRect
-	 *            the part of the image that should be drawn (in image
-	 *            coordinates)
-	 * @param compRect
-	 *            the part of the component where the image should be drawn (in
-	 *            component coordinates)
-	 * @return the part of compRect with the same width/height ratio as the
-	 *         image
-	 */
-	static Rectangle calculateDrawImageRectangle(Rectangle imgRect,
-			Rectangle compRect) {
-		int x, y, w, h;
-		x = 0;
-		y = 0;
-		w = compRect.width;
-		h = compRect.height;
-		int wFact = w * imgRect.height;
-		int hFact = h * imgRect.width;
-		if (wFact != hFact) {
-			if (wFact > hFact) {
-				w = hFact / imgRect.height;
-				x = (compRect.width - w) / 2;
-			} else {
-				h = wFact / imgRect.width;
-				y = (compRect.height - h) / 2;
-			}
-		}
-		return new Rectangle(x + compRect.x, y + compRect.y, w, h);
-	}
-
-	public void zoomBestFitOrOne() {
-		Image image;
-		Rectangle visibleRect;
-		synchronized (this) {
-			image = MapillaryImageDisplay.this.image;
-			visibleRect = MapillaryImageDisplay.this.visibleRect;
-		}
-		if (image == null)
-			return;
-		if (visibleRect.width != image.getWidth(null)
-				|| visibleRect.height != image.getHeight(null)) {
-			// The display is not at best fit. => Zoom to best fit
-			visibleRect = new Rectangle(0, 0, image.getWidth(null),
-					image.getHeight(null));
-		} else {
-			// The display is at best fit => zoom to 1:1
-			Point center = getCenterImgCoord(visibleRect);
-			visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
-					- getHeight() / 2, getWidth(), getHeight());
-			checkVisibleRectPos(image, visibleRect);
-		}
-		synchronized (this) {
-			this.visibleRect = visibleRect;
-		}
-		repaint();
-	}
-
-	private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
-		if (visibleRect.x < 0) {
-			visibleRect.x = 0;
-		}
-		if (visibleRect.y < 0) {
-			visibleRect.y = 0;
-		}
-		if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
-			visibleRect.x = image.getWidth(null) - visibleRect.width;
-		}
-		if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
-			visibleRect.y = image.getHeight(null) - visibleRect.height;
-		}
-	}
-
-	private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
-		if (visibleRect.width > image.getWidth(null)) {
-			visibleRect.width = image.getWidth(null);
-		}
-		if (visibleRect.height > image.getHeight(null)) {
-			visibleRect.height = image.getHeight(null);
-		}
-	}
+    private static final int DRAG_BUTTON = Main.pref.getInteger(
+            "mapillary.picture-drag-button", 3);
+    private static final int OPTION_BUTTON = Main.pref.getInteger(
+            "mapillary.picture-option-button", 2);
+    private static final int ZOOM_BUTTON = Main.pref.getInteger(
+            "mapillary.picture-zoom-button", 1);
+
+    /** The image currently displayed */
+    private transient BufferedImage image = null;
+
+    /**
+     * The rectangle (in image coordinates) of the image that is visible. This
+     * rectangle is calculated each time the zoom is modified
+     */
+    private Rectangle visibleRect = null;
+
+    /**
+     * When a selection is done, the rectangle of the selection (in image
+     * coordinates)
+     */
+    private Rectangle selectedRect = null;
+
+    public HyperlinkLabel hyperlink;
+
+    private class ImgDisplayMouseListener implements MouseListener,
+            MouseWheelListener, MouseMotionListener {
+        private boolean mouseIsDragging = false;
+        private long lastTimeForMousePoint = 0L;
+        private Point mousePointInImg = null;
+
+        /**
+         * Zoom in and out, trying to preserve the point of the image that was
+         * under the mouse cursor at the same place
+         */
+        @Override
+        public void mouseWheelMoved(MouseWheelEvent e) {
+            Image image;
+            Rectangle visibleRect;
+            synchronized (MapillaryImageDisplay.this) {
+                image = MapillaryImageDisplay.this.image;
+                visibleRect = MapillaryImageDisplay.this.visibleRect;
+            }
+            mouseIsDragging = false;
+            selectedRect = null;
+            if (image == null)
+                return;
+            // Calculate the mouse cursor position in image coordinates, so that
+            // we can center the zoom
+            // on that mouse position.
+            // To avoid issues when the user tries to zoom in on the image
+            // borders, this point is not calculated
+            // again if there was less than 1.5seconds since the last event.
+            if (e.getWhen() - lastTimeForMousePoint > 1500
+                    || mousePointInImg == null) {
+                lastTimeForMousePoint = e.getWhen();
+                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+            }
+            // Applicate the zoom to the visible rectangle in image coordinates
+            if (e.getWheelRotation() > 0) {
+                visibleRect.width = visibleRect.width * 3 / 2;
+                visibleRect.height = visibleRect.height * 3 / 2;
+            } else {
+                visibleRect.width = visibleRect.width * 2 / 3;
+                visibleRect.height = visibleRect.height * 2 / 3;
+            }
+            // Check that the zoom doesn't exceed 2:1
+            if (visibleRect.width < getSize().width / 2) {
+                visibleRect.width = getSize().width / 2;
+            }
+            if (visibleRect.height < getSize().height / 2) {
+                visibleRect.height = getSize().height / 2;
+            }
+            // Set the same ratio for the visible rectangle and the display area
+            int hFact = visibleRect.height * getSize().width;
+            int wFact = visibleRect.width * getSize().height;
+            if (hFact > wFact) {
+                visibleRect.width = hFact / getSize().height;
+            } else {
+                visibleRect.height = wFact / getSize().width;
+            }
+            // The size of the visible rectangle is limited by the image size.
+            checkVisibleRectSize(image, visibleRect);
+            // Set the position of the visible rectangle, so that the mouse
+            // cursor doesn't move on the image.
+            Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+            visibleRect.x = mousePointInImg.x
+                    + ((drawRect.x - e.getX()) * visibleRect.width)
+                    / drawRect.width;
+            visibleRect.y = mousePointInImg.y
+                    + ((drawRect.y - e.getY()) * visibleRect.height)
+                    / drawRect.height;
+            // The position is also limited by the image size
+            checkVisibleRectPos(image, visibleRect);
+            synchronized (MapillaryImageDisplay.this) {
+                MapillaryImageDisplay.this.visibleRect = visibleRect;
+            }
+            MapillaryImageDisplay.this.repaint();
+        }
+
+        /** Center the display on the point that has been clicked */
+        @Override
+        public void mouseClicked(MouseEvent e) {
+            // Move the center to the clicked point.
+            Image image;
+            Rectangle visibleRect;
+            synchronized (MapillaryImageDisplay.this) {
+                image = MapillaryImageDisplay.this.image;
+                visibleRect = MapillaryImageDisplay.this.visibleRect;
+            }
+            if (image == null)
+                return;
+            if (e.getButton() == OPTION_BUTTON) {
+                if (!MapillaryImageDisplay.this.visibleRect
+                        .equals(new Rectangle(0, 0, image.getWidth(null), image
+                                .getHeight(null))))
+                    // Zooms to 1:1
+                    MapillaryImageDisplay.this.visibleRect = new Rectangle(0,
+                            0, image.getWidth(null), image.getHeight(null));
+                else
+                    // Zooms to best fit.
+                    MapillaryImageDisplay.this.visibleRect = new Rectangle(
+                            0,
+                            (image.getHeight(null) - (image.getWidth(null) * getHeight())
+                                    / getWidth()) / 2, image.getWidth(null),
+                            (image.getWidth(null) * getHeight()) / getWidth());
+                MapillaryImageDisplay.this.repaint();
+                return;
+            } else if (e.getButton() != DRAG_BUTTON)
+                return;
+            // Calculate the translation to set the clicked point the center of
+            // the view.
+            Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
+            Point center = getCenterImgCoord(visibleRect);
+            visibleRect.x += click.x - center.x;
+            visibleRect.y += click.y - center.y;
+            checkVisibleRectPos(image, visibleRect);
+            synchronized (MapillaryImageDisplay.this) {
+                MapillaryImageDisplay.this.visibleRect = visibleRect;
+            }
+            MapillaryImageDisplay.this.repaint();
+        }
+
+        /**
+         * Initialize the dragging, either with button 1 (simple dragging) or
+         * button 3 (selection of a picture part)
+         */
+        @Override
+        public void mousePressed(MouseEvent e) {
+            if (image == null) {
+                mouseIsDragging = false;
+                selectedRect = null;
+                return;
+            }
+            Image image;
+            Rectangle visibleRect;
+            synchronized (MapillaryImageDisplay.this) {
+                image = MapillaryImageDisplay.this.image;
+                visibleRect = MapillaryImageDisplay.this.visibleRect;
+            }
+            if (image == null)
+                return;
+            if (e.getButton() == DRAG_BUTTON) {
+                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+                mouseIsDragging = true;
+                selectedRect = null;
+            } else if (e.getButton() == ZOOM_BUTTON) {
+                mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+                checkPointInVisibleRect(mousePointInImg, visibleRect);
+                mouseIsDragging = false;
+                selectedRect = new Rectangle(mousePointInImg.x,
+                        mousePointInImg.y, 0, 0);
+                MapillaryImageDisplay.this.repaint();
+            } else {
+                mouseIsDragging = false;
+                selectedRect = null;
+            }
+        }
+
+        @Override
+        public void mouseDragged(MouseEvent e) {
+            if (!mouseIsDragging && selectedRect == null)
+                return;
+            Image image;
+            Rectangle visibleRect;
+            synchronized (MapillaryImageDisplay.this) {
+                image = MapillaryImageDisplay.this.image;
+                visibleRect = MapillaryImageDisplay.this.visibleRect;
+            }
+            if (image == null) {
+                mouseIsDragging = false;
+                selectedRect = null;
+                return;
+            }
+            if (mouseIsDragging) {
+                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+                visibleRect.x += mousePointInImg.x - p.x;
+                visibleRect.y += mousePointInImg.y - p.y;
+                checkVisibleRectPos(image, visibleRect);
+                synchronized (MapillaryImageDisplay.this) {
+                    MapillaryImageDisplay.this.visibleRect = visibleRect;
+                }
+                MapillaryImageDisplay.this.repaint();
+            } else if (selectedRect != null) {
+                Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+                checkPointInVisibleRect(p, visibleRect);
+                Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
+                        : mousePointInImg.x, p.y < mousePointInImg.y ? p.y
+                        : mousePointInImg.y,
+                        p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x
+                                - mousePointInImg.x,
+                        p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
+                                - mousePointInImg.y);
+                checkVisibleRectSize(image, rect);
+                checkVisibleRectPos(image, rect);
+                MapillaryImageDisplay.this.selectedRect = rect;
+                MapillaryImageDisplay.this.repaint();
+            }
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            if (!mouseIsDragging && selectedRect == null)
+                return;
+            Image image;
+            synchronized (MapillaryImageDisplay.this) {
+                image = MapillaryImageDisplay.this.image;
+            }
+            if (image == null) {
+                mouseIsDragging = false;
+                selectedRect = null;
+                return;
+            }
+            if (mouseIsDragging) {
+                mouseIsDragging = false;
+            } else if (selectedRect != null) {
+                int oldWidth = selectedRect.width;
+                int oldHeight = selectedRect.height;
+                // Check that the zoom doesn't exceed 2:1
+                if (selectedRect.width < getSize().width / 2) {
+                    selectedRect.width = getSize().width / 2;
+                }
+                if (selectedRect.height < getSize().height / 2) {
+                    selectedRect.height = getSize().height / 2;
+                }
+                // Set the same ratio for the visible rectangle and the display
+                // area
+                int hFact = selectedRect.height * getSize().width;
+                int wFact = selectedRect.width * getSize().height;
+                if (hFact > wFact) {
+                    selectedRect.width = hFact / getSize().height;
+                } else {
+                    selectedRect.height = wFact / getSize().width;
+                }
+                // Keep the center of the selection
+                if (selectedRect.width != oldWidth) {
+                    selectedRect.x -= (selectedRect.width - oldWidth) / 2;
+                }
+                if (selectedRect.height != oldHeight) {
+                    selectedRect.y -= (selectedRect.height - oldHeight) / 2;
+                }
+                checkVisibleRectSize(image, selectedRect);
+                checkVisibleRectPos(image, selectedRect);
+                synchronized (MapillaryImageDisplay.this) {
+                    MapillaryImageDisplay.this.visibleRect = selectedRect;
+                }
+                selectedRect = null;
+                MapillaryImageDisplay.this.repaint();
+            }
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseMoved(MouseEvent e) {
+        }
+
+        private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
+            if (p.x < visibleRect.x) {
+                p.x = visibleRect.x;
+            }
+            if (p.x > visibleRect.x + visibleRect.width) {
+                p.x = visibleRect.x + visibleRect.width;
+            }
+            if (p.y < visibleRect.y) {
+                p.y = visibleRect.y;
+            }
+            if (p.y > visibleRect.y + visibleRect.height) {
+                p.y = visibleRect.y + visibleRect.height;
+            }
+        }
+    }
+
+    public MapillaryImageDisplay() {
+        ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
+        addMouseListener(mouseListener);
+        addMouseWheelListener(mouseListener);
+        addMouseMotionListener(mouseListener);
+        this.setLayout(new BorderLayout());
+        JPanel southPanel = new JPanel();
+        southPanel.setLayout(new BorderLayout());
+        hyperlink = new HyperlinkLabel();
+        southPanel.add(hyperlink, BorderLayout.EAST);
+        southPanel.setOpaque(false);
+
+        add(southPanel, BorderLayout.SOUTH);
+    }
+
+    /**
+     * Sets a new picture to be displayed.
+     * 
+     * @param image
+     */
+    public void setImage(BufferedImage image) {
+        synchronized (this) {
+            this.image = image;
+            selectedRect = null;
+            if (image != null)
+                this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
+                        image.getHeight(null));
+        }
+        repaint();
+    }
+
+    /**
+     * Returns the picture that is being displayerd
+     * 
+     * @return
+     */
+    public BufferedImage getImage() {
+        return this.image;
+    }
+
+    /**
+     * Paints the visible part of the picture.
+     */
+    public void paintComponent(Graphics g) {
+        Image image;
+        Rectangle visibleRect;
+        synchronized (this) {
+            image = this.image;
+            visibleRect = this.visibleRect;
+        }
+        if (image == null) {
+            g.setColor(Color.black);
+            String noImageStr = tr("No image");
+            Rectangle2D noImageSize = g.getFontMetrics(g.getFont())
+                    .getStringBounds(noImageStr, g);
+            Dimension size = getSize();
+            g.drawString(noImageStr,
+                    (int) ((size.width - noImageSize.getWidth()) / 2),
+                    (int) ((size.height - noImageSize.getHeight()) / 2));
+        } else {
+            Rectangle target = calculateDrawImageRectangle(visibleRect);
+            g.drawImage(image, target.x, target.y, target.x + target.width,
+                    target.y + target.height, visibleRect.x, visibleRect.y,
+                    visibleRect.x + visibleRect.width, visibleRect.y
+                            + visibleRect.height, null);
+            if (selectedRect != null) {
+                Point topLeft = img2compCoord(visibleRect, selectedRect.x,
+                        selectedRect.y);
+                Point bottomRight = img2compCoord(visibleRect, selectedRect.x
+                        + selectedRect.width, selectedRect.y
+                        + selectedRect.height);
+                g.setColor(new Color(128, 128, 128, 180));
+                g.fillRect(target.x, target.y, target.width, topLeft.y
+                        - target.y);
+                g.fillRect(target.x, target.y, topLeft.x - target.x,
+                        target.height);
+                g.fillRect(bottomRight.x, target.y, target.x + target.width
+                        - bottomRight.x, target.height);
+                g.fillRect(target.x, bottomRight.y, target.width, target.y
+                        + target.height - bottomRight.y);
+                g.setColor(Color.black);
+                g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
+                        bottomRight.y - topLeft.y);
+            }
+        }
+    }
+
+    private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
+        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+        return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
+                / visibleRect.width, drawRect.y
+                + ((yImg - visibleRect.y) * drawRect.height)
+                / visibleRect.height);
+    }
+
+    private final Point comp2imgCoord(Rectangle visibleRect, int xComp,
+            int yComp) {
+        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+        return new Point(visibleRect.x
+                + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
+                visibleRect.y + ((yComp - drawRect.y) * visibleRect.height)
+                        / drawRect.height);
+    }
+
+    private final Point getCenterImgCoord(Rectangle visibleRect) {
+        return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y
+                + visibleRect.height / 2);
+    }
+
+    private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
+        return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0,
+                getSize().width, getSize().height));
+    }
+
+    /**
+     * calculateDrawImageRectangle
+     *
+     * @param imgRect
+     *            the part of the image that should be drawn (in image
+     *            coordinates)
+     * @param compRect
+     *            the part of the component where the image should be drawn (in
+     *            component coordinates)
+     * @return the part of compRect with the same width/height ratio as the
+     *         image
+     */
+    static Rectangle calculateDrawImageRectangle(Rectangle imgRect,
+            Rectangle compRect) {
+        int x, y, w, h;
+        x = 0;
+        y = 0;
+        w = compRect.width;
+        h = compRect.height;
+        int wFact = w * imgRect.height;
+        int hFact = h * imgRect.width;
+        if (wFact != hFact) {
+            if (wFact > hFact) {
+                w = hFact / imgRect.height;
+                x = (compRect.width - w) / 2;
+            } else {
+                h = wFact / imgRect.width;
+                y = (compRect.height - h) / 2;
+            }
+        }
+        return new Rectangle(x + compRect.x, y + compRect.y, w, h);
+    }
+
+    public void zoomBestFitOrOne() {
+        Image image;
+        Rectangle visibleRect;
+        synchronized (this) {
+            image = MapillaryImageDisplay.this.image;
+            visibleRect = MapillaryImageDisplay.this.visibleRect;
+        }
+        if (image == null)
+            return;
+        if (visibleRect.width != image.getWidth(null)
+                || visibleRect.height != image.getHeight(null)) {
+            // The display is not at best fit. => Zoom to best fit
+            visibleRect = new Rectangle(0, 0, image.getWidth(null),
+                    image.getHeight(null));
+        } else {
+            // The display is at best fit => zoom to 1:1
+            Point center = getCenterImgCoord(visibleRect);
+            visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
+                    - getHeight() / 2, getWidth(), getHeight());
+            checkVisibleRectPos(image, visibleRect);
+        }
+        synchronized (this) {
+            this.visibleRect = visibleRect;
+        }
+        repaint();
+    }
+
+    private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
+        if (visibleRect.x < 0) {
+            visibleRect.x = 0;
+        }
+        if (visibleRect.y < 0) {
+            visibleRect.y = 0;
+        }
+        if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
+            visibleRect.x = image.getWidth(null) - visibleRect.width;
+        }
+        if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
+            visibleRect.y = image.getHeight(null) - visibleRect.height;
+        }
+    }
+
+    private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
+        if (visibleRect.width > image.getWidth(null)) {
+            visibleRect.width = image.getWidth(null);
+        }
+        if (visibleRect.height > image.getHeight(null)) {
+            visibleRect.height = image.getHeight(null);
+        }
+    }
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java	(revision 31278)
@@ -14,38 +14,41 @@
 public class MapillaryPreferenceSetting implements SubPreferenceSetting {
 
-	private JCheckBox reverseButtons = new JCheckBox(tr("Reverse buttons position when displaying images."));
-	private JCheckBox downloadMode = new JCheckBox(tr("Download images manually"));
+    private JCheckBox reverseButtons = new JCheckBox(
+            tr("Reverse buttons position when displaying images."));
+    private JCheckBox downloadMode = new JCheckBox(
+            tr("Download images manually"));
 
-	
-	@Override
-	public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
-		return gui.getDisplayPreference();
-	}
+    @Override
+    public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
+        return gui.getDisplayPreference();
+    }
 
-	@Override
-	public void addGui(PreferenceTabbedPane gui) {
-		JPanel panel = new JPanel();
-		
-		reverseButtons.setSelected(Main.pref.getBoolean("mapillary.reverse-buttons"));
-		downloadMode.setSelected(Main.pref.getBoolean("mapillary.download-manually"));
-		
-		panel.setLayout(new FlowLayout(FlowLayout.LEFT));
-		panel.add(reverseButtons);
-		panel.add(downloadMode);
+    @Override
+    public void addGui(PreferenceTabbedPane gui) {
+        JPanel panel = new JPanel();
+
+        reverseButtons.setSelected(Main.pref
+                .getBoolean("mapillary.reverse-buttons"));
+        downloadMode.setSelected(Main.pref
+                .getBoolean("mapillary.download-manually"));
+
+        panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        panel.add(reverseButtons);
+        panel.add(downloadMode);
         gui.getDisplayPreference().addSubTab(this, "Mapillary", panel);
-	}
+    }
 
-	@Override
-	public boolean ok() {
+    @Override
+    public boolean ok() {
         boolean mod = false;
         Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected());
         Main.pref.put("mapillary.download-manually", downloadMode.isSelected());
         return mod;
-	}
+    }
 
-	@Override
-	public boolean isExpert() {
-		return false;
-	}
+    @Override
+    public boolean isExpert() {
+        return false;
+    }
 
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java	(revision 31277)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryToggleDialog.java	(revision 31278)
@@ -43,441 +43,441 @@
  */
 public class MapillaryToggleDialog extends ToggleDialog implements
-		ICachedLoaderListener, MapillaryDataListener {
-
-	public final static int NORMAL_MODE = 0;
-	public final static int SIGN_MODE = 1;
-
-	public final static String BASE_TITLE = "Mapillary picture";
-
-	public static MapillaryToggleDialog INSTANCE;
-
-	public volatile MapillaryAbstractImage image;
-
-	public final SideButton nextButton = new SideButton(new nextPictureAction());
-	public final SideButton previousButton = new SideButton(
-			new previousPictureAction());
-	public final SideButton redButton = new SideButton(new redAction());
-	public final SideButton blueButton = new SideButton(new blueAction());
-	private List<SideButton> normalMode;
-
-	public final SideButton nextSignButton = new SideButton(
-			new NextSignAction());
-	public final SideButton previousSignButton = new SideButton(
-			new PreviousSignAction());
-	private List<SideButton> signMode;
-
-	private int mode;
-
-	private JPanel buttonsPanel;
-
-	public MapillaryImageDisplay mapillaryImageDisplay;
-
-	private MapillaryCache imageCache;
-	private MapillaryCache thumbnailCache;
-
-	public MapillaryToggleDialog() {
-		super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"),
-				Shortcut.registerShortcut(tr("Mapillary dialog"),
-						tr("Open Mapillary main dialog"), KeyEvent.VK_M,
-						Shortcut.NONE), 200);
-		MapillaryData.getInstance().addListener(this);
-
-		mapillaryImageDisplay = new MapillaryImageDisplay();
-
-		blueButton.setForeground(Color.BLUE);
-		redButton.setForeground(Color.RED);
-
-		normalMode = Arrays.asList(new SideButton[] { blueButton,
-				previousButton, nextButton, redButton });
-		signMode = Arrays.asList(new SideButton[] { previousSignButton,
-				nextSignButton });
-
-		mode = NORMAL_MODE;
-		
-		createLayout(mapillaryImageDisplay, normalMode,
-				Main.pref.getBoolean("mapillary.reverse-buttons"));
-		disableAllButtons();
-	}
-
-	public static MapillaryToggleDialog getInstance() {
-		if (INSTANCE == null)
-			INSTANCE = new MapillaryToggleDialog();
-		return INSTANCE;
-	}
-
-	public static void destroyInstance() {
-		INSTANCE = null;
-	}
-
-	/**
-	 * Switches from one mode to the other one.
-	 */
-	public void switchMode() {
-		this.removeAll();
-		List<SideButton> list = null;
-		if (mode == NORMAL_MODE) {
-			list = signMode;
-			mode = SIGN_MODE;
-		} else if (mode == SIGN_MODE) {
-			list = normalMode;
-			mode = NORMAL_MODE;
-		}
-		
-		createLayout(mapillaryImageDisplay, list,
-				Main.pref.getBoolean("mapillary.reverse-buttons"));
-		disableAllButtons();
-		updateImage();
-	}
-
-	/**
-	 * Downloads the image of the selected MapillaryImage and sets in the
-	 * MapillaryImageDisplay object.
-	 */
-	public synchronized void updateImage() {
-		if (!SwingUtilities.isEventDispatchThread()) {
-			SwingUtilities.invokeLater(new Runnable() {
-				@Override
-				public void run() {
-					updateImage();
-				}
-			});
-		} else {
-			if (MapillaryLayer.INSTANCE == null) {
-				return;
-			}
-			if (this.image == null) {
-				mapillaryImageDisplay.setImage(null);
-				titleBar.setTitle(tr(BASE_TITLE));
-				disableAllButtons();
-				return;
-			}
-			if (image instanceof MapillaryImage) {
-				mapillaryImageDisplay.hyperlink.setVisible(true);
-				MapillaryImage mapillaryImage = (MapillaryImage) this.image;
-				String title = tr(BASE_TITLE);
-				if (mapillaryImage.getUser() != null)
-					title += " -- " + mapillaryImage.getUser();
-				if (mapillaryImage.getCapturedAt() != 0)
-					title += " -- " + mapillaryImage.getDate();
-				titleBar.setTitle(title);
-				if (mode == NORMAL_MODE) {
-					this.nextButton.setEnabled(true);
-					this.previousButton.setEnabled(true);
-					if (mapillaryImage.next() == null)
-						this.nextButton.setEnabled(false);
-					if (mapillaryImage.previous() == null)
-						this.previousButton.setEnabled(false);
-				} else if (mode == SIGN_MODE) {
-					previousSignButton.setEnabled(true);
-					nextSignButton.setEnabled(true);
-					int i = MapillaryData
-							.getInstance()
-							.getImages()
-							.indexOf(
-									MapillaryData.getInstance()
-											.getSelectedImage());
-					int first = -1;
-					int last = -1;
-					int c = 0;
-					for (MapillaryAbstractImage img : MapillaryData
-							.getInstance().getImages()) {
-						if (img instanceof MapillaryImage)
-							if (!((MapillaryImage) img).getSigns().isEmpty()) {
-								if (first == -1)
-									first = c;
-								last = c;
-							}
-						c++;
-					}
-					if (first >= i)
-						previousSignButton.setEnabled(false);
-					if (last <= i)
-						nextSignButton.setEnabled(false);
-				}
-
-				mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey());
-				// Downloads the thumbnail.
-				this.mapillaryImageDisplay.setImage(null);
-				if (thumbnailCache != null)
-					thumbnailCache.cancelOutstandingTasks();
-				thumbnailCache = new MapillaryCache(mapillaryImage.getKey(),
-						MapillaryCache.Type.THUMBNAIL);
-				thumbnailCache.submit(this, false);
-
-				// Downloads the full resolution image.
-				if (imageCache != null)
-					imageCache.cancelOutstandingTasks();
-				imageCache = new MapillaryCache(mapillaryImage.getKey(),
-						MapillaryCache.Type.FULL_IMAGE);
-				imageCache.submit(this, false);
-			} else if (image instanceof MapillaryImportedImage) {
-				mapillaryImageDisplay.hyperlink.setVisible(false);
-				this.nextButton.setEnabled(false);
-				this.previousButton.setEnabled(false);
-				MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image;
-				try {
-					mapillaryImageDisplay.setImage(mapillaryImage.getImage());
-				} catch (IOException e) {
-					Main.error(e);
-				}
-				mapillaryImageDisplay.hyperlink.setURL(null);
-			}
-		}
-	}
-
-	private void disableAllButtons() {
-		nextButton.setEnabled(false);
-		previousButton.setEnabled(false);
-		blueButton.setEnabled(false);
-		redButton.setEnabled(false);
-		nextSignButton.setEnabled(false);
-		previousSignButton.setEnabled(false);
-		mapillaryImageDisplay.hyperlink.setVisible(false);
-	}
-
-	/**
-	 * Sets a new MapillaryImage to be shown.
-	 * 
-	 * @param image
-	 */
-	public synchronized void setImage(MapillaryAbstractImage image) {
-		this.image = image;
-	}
-
-	/**
-	 * Returns the MapillaryImage objects which is being shown.
-	 * 
-	 * @return
-	 */
-	public synchronized MapillaryAbstractImage getImage() {
-		return this.image;
-	}
-
-	/**
-	 * Action class form the next image button.
-	 * 
-	 * @author Jorge
-	 *
-	 */
-	class nextPictureAction extends AbstractAction {
-		public nextPictureAction() {
-			putValue(NAME, tr("Next picture"));
-			putValue(SHORT_DESCRIPTION,
-					tr("Shows the next picture in the sequence"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				MapillaryData.getInstance().selectNext();
-			}
-		}
-	}
-
-	/**
-	 * Action class for the previous image button.
-	 * 
-	 * @author Jorge
-	 *
-	 */
-	class previousPictureAction extends AbstractAction {
-		public previousPictureAction() {
-			putValue(NAME, tr("Previous picture"));
-			putValue(SHORT_DESCRIPTION,
-					tr("Shows the previous picture in the sequence"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				MapillaryData.getInstance().selectPrevious();
-			}
-		}
-	}
-
-	/**
-	 * Action class to jump to the image following the red line.
-	 * 
-	 * @author nokutu
-	 *
-	 */
-	class redAction extends AbstractAction {
-		public redAction() {
-			putValue(NAME, tr("Jump to red"));
-			putValue(
-					SHORT_DESCRIPTION,
-					tr("Jumps to the picture at the other side of the red line"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				MapillaryData.getInstance().setSelectedImage(
-						MapillaryLayer.RED, true);
-			}
-		}
-	}
-
-	/**
-	 * Action class to jump to the image following the blue line.
-	 * 
-	 * @author nokutu
-	 *
-	 */
-	class blueAction extends AbstractAction {
-		public blueAction() {
-			putValue(NAME, tr("Jump to blue"));
-			putValue(
-					SHORT_DESCRIPTION,
-					tr("Jumps to the picture at the other side of the blue line"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				MapillaryData.getInstance().setSelectedImage(
-						MapillaryLayer.BLUE, true);
-			}
-		}
-	}
-
-	/**
-	 * When the pictures are returned from the cache, they are set in the
-	 * {@link MapillaryImageDisplay} object.
-	 */
-	@Override
-	public void loadingFinished(CacheEntry data,
-			CacheEntryAttributes attributes, LoadResult result) {
-		if (!SwingUtilities.isEventDispatchThread()) {
-			SwingUtilities.invokeLater(new Runnable() {
-				@Override
-				public void run() {
-					updateImage();
-				}
-			});
-		} else if (data != null && result == LoadResult.SUCCESS) {
-			try {
-				BufferedImage img = ImageIO.read(new ByteArrayInputStream(data
-						.getContent()));
-				if (this.mapillaryImageDisplay.getImage() == null)
-					mapillaryImageDisplay.setImage(img);
-				else if (img.getHeight() > this.mapillaryImageDisplay
-						.getImage().getHeight()) {
-					mapillaryImageDisplay.setImage(img);
-				}
-			} catch (IOException e) {
-				Main.error(e);
-			}
-		}
-	}
-
-	/**
-	 * Creates the layout of the dialog.
-	 * 
-	 * @param data
-	 *            The content of the dialog
-	 * @param buttons
-	 *            The buttons where you can click
-	 * @param reverse
-	 *            {@code true} if the buttons should go at the top;
-	 *            {@code false} otherwise.
-	 */
-	public void createLayout(Component data, List<SideButton> buttons,
-			boolean reverse) {
-		this.removeAll();
-		JPanel panel = new JPanel();
-		panel.setLayout(new BorderLayout());
-		panel.add(data, BorderLayout.CENTER);
-		if (reverse) {
-			buttonsPanel = new JPanel(new GridLayout(1, 1));
-			if (!buttons.isEmpty() && buttons.get(0) != null) {
-				final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean(
-						"dialog.align.left", false) ? new FlowLayout(
-						FlowLayout.LEFT) : new GridLayout(1, buttons.size()));
-				buttonsPanel.add(buttonRowPanel);
-				for (SideButton button : buttons)
-					buttonRowPanel.add(button);
-			}
-			panel.add(buttonsPanel, BorderLayout.NORTH);
-			createLayout(panel, true, null);
-		} else
-			createLayout(panel, true, buttons);
-		this.add(titleBar, BorderLayout.NORTH);
-	}
-
-	@Override
-	public void selectedImageChanged(MapillaryAbstractImage oldImage,
-			MapillaryAbstractImage newImage) {
-		setImage(MapillaryData.getInstance().getSelectedImage());
-		updateImage();
-	}
-
-	/**
-	 * Action class to jump to the next picture containing a sign.
-	 * 
-	 * @author nokutu
-	 *
-	 */
-	class NextSignAction extends AbstractAction {
-		public NextSignAction() {
-			putValue(NAME, tr("Next Sign"));
-			putValue(SHORT_DESCRIPTION,
-					tr("Jumps to the next picture that contains a sign"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				int i = MapillaryData
-						.getInstance()
-						.getImages()
-						.indexOf(MapillaryData.getInstance().getSelectedImage());
-				for (int j = i + 1; j < MapillaryData.getInstance().getImages()
-						.size(); j++) {
-					MapillaryAbstractImage img = MapillaryData.getInstance()
-							.getImages().get(j);
-					if (img instanceof MapillaryImage)
-						if (!((MapillaryImage) img).getSigns().isEmpty()) {
-							MapillaryData.getInstance().setSelectedImage(img,
-									true);
-							return;
-						}
-				}
-			}
-		}
-	}
-
-	/**
-	 * Action class to jump to the previous picture containing a sign.
-	 * 
-	 * @author nokutu
-	 *
-	 */
-	class PreviousSignAction extends AbstractAction {
-		public PreviousSignAction() {
-			putValue(NAME, tr("Previous Sign"));
-			putValue(SHORT_DESCRIPTION,
-					tr("Jumps to the previous picture that contains a sign"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent e) {
-			if (MapillaryToggleDialog.getInstance().getImage() != null) {
-				int i = MapillaryData
-						.getInstance()
-						.getImages()
-						.indexOf(MapillaryData.getInstance().getSelectedImage());
-				for (int j = i - 1; j >= 0; j--) {
-					MapillaryAbstractImage img = MapillaryData.getInstance()
-							.getImages().get(j);
-					if (img instanceof MapillaryImage)
-						if (!((MapillaryImage) img).getSigns().isEmpty()) {
-							MapillaryData.getInstance().setSelectedImage(img,
-									true);
-							return;
-						}
-				}
-			}
-		}
-	}
+        ICachedLoaderListener, MapillaryDataListener {
+
+    public final static int NORMAL_MODE = 0;
+    public final static int SIGN_MODE = 1;
+
+    public final static String BASE_TITLE = "Mapillary picture";
+
+    public static MapillaryToggleDialog INSTANCE;
+
+    public volatile MapillaryAbstractImage image;
+
+    public final SideButton nextButton = new SideButton(new nextPictureAction());
+    public final SideButton previousButton = new SideButton(
+            new previousPictureAction());
+    public final SideButton redButton = new SideButton(new redAction());
+    public final SideButton blueButton = new SideButton(new blueAction());
+    private List<SideButton> normalMode;
+
+    public final SideButton nextSignButton = new SideButton(
+            new NextSignAction());
+    public final SideButton previousSignButton = new SideButton(
+            new PreviousSignAction());
+    private List<SideButton> signMode;
+
+    private int mode;
+
+    private JPanel buttonsPanel;
+
+    public MapillaryImageDisplay mapillaryImageDisplay;
+
+    private MapillaryCache imageCache;
+    private MapillaryCache thumbnailCache;
+
+    public MapillaryToggleDialog() {
+        super(tr(BASE_TITLE), "mapillary.png", tr("Open Mapillary window"),
+                Shortcut.registerShortcut(tr("Mapillary dialog"),
+                        tr("Open Mapillary main dialog"), KeyEvent.VK_M,
+                        Shortcut.NONE), 200);
+        MapillaryData.getInstance().addListener(this);
+
+        mapillaryImageDisplay = new MapillaryImageDisplay();
+
+        blueButton.setForeground(Color.BLUE);
+        redButton.setForeground(Color.RED);
+
+        normalMode = Arrays.asList(new SideButton[] { blueButton,
+                previousButton, nextButton, redButton });
+        signMode = Arrays.asList(new SideButton[] { previousSignButton,
+                nextSignButton });
+
+        mode = NORMAL_MODE;
+
+        createLayout(mapillaryImageDisplay, normalMode,
+                Main.pref.getBoolean("mapillary.reverse-buttons"));
+        disableAllButtons();
+    }
+
+    public static MapillaryToggleDialog getInstance() {
+        if (INSTANCE == null)
+            INSTANCE = new MapillaryToggleDialog();
+        return INSTANCE;
+    }
+
+    public static void destroyInstance() {
+        INSTANCE = null;
+    }
+
+    /**
+     * Switches from one mode to the other one.
+     */
+    public void switchMode() {
+        this.removeAll();
+        List<SideButton> list = null;
+        if (mode == NORMAL_MODE) {
+            list = signMode;
+            mode = SIGN_MODE;
+        } else if (mode == SIGN_MODE) {
+            list = normalMode;
+            mode = NORMAL_MODE;
+        }
+
+        createLayout(mapillaryImageDisplay, list,
+                Main.pref.getBoolean("mapillary.reverse-buttons"));
+        disableAllButtons();
+        updateImage();
+    }
+
+    /**
+     * Downloads the image of the selected MapillaryImage and sets in the
+     * MapillaryImageDisplay object.
+     */
+    public synchronized void updateImage() {
+        if (!SwingUtilities.isEventDispatchThread()) {
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    updateImage();
+                }
+            });
+        } else {
+            if (MapillaryLayer.INSTANCE == null) {
+                return;
+            }
+            if (this.image == null) {
+                mapillaryImageDisplay.setImage(null);
+                titleBar.setTitle(tr(BASE_TITLE));
+                disableAllButtons();
+                return;
+            }
+            if (image instanceof MapillaryImage) {
+                mapillaryImageDisplay.hyperlink.setVisible(true);
+                MapillaryImage mapillaryImage = (MapillaryImage) this.image;
+                String title = tr(BASE_TITLE);
+                if (mapillaryImage.getUser() != null)
+                    title += " -- " + mapillaryImage.getUser();
+                if (mapillaryImage.getCapturedAt() != 0)
+                    title += " -- " + mapillaryImage.getDate();
+                titleBar.setTitle(title);
+                if (mode == NORMAL_MODE) {
+                    this.nextButton.setEnabled(true);
+                    this.previousButton.setEnabled(true);
+                    if (mapillaryImage.next() == null)
+                        this.nextButton.setEnabled(false);
+                    if (mapillaryImage.previous() == null)
+                        this.previousButton.setEnabled(false);
+                } else if (mode == SIGN_MODE) {
+                    previousSignButton.setEnabled(true);
+                    nextSignButton.setEnabled(true);
+                    int i = MapillaryData
+                            .getInstance()
+                            .getImages()
+                            .indexOf(
+                                    MapillaryData.getInstance()
+                                            .getSelectedImage());
+                    int first = -1;
+                    int last = -1;
+                    int c = 0;
+                    for (MapillaryAbstractImage img : MapillaryData
+                            .getInstance().getImages()) {
+                        if (img instanceof MapillaryImage)
+                            if (!((MapillaryImage) img).getSigns().isEmpty()) {
+                                if (first == -1)
+                                    first = c;
+                                last = c;
+                            }
+                        c++;
+                    }
+                    if (first >= i)
+                        previousSignButton.setEnabled(false);
+                    if (last <= i)
+                        nextSignButton.setEnabled(false);
+                }
+
+                mapillaryImageDisplay.hyperlink.setURL(mapillaryImage.getKey());
+                // Downloads the thumbnail.
+                this.mapillaryImageDisplay.setImage(null);
+                if (thumbnailCache != null)
+                    thumbnailCache.cancelOutstandingTasks();
+                thumbnailCache = new MapillaryCache(mapillaryImage.getKey(),
+                        MapillaryCache.Type.THUMBNAIL);
+                thumbnailCache.submit(this, false);
+
+                // Downloads the full resolution image.
+                if (imageCache != null)
+                    imageCache.cancelOutstandingTasks();
+                imageCache = new MapillaryCache(mapillaryImage.getKey(),
+                        MapillaryCache.Type.FULL_IMAGE);
+                imageCache.submit(this, false);
+            } else if (image instanceof MapillaryImportedImage) {
+                mapillaryImageDisplay.hyperlink.setVisible(false);
+                this.nextButton.setEnabled(false);
+                this.previousButton.setEnabled(false);
+                MapillaryImportedImage mapillaryImage = (MapillaryImportedImage) this.image;
+                try {
+                    mapillaryImageDisplay.setImage(mapillaryImage.getImage());
+                } catch (IOException e) {
+                    Main.error(e);
+                }
+                mapillaryImageDisplay.hyperlink.setURL(null);
+            }
+        }
+    }
+
+    private void disableAllButtons() {
+        nextButton.setEnabled(false);
+        previousButton.setEnabled(false);
+        blueButton.setEnabled(false);
+        redButton.setEnabled(false);
+        nextSignButton.setEnabled(false);
+        previousSignButton.setEnabled(false);
+        mapillaryImageDisplay.hyperlink.setVisible(false);
+    }
+
+    /**
+     * Sets a new MapillaryImage to be shown.
+     * 
+     * @param image
+     */
+    public synchronized void setImage(MapillaryAbstractImage image) {
+        this.image = image;
+    }
+
+    /**
+     * Returns the MapillaryImage objects which is being shown.
+     * 
+     * @return
+     */
+    public synchronized MapillaryAbstractImage getImage() {
+        return this.image;
+    }
+
+    /**
+     * Action class form the next image button.
+     * 
+     * @author Jorge
+     *
+     */
+    class nextPictureAction extends AbstractAction {
+        public nextPictureAction() {
+            putValue(NAME, tr("Next picture"));
+            putValue(SHORT_DESCRIPTION,
+                    tr("Shows the next picture in the sequence"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                MapillaryData.getInstance().selectNext();
+            }
+        }
+    }
+
+    /**
+     * Action class for the previous image button.
+     * 
+     * @author Jorge
+     *
+     */
+    class previousPictureAction extends AbstractAction {
+        public previousPictureAction() {
+            putValue(NAME, tr("Previous picture"));
+            putValue(SHORT_DESCRIPTION,
+                    tr("Shows the previous picture in the sequence"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                MapillaryData.getInstance().selectPrevious();
+            }
+        }
+    }
+
+    /**
+     * Action class to jump to the image following the red line.
+     * 
+     * @author nokutu
+     *
+     */
+    class redAction extends AbstractAction {
+        public redAction() {
+            putValue(NAME, tr("Jump to red"));
+            putValue(
+                    SHORT_DESCRIPTION,
+                    tr("Jumps to the picture at the other side of the red line"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                MapillaryData.getInstance().setSelectedImage(
+                        MapillaryLayer.RED, true);
+            }
+        }
+    }
+
+    /**
+     * Action class to jump to the image following the blue line.
+     * 
+     * @author nokutu
+     *
+     */
+    class blueAction extends AbstractAction {
+        public blueAction() {
+            putValue(NAME, tr("Jump to blue"));
+            putValue(
+                    SHORT_DESCRIPTION,
+                    tr("Jumps to the picture at the other side of the blue line"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                MapillaryData.getInstance().setSelectedImage(
+                        MapillaryLayer.BLUE, true);
+            }
+        }
+    }
+
+    /**
+     * When the pictures are returned from the cache, they are set in the
+     * {@link MapillaryImageDisplay} object.
+     */
+    @Override
+    public void loadingFinished(CacheEntry data,
+            CacheEntryAttributes attributes, LoadResult result) {
+        if (!SwingUtilities.isEventDispatchThread()) {
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    updateImage();
+                }
+            });
+        } else if (data != null && result == LoadResult.SUCCESS) {
+            try {
+                BufferedImage img = ImageIO.read(new ByteArrayInputStream(data
+                        .getContent()));
+                if (this.mapillaryImageDisplay.getImage() == null)
+                    mapillaryImageDisplay.setImage(img);
+                else if (img.getHeight() > this.mapillaryImageDisplay
+                        .getImage().getHeight()) {
+                    mapillaryImageDisplay.setImage(img);
+                }
+            } catch (IOException e) {
+                Main.error(e);
+            }
+        }
+    }
+
+    /**
+     * Creates the layout of the dialog.
+     * 
+     * @param data
+     *            The content of the dialog
+     * @param buttons
+     *            The buttons where you can click
+     * @param reverse
+     *            {@code true} if the buttons should go at the top;
+     *            {@code false} otherwise.
+     */
+    public void createLayout(Component data, List<SideButton> buttons,
+            boolean reverse) {
+        this.removeAll();
+        JPanel panel = new JPanel();
+        panel.setLayout(new BorderLayout());
+        panel.add(data, BorderLayout.CENTER);
+        if (reverse) {
+            buttonsPanel = new JPanel(new GridLayout(1, 1));
+            if (!buttons.isEmpty() && buttons.get(0) != null) {
+                final JPanel buttonRowPanel = new JPanel(Main.pref.getBoolean(
+                        "dialog.align.left", false) ? new FlowLayout(
+                        FlowLayout.LEFT) : new GridLayout(1, buttons.size()));
+                buttonsPanel.add(buttonRowPanel);
+                for (SideButton button : buttons)
+                    buttonRowPanel.add(button);
+            }
+            panel.add(buttonsPanel, BorderLayout.NORTH);
+            createLayout(panel, true, null);
+        } else
+            createLayout(panel, true, buttons);
+        this.add(titleBar, BorderLayout.NORTH);
+    }
+
+    @Override
+    public void selectedImageChanged(MapillaryAbstractImage oldImage,
+            MapillaryAbstractImage newImage) {
+        setImage(MapillaryData.getInstance().getSelectedImage());
+        updateImage();
+    }
+
+    /**
+     * Action class to jump to the next picture containing a sign.
+     * 
+     * @author nokutu
+     *
+     */
+    class NextSignAction extends AbstractAction {
+        public NextSignAction() {
+            putValue(NAME, tr("Next Sign"));
+            putValue(SHORT_DESCRIPTION,
+                    tr("Jumps to the next picture that contains a sign"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                int i = MapillaryData
+                        .getInstance()
+                        .getImages()
+                        .indexOf(MapillaryData.getInstance().getSelectedImage());
+                for (int j = i + 1; j < MapillaryData.getInstance().getImages()
+                        .size(); j++) {
+                    MapillaryAbstractImage img = MapillaryData.getInstance()
+                            .getImages().get(j);
+                    if (img instanceof MapillaryImage)
+                        if (!((MapillaryImage) img).getSigns().isEmpty()) {
+                            MapillaryData.getInstance().setSelectedImage(img,
+                                    true);
+                            return;
+                        }
+                }
+            }
+        }
+    }
+
+    /**
+     * Action class to jump to the previous picture containing a sign.
+     * 
+     * @author nokutu
+     *
+     */
+    class PreviousSignAction extends AbstractAction {
+        public PreviousSignAction() {
+            putValue(NAME, tr("Previous Sign"));
+            putValue(SHORT_DESCRIPTION,
+                    tr("Jumps to the previous picture that contains a sign"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            if (MapillaryToggleDialog.getInstance().getImage() != null) {
+                int i = MapillaryData
+                        .getInstance()
+                        .getImages()
+                        .indexOf(MapillaryData.getInstance().getSelectedImage());
+                for (int j = i - 1; j >= 0; j--) {
+                    MapillaryAbstractImage img = MapillaryData.getInstance()
+                            .getImages().get(j);
+                    if (img instanceof MapillaryImage)
+                        if (!((MapillaryImage) img).getSigns().isEmpty()) {
+                            MapillaryData.getInstance().setSelectedImage(img,
+                                    true);
+                            return;
+                        }
+                }
+            }
+        }
+    }
 }
