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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryAbstractImage.java	(revision 31328)
@@ -6,4 +6,6 @@
 import java.util.Calendar;
 import java.util.TimeZone;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import org.openstreetmap.josm.Main;
@@ -18,4 +20,6 @@
  */
 public abstract class MapillaryAbstractImage {
+    
+    public static Lock lock = new ReentrantLock();
 
     private long capturedAt;
@@ -147,5 +151,5 @@
         else
             format += "dd/MM/yyyy";
-        if (Main.pref.getBoolean("mapillary.display-hour", true)){
+        if (Main.pref.getBoolean("mapillary.display-hour", true)) {
             if (Main.pref.getBoolean("mapillary.format-24"))
                 format += " - HH:mm:ss (z)";
@@ -177,11 +181,11 @@
         return formatter.format(date);
     }
-    
+
     public long getEpoch(String date, String format) {
-        
+
         SimpleDateFormat formatter = new SimpleDateFormat(format);
         try {
             Date dateTime = (Date) formatter.parse(date);
-            return dateTime.getTime();        
+            return dateTime.getTime();
         } catch (ParseException e) {
             Main.error(e);
@@ -189,5 +193,5 @@
         return currentTime();
     }
-    
+
     private long currentTime() {
         Calendar cal = Calendar.getInstance();
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java	(revision 31328)
@@ -20,315 +20,315 @@
  */
 public class MapillaryData implements ICachedLoaderListener {
-	public volatile static MapillaryData INSTANCE;
-	public static boolean TEST_MODE = false;
-
-	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();
-		fireImagesAdded();
-	}
-
-	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);
-		}
-		fireImagesAdded();
-	}
-
-	/**
-	 * Repaints mapView object.
-	 */
-	public synchronized void dataUpdated() {
-		if (!TEST_MODE)
-			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;
-	}
-
-	private void fireImagesAdded() {
-		if (listeners.isEmpty())
-			return;
-		for (MapillaryDataListener lis : listeners)
-			lis.imagesAdded();
-	}
-
-	/**
-	 * If the selected MapillaryImage is part of a MapillarySequence then the
-	 * following visible 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;
-			if (selectedImage instanceof MapillaryImage
-					&& ((MapillaryImage) selectedImage).getSequence() != null) {
-				MapillaryImage tempImage = (MapillaryImage) selectedImage;
-				while (tempImage.next() != null) {
-					tempImage = tempImage.next();
-					if (tempImage.isVisible()) {
-						setSelectedImage(tempImage, Main.pref.getBoolean(
-								"mapillary.move-to-picture", true));
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * If the selected MapillaryImage is part of a MapillarySequence then the
-	 * previous visible 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();
-			if (selectedImage instanceof MapillaryImage
-					&& ((MapillaryImage) selectedImage).getSequence() != null) {
-				MapillaryImage tempImage = (MapillaryImage) selectedImage;
-				while (tempImage.previous() != null) {
-					tempImage = tempImage.previous();
-					if (tempImage.isVisible()) {
-						setSelectedImage(tempImage, Main.pref.getBoolean(
-								"mapillary.move-to-picture", true));
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * 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 whether 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
-	}
-
-	/**
-	 * Returns the amount of images contained by this object.
-	 * 
-	 * @return
-	 */
-	public int size() {
-		return images.size();
-	}
+    public volatile static MapillaryData INSTANCE;
+    public static boolean TEST_MODE = false;
+
+    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();
+        fireImagesAdded();
+    }
+
+    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);
+        }
+        fireImagesAdded();
+    }
+
+    /**
+     * Repaints mapView object.
+     */
+    public synchronized void dataUpdated() {
+        if (!TEST_MODE)
+            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;
+    }
+
+    private void fireImagesAdded() {
+        if (listeners.isEmpty())
+            return;
+        for (MapillaryDataListener lis : listeners)
+            lis.imagesAdded();
+    }
+
+    /**
+     * If the selected MapillaryImage is part of a MapillarySequence then the
+     * following visible 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;
+            if (selectedImage instanceof MapillaryImage
+                    && ((MapillaryImage) selectedImage).getSequence() != null) {
+                MapillaryImage tempImage = (MapillaryImage) selectedImage;
+                while (tempImage.next() != null) {
+                    tempImage = tempImage.next();
+                    if (tempImage.isVisible()) {
+                        setSelectedImage(tempImage, Main.pref.getBoolean(
+                                "mapillary.move-to-picture", true));
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * If the selected MapillaryImage is part of a MapillarySequence then the
+     * previous visible 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();
+            if (selectedImage instanceof MapillaryImage
+                    && ((MapillaryImage) selectedImage).getSequence() != null) {
+                MapillaryImage tempImage = (MapillaryImage) selectedImage;
+                while (tempImage.previous() != null) {
+                    tempImage = tempImage.previous();
+                    if (tempImage.isVisible()) {
+                        setSelectedImage(tempImage, Main.pref.getBoolean(
+                                "mapillary.move-to-picture", true));
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 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 whether 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
+    }
+
+    /**
+     * Returns the amount of images contained by this object.
+     * 
+     * @return
+     */
+    public int size() {
+        return images.size();
+    }
 }
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDataListener.java	(revision 31328)
@@ -2,7 +2,7 @@
 
 public interface MapillaryDataListener {
-    
+
     public void imagesAdded();
-    
+
     /**
      * Fired when the selected image is changed by something different from
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java	(revision 31328)
@@ -12,130 +12,134 @@
  */
 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;
 
-	/** Epoch time when the image was taken. */
-	/** The user that made the image */
-	private String user;
-	/** Set of traffic signs in the image */
-	private List<String> signs;
-	private String location;
+    /** Epoch time when the image was taken. */
+    /** 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;
-	}
+    /**
+     * Returns the unique identifier of the object.
+     * 
+     * @return A String containing the unique identifier of the object.
+     */
+    public String getKey() {
+        return this.key;
+    }
 
-	/**
-	 * Adds a new sign to the set of signs.
-	 * 
-	 * @param sign
-	 */
-	public void addSign(String sign) {
-		signs.add(sign);
-	}
+    /**
+     * Adds a new sign to the set of signs.
+     * 
+     * @param sign
+     */
+    public void addSign(String sign) {
+        signs.add(sign);
+    }
 
-	public List<String> getSigns() {
-		return signs;
-	}
+    public List<String> getSigns() {
+        return signs;
+    }
 
-	public void setUser(String user) {
-		this.user = user;
-	}
+    public void setUser(String user) {
+        this.user = user;
+    }
 
-	public String getUser() {
-		return user;
-	}
+    public String getUser() {
+        return user;
+    }
 
-	/**
-	 * Sets the MapillarySequence object which contains the MapillaryImage.
-	 * 
-	 * @param sequence
-	 *            The MapillarySequence that contains the MapillaryImage.
-	 */
-	public void setSequence(MapillarySequence sequence) {
-		this.sequence = sequence;
-	}
+    /**
+     * Sets the MapillarySequence object which contains the MapillaryImage.
+     * 
+     * @param sequence
+     *            The MapillarySequence that contains the MapillaryImage.
+     */
+    public void setSequence(MapillarySequence sequence) {
+        this.sequence = sequence;
+    }
 
-	/**
-	 * Returns the sequence which contains this image.
-	 * 
-	 * @return The MapillarySequence object that contains this MapillaryImage.
-	 */
-	public MapillarySequence getSequence() {
-		return this.sequence;
-	}
+    /**
+     * Returns the sequence which contains this image.
+     * 
+     * @return The MapillarySequence object that contains this MapillaryImage.
+     */
+    public MapillarySequence getSequence() {
+        return this.sequence;
+    }
 
-	public String toString() {
-		return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
-				+ this.latLon.lon() + ";ca=" + this.ca + "]";
-	}
+    public String toString() {
+        return "Image[key=" + this.key + ";lat=" + this.latLon.lat() + ";lon="
+                + this.latLon.lon() + ";ca=" + this.ca + "]";
+    }
 
-	/**
-	 * 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);
-	}
+    /**
+     * 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() {
+        synchronized (lock) {
+            if (this.getSequence() == null)
+                return null;
+            return this.getSequence().next(this);
+        }
+    }
 
-	/**
-	 * 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);
-	}
+    /**
+     * 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() {
+        synchronized (lock) {
+            if (this.getSequence() == null)
+                return null;
+            return this.getSequence().previous(this);
+        }
+    }
 
-	@Override
-	public boolean equals(Object object) {
-		if (object instanceof MapillaryImage)
-			return this.key.equals(((MapillaryImage) object).getKey());
-		return false;
-	}
+    @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();
-	}
+    @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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImportedImage.java	(revision 31328)
@@ -16,7 +16,7 @@
     protected File file;
     public final long datetimeOriginal;
-    
+
     public MapillaryImportedImage(double lat, double lon, double ca, File file) {
-    	this(lat, lon, ca, file, currentDate());
+        this(lat, lon, ca, file, currentDate());
     }
 
@@ -25,5 +25,6 @@
         super(lat, lon, ca);
         this.file = file;
-        this.datetimeOriginal = getEpoch(datetimeOriginal, "yyyy:MM:dd hh:mm:ss");
+        this.datetimeOriginal = getEpoch(datetimeOriginal,
+                "yyyy:MM:dd hh:mm:ss");
     }
 
@@ -53,5 +54,5 @@
         return this.file.hashCode();
     }
-    
+
     private static String currentDate() {
         Calendar cal = Calendar.getInstance();
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31328)
@@ -59,521 +59,520 @@
 
 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;
-
-	public final MapillaryData data = MapillaryData.getInstance();
-
-	public ArrayList<Bounds> bounds;
-
-	private MouseAdapter mouseAdapter;
-
-	private int highlightPointRadius = Main.pref.getInteger(
-			"mappaint.highlight.radius", 7);
-	private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
-			4);
-
-	private volatile TexturePaint hatched;
-
-	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);
-			if (Main.map.mapView.getEditLayer() != null)
-				Main.map.mapView.getEditLayer().data.addDataSetListener(this);
-		}
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
-		if (!MapillaryToggleDialog.getInstance().isShowing())
-			MapillaryToggleDialog.getInstance().getButton().doClick();
-		createHatchTexture();
-		data.dataUpdated();
-	}
-
-	private 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 data;
-	}
-
-	/**
-	 * Method invoked when the layer is destroyed.
-	 */
-	@Override
-	public void destroy() {
-		MapillaryToggleDialog.getInstance().mapillaryImageDisplay
-				.setImage(null);
-		MapillaryToggleDialog.getInstance().updateImage();
-		data.getImages().clear();
-		MapillaryLayer.INSTANCE = null;
-		MapillaryData.INSTANCE = null;
-		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_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 : data.getImages())
-			if (image.isModified())
-				return true;
-		return false;
-	}
-
-	@Override
-	public void setVisible(boolean visible) {
-		super.setVisible(visible);
-		for (MapillaryAbstractImage img : data.getImages())
-			img.setVisible(visible);
-		MapillaryFilterDialog.getInstance().refresh();
-	}
-
-	/**
-	 * Replies background color for downloaded areas.
-	 * 
-	 * @return background color for downloaded areas. Black by default
-	 */
-	private Color getBackgroundColor() {
-		return Main.pref.getColor(marktr("background"), Color.BLACK);
-	}
-
-	/**
-	 * Replies background color for non-downloaded areas.
-	 * 
-	 * @return background color for non-downloaded areas. Yellow by default
-	 */
-	private Color getOutsideColor() {
-		return Main.pref.getColor(marktr("outside downloaded area"),
-				Color.YELLOW);
-	}
-
-	/**
-	 * Initialize the hatch pattern used to paint the non-downloaded area
-	 */
-	private void createHatchTexture() {
-		BufferedImage bi = new BufferedImage(15, 15,
-				BufferedImage.TYPE_INT_ARGB);
-		Graphics2D big = bi.createGraphics();
-		big.setColor(getBackgroundColor());
-		Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-				0.3f);
-		big.setComposite(comp);
-		big.fillRect(0, 0, 15, 15);
-		big.setColor(getOutsideColor());
-		big.drawLine(0, 15, 15, 0);
-		Rectangle r = new Rectangle(0, 0, 15, 15);
-		hatched = new TexturePaint(bi, r);
-	}
-
-	/**
-	 * Paints the database in the map.
-	 */
-	@Override
-	public synchronized void paint(Graphics2D g, MapView mv, Bounds box) {
-		if (Main.map.mapView.getActiveLayer() == this) {
-			Rectangle b = mv.getBounds();
-			// on some platforms viewport bounds seem to be offset from the
-			// left,
-			// over-grow it just to be sure
-			b.grow(100, 100);
-			Area a = new Area(b);
-			// now successively subtract downloaded areas
-			for (Bounds bounds : this.bounds) {
-				Point p1 = mv.getPoint(bounds.getMin());
-				Point p2 = mv.getPoint(bounds.getMax());
-				Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(
-						p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y
-						- p1.y));
-				a.subtract(new Area(r));
-			}
-			// paint remainder
-			g.setPaint(hatched);
-			g.fill(a);
-		}
-
-		// Draw colored lines
-		MapillaryLayer.BLUE = null;
-		MapillaryLayer.RED = null;
-		MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
-		MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
-
-		// Sets blue and red lines and enables/disables the buttons
-		if (data.getSelectedImage() != null) {
-			MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
-			Point selected = mv.getPoint(data.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 : data.getImages()) {
-			if (!imageAbs.isVisible())
-				continue;
-			Point p = mv.getPoint(imageAbs.getLatLon());
-			if (imageAbs instanceof MapillaryImage) {
-				MapillaryImage image = (MapillaryImage) imageAbs;
-				Point nextp = null;
-				// Draw sequence line
-				if (image.getSequence() != null) {
-					MapillaryImage tempImage = image;
-					while (tempImage.next() != null) {
-						tempImage = tempImage.next();
-						if (tempImage.isVisible()) {
-							nextp = mv.getPoint(tempImage.getLatLon());
-							break;
-						}
-					}
-					if (nextp != null)
-						g.drawLine(p.x, p.y, nextp.x, nextp.y);
-				}
-
-				ImageIcon icon;
-				if (!data.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 (!data.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 (data.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()]);
-	}
-
-	/**
-	 * Returns the 2 closest images belonging to a different sequence.
-	 * 
-	 * @return
-	 */
-	private MapillaryImage[] getClosestImagesFromDifferentSequences() {
-		if (!(data.getSelectedImage() instanceof MapillaryImage))
-			return new MapillaryImage[2];
-		MapillaryImage selected = (MapillaryImage) data.getSelectedImage();
-		MapillaryImage[] ret = new MapillaryImage[2];
-		double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
-				SEQUENCE_MAX_JUMP_DISTANCE };
-		LatLon selectedCoords = data.getSelectedImage().getLatLon();
-		for (MapillaryAbstractImage imagePrev : data.getImages()) {
-			if (!(imagePrev instanceof MapillaryImage))
-				continue;
-			if (!imagePrev.isVisible())
-				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(data, false);
-		if (ret[1] != null)
-			new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
-					.submit(data, 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(data.size());
-		sb.append("\n");
-		return sb.toString();
-	}
-
-	@Override
-	public String getToolTipText() {
-		return data.size() + " " + tr("images");
-	}
-
-	// EditDataLayerChanged
-	@Override
-	public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
-		if (oldLayer == null && newLayer != null) {
-			newLayer.data.addDataSetListener(this);
-
-		} else if (oldLayer != null && newLayer == null) {
-			oldLayer.data.removeDataSetListener(this);
-		}
-	}
-
-	/**
-	 * 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 (data.size() > 0)
-				Main.map.statusLine.setHelpText(tr("Total images: {0}",
-						data.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;
+
+    public final MapillaryData data = MapillaryData.getInstance();
+
+    public ArrayList<Bounds> bounds;
+
+    private MouseAdapter mouseAdapter;
+
+    private int highlightPointRadius = Main.pref.getInteger(
+            "mappaint.highlight.radius", 7);
+    private int highlightStep = Main.pref.getInteger("mappaint.highlight.step",
+            4);
+
+    private volatile TexturePaint hatched;
+
+    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);
+            if (Main.map.mapView.getEditLayer() != null)
+                Main.map.mapView.getEditLayer().data.addDataSetListener(this);
+        }
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, true);
+        if (!MapillaryToggleDialog.getInstance().isShowing())
+            MapillaryToggleDialog.getInstance().getButton().doClick();
+        createHatchTexture();
+        data.dataUpdated();
+    }
+
+    private 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 data;
+    }
+
+    /**
+     * Method invoked when the layer is destroyed.
+     */
+    @Override
+    public void destroy() {
+        MapillaryToggleDialog.getInstance().setImage(null);
+        MapillaryToggleDialog.getInstance().updateImage();
+        data.getImages().clear();
+        MapillaryLayer.INSTANCE = null;
+        MapillaryData.INSTANCE = null;
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_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 : data.getImages())
+            if (image.isModified())
+                return true;
+        return false;
+    }
+
+    @Override
+    public void setVisible(boolean visible) {
+        super.setVisible(visible);
+        for (MapillaryAbstractImage img : data.getImages())
+            img.setVisible(visible);
+        MapillaryFilterDialog.getInstance().refresh();
+    }
+
+    /**
+     * Replies background color for downloaded areas.
+     * 
+     * @return background color for downloaded areas. Black by default
+     */
+    private Color getBackgroundColor() {
+        return Main.pref.getColor(marktr("background"), Color.BLACK);
+    }
+
+    /**
+     * Replies background color for non-downloaded areas.
+     * 
+     * @return background color for non-downloaded areas. Yellow by default
+     */
+    private Color getOutsideColor() {
+        return Main.pref.getColor(marktr("outside downloaded area"),
+                Color.YELLOW);
+    }
+
+    /**
+     * Initialize the hatch pattern used to paint the non-downloaded area
+     */
+    private void createHatchTexture() {
+        BufferedImage bi = new BufferedImage(15, 15,
+                BufferedImage.TYPE_INT_ARGB);
+        Graphics2D big = bi.createGraphics();
+        big.setColor(getBackgroundColor());
+        Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+                0.3f);
+        big.setComposite(comp);
+        big.fillRect(0, 0, 15, 15);
+        big.setColor(getOutsideColor());
+        big.drawLine(0, 15, 15, 0);
+        Rectangle r = new Rectangle(0, 0, 15, 15);
+        hatched = new TexturePaint(bi, r);
+    }
+
+    /**
+     * Paints the database in the map.
+     */
+    @Override
+    public synchronized void paint(Graphics2D g, MapView mv, Bounds box) {
+        if (Main.map.mapView.getActiveLayer() == this) {
+            Rectangle b = mv.getBounds();
+            // on some platforms viewport bounds seem to be offset from the
+            // left,
+            // over-grow it just to be sure
+            b.grow(100, 100);
+            Area a = new Area(b);
+            // now successively subtract downloaded areas
+            for (Bounds bounds : this.bounds) {
+                Point p1 = mv.getPoint(bounds.getMin());
+                Point p2 = mv.getPoint(bounds.getMax());
+                Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(
+                        p1.y, p2.y), Math.abs(p2.x - p1.x), Math.abs(p2.y
+                        - p1.y));
+                a.subtract(new Area(r));
+            }
+            // paint remainder
+            g.setPaint(hatched);
+            g.fill(a);
+        }
+
+        // Draw colored lines
+        MapillaryLayer.BLUE = null;
+        MapillaryLayer.RED = null;
+        MapillaryToggleDialog.getInstance().blueButton.setEnabled(false);
+        MapillaryToggleDialog.getInstance().redButton.setEnabled(false);
+
+        // Sets blue and red lines and enables/disables the buttons
+        if (data.getSelectedImage() != null) {
+            MapillaryImage[] closestImages = getClosestImagesFromDifferentSequences();
+            Point selected = mv.getPoint(data.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 : data.getImages()) {
+            if (!imageAbs.isVisible())
+                continue;
+            Point p = mv.getPoint(imageAbs.getLatLon());
+            if (imageAbs instanceof MapillaryImage) {
+                MapillaryImage image = (MapillaryImage) imageAbs;
+                Point nextp = null;
+                // Draw sequence line
+                if (image.getSequence() != null) {
+                    MapillaryImage tempImage = image.next();
+                    while (tempImage != null) {
+                        if (tempImage.isVisible()) {
+                            nextp = mv.getPoint(tempImage.getLatLon());
+                            break;
+                        }
+                        tempImage = tempImage.next();
+                    }
+                    if (nextp != null)
+                        g.drawLine(p.x, p.y, nextp.x, nextp.y);
+                }
+
+                ImageIcon icon;
+                if (!data.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 (!data.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 (data.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()]);
+    }
+
+    /**
+     * Returns the 2 closest images belonging to a different sequence.
+     * 
+     * @return
+     */
+    private MapillaryImage[] getClosestImagesFromDifferentSequences() {
+        if (!(data.getSelectedImage() instanceof MapillaryImage))
+            return new MapillaryImage[2];
+        MapillaryImage selected = (MapillaryImage) data.getSelectedImage();
+        MapillaryImage[] ret = new MapillaryImage[2];
+        double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
+                SEQUENCE_MAX_JUMP_DISTANCE };
+        LatLon selectedCoords = data.getSelectedImage().getLatLon();
+        for (MapillaryAbstractImage imagePrev : data.getImages()) {
+            if (!(imagePrev instanceof MapillaryImage))
+                continue;
+            if (!imagePrev.isVisible())
+                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(data, false);
+        if (ret[1] != null)
+            new MapillaryCache(ret[1].getKey(), MapillaryCache.Type.THUMBNAIL)
+                    .submit(data, 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(data.size());
+        sb.append("\n");
+        return sb.toString();
+    }
+
+    @Override
+    public String getToolTipText() {
+        return data.size() + " " + tr("images");
+    }
+
+    // EditDataLayerChanged
+    @Override
+    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+        if (oldLayer == null && newLayer != null) {
+            newLayer.data.addDataSetListener(this);
+
+        } else if (oldLayer != null && newLayer == null) {
+            oldLayer.data.removeDataSetListener(this);
+        }
+    }
+
+    /**
+     * 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 (data.size() > 0)
+                Main.map.statusLine.setHelpText(tr("Total images: {0}",
+                        data.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/MapillaryPlugin.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31328)
@@ -33,106 +33,106 @@
 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 MapillaryZoomAction zoomAction;
-	private final MapillaryDownloadViewAction downloadViewAction;
+    private final MapillaryDownloadAction downloadAction;
+    private final MapillaryExportAction exportAction;
+    private final MapillaryImportAction importAction;
+    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 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 ZOOM_MENU;
+    public static JMenuItem DOWNLOAD_VIEW_MENU;
 
-	public MapillaryPlugin(PluginInformation info) {
-		super(info);
-		downloadAction = new MapillaryDownloadAction();
-		exportAction = new MapillaryExportAction();
-		importAction = new MapillaryImportAction();
-		zoomAction = new MapillaryZoomAction();
-		downloadViewAction = new MapillaryDownloadViewAction();
+    public MapillaryPlugin(PluginInformation info) {
+        super(info);
+        downloadAction = new MapillaryDownloadAction();
+        exportAction = new MapillaryExportAction();
+        importAction = new MapillaryImportAction();
+        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);
-		ZOOM_MENU = MainMenu
-				.add(Main.main.menu.viewMenu, zoomAction, false, 15);
-		DOWNLOAD_VIEW_MENU = MainMenu.add(Main.main.menu.fileMenu,
-				downloadViewAction, false, 14);
+        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);
+        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);
-		ZOOM_MENU.setEnabled(false);
-		DOWNLOAD_VIEW_MENU.setEnabled(false);
+        EXPORT_MENU.setEnabled(false);
+        DOWNLOAD_MENU.setEnabled(false);
+        IMPORT_MENU.setEnabled(false);
+        ZOOM_MENU.setEnabled(false);
+        DOWNLOAD_VIEW_MENU.setEnabled(false);
 
-		MapView.addEditLayerChangeListener(this);
-		try {
-			CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
-					this.getPluginDir() + "/cache/");
-		} catch (IOException e) {
-			Main.error(e);
-		}
-	}
+        MapView.addEditLayerChangeListener(this);
+        try {
+            CACHE = JCSCacheManager.getCache("mapillary", 10, 10000,
+                    this.getPluginDir() + "/cache/");
+        } catch (IOException e) {
+            Main.error(e);
+        }
+    }
 
-	/**
-	 * 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
-			Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
-			Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(),
-					false);
-			Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
-			setMenuEnabled(DOWNLOAD_MENU, true);
-			if (Main.pref.getBoolean("mapillary.download-manually"))
-				setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
-			setMenuEnabled(IMPORT_MENU, true);
-		}
-		if (oldFrame != null && newFrame == null) { // map frame destroyed
-			MapillaryToggleDialog.destroyInstance();
-			MapillaryHistoryDialog.destroyInstance();
-			MapillaryFilterDialog.destroyInstance();
-			setMenuEnabled(DOWNLOAD_MENU, false);
-			setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
-			setMenuEnabled(IMPORT_MENU, 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
+            Main.map.addToggleDialog(MapillaryToggleDialog.getInstance(), false);
+            Main.map.addToggleDialog(MapillaryHistoryDialog.getInstance(),
+                    false);
+            Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
+            setMenuEnabled(DOWNLOAD_MENU, true);
+            if (Main.pref.getBoolean("mapillary.download-manually"))
+                setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
+            setMenuEnabled(IMPORT_MENU, true);
+        }
+        if (oldFrame != null && newFrame == null) { // map frame destroyed
+            MapillaryToggleDialog.destroyInstance();
+            MapillaryHistoryDialog.destroyInstance();
+            MapillaryFilterDialog.destroyInstance();
+            setMenuEnabled(DOWNLOAD_MENU, false);
+            setMenuEnabled(DOWNLOAD_VIEW_MENU, false);
+            setMenuEnabled(IMPORT_MENU, false);
+        }
+    }
 
-	public static void setMenuEnabled(JMenuItem menu, boolean value) {
-		menu.setEnabled(value);
-		menu.getAction().setEnabled(value);
-	}
+    public static void setMenuEnabled(JMenuItem menu, boolean value) {
+        menu.setEnabled(value);
+        menu.getAction().setEnabled(value);
+    }
 
-	@Override
-	public PreferenceSetting getPreferenceSetting() {
-		return new MapillaryPreferenceSetting();
-	}
+    @Override
+    public PreferenceSetting getPreferenceSetting() {
+        return new MapillaryPreferenceSetting();
+    }
 
-	@Override
-	public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
-		if (oldLayer == null && newLayer != null) {
-		} else if (oldLayer != null && newLayer == null) {
-		}
-	}
+    @Override
+    public void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
+        if (oldLayer == null && newLayer != null) {
+        } else if (oldLayer != null && newLayer == null) {
+        }
+    }
 }
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadAction.java	(revision 31328)
@@ -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_COMMA, Shortcut.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_COMMA, Shortcut.SHIFT), false,
+                "mapillaryDownload", false);
+        this.setEnabled(false);
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		if (MapillaryLayer.INSTANCE == null) {
-			if (Main.map.mapView.getEditLayer() != 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) {
+            if (Main.map.mapView.getEditLayer() != 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/MapillaryImportAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryImportAction.java	(revision 31328)
@@ -70,5 +70,5 @@
 
                 } else {
-                	MapillaryLayer.getInstance();
+                    MapillaryLayer.getInstance();
                     if (file.getPath().substring(file.getPath().length() - 4)
                             .equals(".jpg")
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/cache/MapillaryCache.java	(revision 31328)
@@ -11,59 +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/downloads/MapillaryDownloader.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31328)
@@ -18,58 +18,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 Executor EXECUTOR = Executors.newSingleThreadExecutor();
+    public final static String BASE_URL = "https://a.mapillary.com/v2/";
+    public final static String CLIENT_ID = "NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1YTA2NmNlODhlNWMwOTBm";
+    public final static Executor EXECUTOR = Executors.newSingleThreadExecutor();
 
-	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);
+    /**
+     * 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);
 
-		try {
-			Main.info("GET " + url2 + " (Mapillary plugin)");
-			EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1, url2,
-					url3, MapillaryLayer.getInstance()));
-		} catch (Exception e) {
-			Main.error(e);
-		}
-	}
+        try {
+            Main.info("GET " + url2 + " (Mapillary plugin)");
+            EXECUTOR.execute(new MapillarySquareDownloadManagerThread(url1,
+                    url2, url3, MapillaryLayer.getInstance()));
+        } catch (Exception e) {
+            Main.error(e);
+        }
+    }
 
-	public void getImages(Bounds bounds) {
-		getImages(bounds.getMin(), bounds.getMax());
-	}
+    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;
-	}
+    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/MapillaryExportWriterThread.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryExportWriterThread.java	(revision 31328)
@@ -87,5 +87,6 @@
                     exifDirectory.add(
                             ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
-                            ((MapillaryImportedImage) mimg).getDate("yyyy/MM/dd hh:mm:ss"));
+                            ((MapillaryImportedImage) mimg)
+                                    .getDate("yyyy/MM/dd hh:mm:ss"));
                 } else if (mimg instanceof MapillaryImage)
                     exifDirectory.add(
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryImageInfoDownloaderThread.java	(revision 31328)
@@ -25,44 +25,44 @@
  */
 public class MapillaryImageInfoDownloaderThread implements Runnable {
-	private final String url;
-	private final ExecutorService ex;
-	private final MapillaryLayer layer;
+    private final String url;
+    private final ExecutorService ex;
+    private final MapillaryLayer layer;
 
-	public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url,
-			MapillaryLayer layer) {
-		this.ex = ex;
-		this.url = url;
-		this.layer = layer;
-	}
+    public MapillaryImageInfoDownloaderThread(ExecutorService ex, String url,
+            MapillaryLayer layer) {
+        this.ex = ex;
+        this.url = url;
+        this.layer = layer;
+    }
 
-	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 : layer.data.getImages()) {
-					if (image instanceof MapillaryImage) {
-						if (((MapillaryImage) image).getKey().equals(key)
-								&& ((MapillaryImage) image).getUser() == null) {
-							((MapillaryImage) image).setUser(data
-									.getString("user"));
-							((MapillaryImage) image).setCapturedAt(data
-									.getJsonNumber("captured_at").longValue());
-						}
-					}
-				}
-			}
-		} 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 : layer.data.getImages()) {
+                    if (image instanceof MapillaryImage) {
+                        if (((MapillaryImage) image).getKey().equals(key)
+                                && ((MapillaryImage) image).getUser() == null) {
+                            ((MapillaryImage) image).setUser(data
+                                    .getString("user"));
+                            ((MapillaryImage) image).setCapturedAt(data
+                                    .getJsonNumber("captured_at").longValue());
+                        }
+                    }
+                }
+            }
+        } 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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java	(revision 31328)
@@ -90,6 +90,8 @@
 
                 boolean imagesAdded = false;
+                MapillaryImage.lock.lock();
                 for (MapillaryImage img : finalImages) {
                     if (layer.data.getImages().contains(img)) {
+                        sequence.add(img);
                         ((MapillaryImage) layer.data.getImages().get(
                                 layer.data.getImages().indexOf(img)))
@@ -99,5 +101,4 @@
                                 (MapillaryImage) layer.data.getImages().get(
                                         layer.data.getImages().indexOf(img)));
-                        sequence.add(img);
                     } else {
                         img.setSequence(sequence);
@@ -106,4 +107,5 @@
                     }
                 }
+                MapillaryImage.lock.unlock();
                 manager.imagesAdded = imagesAdded;
                 layer.data
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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySignDownloaderThread.java	(revision 31328)
@@ -19,67 +19,68 @@
 public class MapillarySignDownloaderThread implements Runnable {
 
-	private final String url;
-	private final ExecutorService ex;
-	private final MapillaryLayer layer;
+    private final String url;
+    private final ExecutorService ex;
+    private final MapillaryLayer layer;
 
-	public MapillarySignDownloaderThread(ExecutorService ex, String url,
-			MapillaryLayer layer) {
-		this.ex = ex;
-		this.url = url;
-		this.layer = layer;
-	}
+    public MapillarySignDownloaderThread(ExecutorService ex, String url,
+            MapillaryLayer layer) {
+        this.ex = ex;
+        this.url = url;
+        this.layer = layer;
+    }
 
-	@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 : layer.data
-									.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 : layer.data
+                                    .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 : layer.data.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 : layer.data
+                                .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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java	(revision 31328)
@@ -14,6 +14,6 @@
 /**
  * This Class is needed to create an indeterminate amount of downloads, because
- * the Mapillary API has a paramameter called page which is needed when the amount of
- * requested images is quite big.
+ * the Mapillary API has a parameter called page which is needed when the
+ * amount of requested images is quite big.
  * 
  * @author nokutu
@@ -23,84 +23,84 @@
 public class MapillarySquareDownloadManagerThread implements Runnable {
 
-	private final String urlImages;
-	private final String urlSequences;
-	private final String urlSigns;
-	private final MapillaryLayer layer;
-	public boolean imagesAdded = false;
-	
-	public MapillarySquareDownloadManagerThread(String urlImages,
-			String urlSequences, String urlSigns, MapillaryLayer layer) {
-		this.urlImages = urlImages;
-		this.urlSequences = urlSequences;
-		this.urlSigns = urlSigns;
-		this.layer = layer;
-	}
+    private final String urlImages;
+    private final String urlSequences;
+    private final String urlSigns;
+    private final MapillaryLayer layer;
+    public boolean imagesAdded = false;
 
-	public void run() {
-		Main.map.statusLine.setHelpText("Downloading images from Mapillary");
-		try {
-			downloadSequences();
-			if (imagesAdded) {
-				Main.map.statusLine
-						.setHelpText("Downloading image's information");
-				completeImages();
-				MapillaryToggleDialog.getInstance().updateTitle();
-				Main.map.statusLine.setHelpText("Downloading signs");
-				downloadSigns();
-			}
-		} catch (InterruptedException e) {
-			Main.error(e);
-		}
-		if (layer.data.getImages().size() > 0)
-			Main.map.statusLine.setHelpText(tr("Total images: ")
-					+ layer.data.getImages().size());
-		else
-			Main.map.statusLine.setHelpText(tr("No images found"));
-		layer.data.dataUpdated();
-		MapillaryFilterDialog.getInstance().refresh();
-		MapillaryToggleDialog.getInstance().updateImage();
-	}
+    public MapillarySquareDownloadManagerThread(String urlImages,
+            String urlSequences, String urlSigns, MapillaryLayer layer) {
+        this.urlImages = urlImages;
+        this.urlSequences = urlSequences;
+        this.urlSigns = urlSigns;
+        this.layer = layer;
+    }
 
-	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", layer, this));
-			while (ex.getQueue().remainingCapacity() == 0)
-				Thread.sleep(100);
-			page++;
-		}
-		ex.awaitTermination(15, TimeUnit.SECONDS);
-		layer.data.dataUpdated();
-	}
+    public void run() {
+        Main.map.statusLine.setHelpText("Downloading images from Mapillary");
+        try {
+            downloadSequences();
+            if (imagesAdded) {
+                Main.map.statusLine
+                        .setHelpText("Downloading image's information");
+                completeImages();
+                MapillaryToggleDialog.getInstance().updateTitle();
+                Main.map.statusLine.setHelpText("Downloading signs");
+                downloadSigns();
+            }
+        } catch (InterruptedException e) {
+            Main.error(e);
+        }
+        if (layer.data.getImages().size() > 0)
+            Main.map.statusLine.setHelpText(tr("Total images: ")
+                    + layer.data.getImages().size());
+        else
+            Main.map.statusLine.setHelpText(tr("No images found"));
+        layer.data.dataUpdated();
+        MapillaryFilterDialog.getInstance().refresh();
+        MapillaryToggleDialog.getInstance().updateImage();
+    }
 
-	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", layer));
-			while (ex.getQueue().remainingCapacity() == 0)
-				Thread.sleep(100);
-			page++;
-		}
-		ex.awaitTermination(15, TimeUnit.SECONDS);
-	}
+    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", layer, this));
+            while (ex.getQueue().remainingCapacity() == 0)
+                Thread.sleep(100);
+            page++;
+        }
+        ex.awaitTermination(15, TimeUnit.SECONDS);
+        layer.data.dataUpdated();
+    }
 
-	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", layer));
-			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", layer));
+            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", layer));
+            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/MapillaryFilterChooseSigns.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterChooseSigns.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterChooseSigns.java	(revision 31328)
@@ -14,149 +14,149 @@
 
 public class MapillaryFilterChooseSigns extends JPanel implements
-		ActionListener {
+        ActionListener {
 
-	public final JCheckBox maxspeed = new JCheckBox();
-	public final JCheckBox stop = new JCheckBox();
-	public final JCheckBox giveWay = new JCheckBox();
-	public final JCheckBox roundabout = new JCheckBox();
-	public final JCheckBox access = new JCheckBox();
-	public final JCheckBox intersection = new JCheckBox();
-	public final JCheckBox direction = new JCheckBox();
-	public final JCheckBox uneven = new JCheckBox();
-	public final JCheckBox noParking = new JCheckBox();
-	public final JCheckBox noOvertaking = new JCheckBox();
-	public final JCheckBox crossing = new JCheckBox();
-	public final JCheckBox noTurn = new JCheckBox();
+    public final JCheckBox maxspeed = new JCheckBox();
+    public final JCheckBox stop = new JCheckBox();
+    public final JCheckBox giveWay = new JCheckBox();
+    public final JCheckBox roundabout = new JCheckBox();
+    public final JCheckBox access = new JCheckBox();
+    public final JCheckBox intersection = new JCheckBox();
+    public final JCheckBox direction = new JCheckBox();
+    public final JCheckBox uneven = new JCheckBox();
+    public final JCheckBox noParking = new JCheckBox();
+    public final JCheckBox noOvertaking = new JCheckBox();
+    public final JCheckBox crossing = new JCheckBox();
+    public final JCheckBox noTurn = new JCheckBox();
 
-	private static MapillaryFilterChooseSigns INSTANCE;
+    private static MapillaryFilterChooseSigns INSTANCE;
 
-	public MapillaryFilterChooseSigns() {
-		maxspeed.setSelected(true);
-		stop.setSelected(true);
-		giveWay.setSelected(true);
-		roundabout.setSelected(true);
-		access.setSelected(true);
-		intersection.setSelected(true);
-		direction.setSelected(true);
-		uneven.setSelected(true);
-		noParking.setSelected(true);
-		noOvertaking.setSelected(true);
-		crossing.setSelected(true);
-		noTurn.setSelected(true);
+    public MapillaryFilterChooseSigns() {
+        maxspeed.setSelected(true);
+        stop.setSelected(true);
+        giveWay.setSelected(true);
+        roundabout.setSelected(true);
+        access.setSelected(true);
+        intersection.setSelected(true);
+        direction.setSelected(true);
+        uneven.setSelected(true);
+        noParking.setSelected(true);
+        noOvertaking.setSelected(true);
+        crossing.setSelected(true);
+        noTurn.setSelected(true);
 
-		// Max speed sign
-		JPanel maxspeedPanel = new JPanel();
-		JLabel maxspeedLabel = new JLabel(tr("Speed limit"));
-		maxspeedLabel.setIcon(new ImageProvider("signs/speed.png").get());
-		maxspeedPanel.add(maxspeedLabel);
-		maxspeedPanel.add(maxspeed);
-		this.add(maxspeedPanel);
+        // Max speed sign
+        JPanel maxspeedPanel = new JPanel();
+        JLabel maxspeedLabel = new JLabel(tr("Speed limit"));
+        maxspeedLabel.setIcon(new ImageProvider("signs/speed.png").get());
+        maxspeedPanel.add(maxspeedLabel);
+        maxspeedPanel.add(maxspeed);
+        this.add(maxspeedPanel);
 
-		// Stop sign
-		JPanel stopPanel = new JPanel();
-		JLabel stopLabel = new JLabel(tr("Stop"));
-		stopLabel.setIcon(new ImageProvider("signs/stop.png").get());
-		stopPanel.add(stopLabel);
-		stopPanel.add(stop);
-		this.add(stopPanel);
+        // Stop sign
+        JPanel stopPanel = new JPanel();
+        JLabel stopLabel = new JLabel(tr("Stop"));
+        stopLabel.setIcon(new ImageProvider("signs/stop.png").get());
+        stopPanel.add(stopLabel);
+        stopPanel.add(stop);
+        this.add(stopPanel);
 
-		// Give way sign
-		JPanel giveWayPanel = new JPanel();
-		JLabel giveWayLabel = new JLabel(tr("Give way"));
-		giveWayLabel.setIcon(new ImageProvider("signs/right_of_way.png").get());
-		giveWayPanel.add(giveWayLabel);
-		giveWayPanel.add(giveWay);
-		this.add(giveWayPanel);
+        // Give way sign
+        JPanel giveWayPanel = new JPanel();
+        JLabel giveWayLabel = new JLabel(tr("Give way"));
+        giveWayLabel.setIcon(new ImageProvider("signs/right_of_way.png").get());
+        giveWayPanel.add(giveWayLabel);
+        giveWayPanel.add(giveWay);
+        this.add(giveWayPanel);
 
-		// Roundabout sign
-		JPanel roundaboutPanel = new JPanel();
-		JLabel roundaboutLabel = new JLabel(tr("Give way"));
-		roundaboutLabel.setIcon(new ImageProvider("signs/roundabout_right.png")
-				.get());
-		roundaboutPanel.add(roundaboutLabel);
-		roundaboutPanel.add(roundabout);
-		this.add(roundaboutPanel);
+        // Roundabout sign
+        JPanel roundaboutPanel = new JPanel();
+        JLabel roundaboutLabel = new JLabel(tr("Give way"));
+        roundaboutLabel.setIcon(new ImageProvider("signs/roundabout_right.png")
+                .get());
+        roundaboutPanel.add(roundaboutLabel);
+        roundaboutPanel.add(roundabout);
+        this.add(roundaboutPanel);
 
-		// No entry sign
-		JPanel noEntryPanel = new JPanel();
-		JLabel noEntryLabel = new JLabel(tr("No entry"));
-		noEntryLabel.setIcon(new ImageProvider("signs/no_entry.png").get());
-		noEntryPanel.add(noEntryLabel);
-		noEntryPanel.add(access);
-		this.add(noEntryPanel);
+        // No entry sign
+        JPanel noEntryPanel = new JPanel();
+        JLabel noEntryLabel = new JLabel(tr("No entry"));
+        noEntryLabel.setIcon(new ImageProvider("signs/no_entry.png").get());
+        noEntryPanel.add(noEntryLabel);
+        noEntryPanel.add(access);
+        this.add(noEntryPanel);
 
-		// Danger intersection
-		JPanel intersectionPanel = new JPanel();
-		JLabel intersectionLabel = new JLabel(tr("Intersection danger"));
-		intersectionLabel.setIcon(new ImageProvider(
-				"signs/intersection_danger.png").get());
-		intersectionPanel.add(intersectionLabel);
-		intersectionPanel.add(intersection);
-		this.add(intersectionPanel);
+        // Danger intersection
+        JPanel intersectionPanel = new JPanel();
+        JLabel intersectionLabel = new JLabel(tr("Intersection danger"));
+        intersectionLabel.setIcon(new ImageProvider(
+                "signs/intersection_danger.png").get());
+        intersectionPanel.add(intersectionLabel);
+        intersectionPanel.add(intersection);
+        this.add(intersectionPanel);
 
-		// Mandatory direction
-		JPanel directionPanel = new JPanel();
-		JLabel directionLabel = new JLabel(tr("Mandatory direction (any)"));
-		directionLabel.setIcon(new ImageProvider("signs/only_straight_on.png")
-				.get());
-		directionPanel.add(directionLabel);
-		directionPanel.add(direction);
-		this.add(directionPanel);
+        // Mandatory direction
+        JPanel directionPanel = new JPanel();
+        JLabel directionLabel = new JLabel(tr("Mandatory direction (any)"));
+        directionLabel.setIcon(new ImageProvider("signs/only_straight_on.png")
+                .get());
+        directionPanel.add(directionLabel);
+        directionPanel.add(direction);
+        this.add(directionPanel);
 
-		// No turn
-		JPanel noTurnPanel = new JPanel();
-		JLabel noTurnLabel = new JLabel(tr("No turn"));
-		noTurnLabel.setIcon(new ImageProvider("signs/no_turn.png").get());
-		noTurnPanel.add(noTurnLabel);
-		noTurnPanel.add(noTurn);
-		this.add(noTurnPanel);
+        // No turn
+        JPanel noTurnPanel = new JPanel();
+        JLabel noTurnLabel = new JLabel(tr("No turn"));
+        noTurnLabel.setIcon(new ImageProvider("signs/no_turn.png").get());
+        noTurnPanel.add(noTurnLabel);
+        noTurnPanel.add(noTurn);
+        this.add(noTurnPanel);
 
-		// Uneven road
-		JPanel unevenPanel = new JPanel();
-		JLabel unevenLabel = new JLabel(tr("Uneven road"));
-		unevenLabel.setIcon(new ImageProvider("signs/uneaven.png").get());
-		unevenPanel.add(unevenLabel);
-		unevenPanel.add(uneven);
-		this.add(unevenPanel);
+        // Uneven road
+        JPanel unevenPanel = new JPanel();
+        JLabel unevenLabel = new JLabel(tr("Uneven road"));
+        unevenLabel.setIcon(new ImageProvider("signs/uneaven.png").get());
+        unevenPanel.add(unevenLabel);
+        unevenPanel.add(uneven);
+        this.add(unevenPanel);
 
-		// No parking
-		JPanel noParkingPanel = new JPanel();
-		JLabel noParkingLabel = new JLabel(tr("No parking"));
-		noParkingLabel.setIcon(new ImageProvider("signs/no_parking.png").get());
-		noParkingPanel.add(noParkingLabel);
-		noParkingPanel.add(noParking);
-		this.add(noParkingPanel);
+        // No parking
+        JPanel noParkingPanel = new JPanel();
+        JLabel noParkingLabel = new JLabel(tr("No parking"));
+        noParkingLabel.setIcon(new ImageProvider("signs/no_parking.png").get());
+        noParkingPanel.add(noParkingLabel);
+        noParkingPanel.add(noParking);
+        this.add(noParkingPanel);
 
-		// No overtaking
-		JPanel noOvertakingPanel = new JPanel();
-		JLabel noOvertakingLabel = new JLabel(tr("No overtaking"));
-		noOvertakingLabel.setIcon(new ImageProvider("signs/no_overtaking.png")
-				.get());
-		noOvertakingPanel.add(noOvertakingLabel);
-		noOvertakingPanel.add(noOvertaking);
-		this.add(noOvertakingPanel);
+        // No overtaking
+        JPanel noOvertakingPanel = new JPanel();
+        JLabel noOvertakingLabel = new JLabel(tr("No overtaking"));
+        noOvertakingLabel.setIcon(new ImageProvider("signs/no_overtaking.png")
+                .get());
+        noOvertakingPanel.add(noOvertakingLabel);
+        noOvertakingPanel.add(noOvertaking);
+        this.add(noOvertakingPanel);
 
-		// Pedestrian crossing
-		JPanel crossingPanel = new JPanel();
-		JLabel crossingLabel = new JLabel(tr("Pedestrian crossing"));
-		crossingLabel.setIcon(new ImageProvider("signs/crossing.png").get());
-		crossingPanel.add(crossingLabel);
-		crossingPanel.add(crossing);
-		this.add(crossingPanel);
+        // Pedestrian crossing
+        JPanel crossingPanel = new JPanel();
+        JLabel crossingLabel = new JLabel(tr("Pedestrian crossing"));
+        crossingLabel.setIcon(new ImageProvider("signs/crossing.png").get());
+        crossingPanel.add(crossingLabel);
+        crossingPanel.add(crossing);
+        this.add(crossingPanel);
 
-		this.setPreferredSize(new Dimension(600, 150));
-	}
+        this.setPreferredSize(new Dimension(600, 150));
+    }
 
-	public static MapillaryFilterChooseSigns getInstance() {
-		if (INSTANCE == null)
-			INSTANCE = new MapillaryFilterChooseSigns();
-		return INSTANCE;
-	}
+    public static MapillaryFilterChooseSigns getInstance() {
+        if (INSTANCE == null)
+            INSTANCE = new MapillaryFilterChooseSigns();
+        return INSTANCE;
+    }
 
-	@Override
-	public void actionPerformed(ActionEvent arg0) {
-		// TODO Auto-generated method stub
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        // TODO Auto-generated method stub
 
-	}
+    }
 
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java	(revision 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryFilterDialog.java	(revision 31328)
@@ -37,265 +37,265 @@
  */
 public class MapillaryFilterDialog extends ToggleDialog implements
-		MapillaryDataListener {
-
-	public static MapillaryFilterDialog INSTANCE;
-
-	private final static String[] TIME_LIST = { tr("All time"),
-			tr("This year"), tr("This month"), tr("This week") };
-
-	private final static int ROWS = 0;
-	private final static int COLUMNS = 3;
-
-	private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS));
-
-	public final JCheckBox imported = new JCheckBox("Imported images");
-	public final JCheckBox downloaded = new JCheckBox(
-			new downloadCheckBoxAction());
-	public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction());
-	public final JComboBox<String> time;
-	public final JTextField user;
-
-	public final SideButton updateButton = new SideButton(new UpdateAction());
-	public final SideButton resetButton = new SideButton(new ResetAction());
-	public final JButton signChooser = new JButton(new SignChooserAction());
-
-	public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns
-			.getInstance();
-
-	private final String[] SIGN_TAGS = { "prohibitory_speed_limit",
-			"priority_stop", "other_give_way", "mandatory_roundabout",
-			"other_no_entry", "prohibitory_no_traffic_both_ways",
-			"danger_intersection", "mandatory_go", "mandatory_keep",
-			"danger_priority_next_intersection", "danger_uneven_road",
-			"prohibitory_no_parking", "prohibitory_on_overtaking",
-			"danger_pedestrian_crossing", "prohibitory_no_u_turn",
-			"prohibitory_noturn" };
-	private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed,
-			signFilter.stop, signFilter.giveWay, signFilter.roundabout,
-			signFilter.access, signFilter.access, signFilter.intersection,
-			signFilter.direction, signFilter.direction,
-			signFilter.intersection, signFilter.uneven, signFilter.noParking,
-			signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn,
-			signFilter.noTurn };
-
-	public MapillaryFilterDialog() {
-		super(tr("Mapillary filter"), "mapillaryfilter.png",
-				tr("Open Mapillary filter dialog"), Shortcut.registerShortcut(
-						tr("Mapillary filter"),
-						tr("Open Mapillary filter dialog"), KeyEvent.VK_M,
-						Shortcut.NONE), 200);
-
-		signChooser.setEnabled(false);
-		JPanel signChooserPanel = new JPanel();
-		signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
-		signChooserPanel.add(signChooser);
-
-		JPanel fromPanel = new JPanel();
-		fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
-		fromPanel.add(new JLabel("From"));
-		time = new JComboBox<>(TIME_LIST);
-		fromPanel.add(time);
-
-		JPanel userSearchPanel = new JPanel();
-		userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
-		user = new JTextField(10);
-		user.addActionListener(new UpdateAction());
-		userSearchPanel.add(new JLabel("User"));
-		userSearchPanel.add(user);
-
-		imported.setSelected(true);
-		downloaded.setSelected(true);
-
-		panel.add(downloaded);
-		panel.add(imported);
-		panel.add(onlySigns);
-		panel.add(fromPanel);
-		panel.add(userSearchPanel);
-		panel.add(signChooserPanel);
-
-		createLayout(panel, true,
-				Arrays.asList(new SideButton[] { updateButton, resetButton }));
-	}
-
-	public static MapillaryFilterDialog getInstance() {
-		if (INSTANCE == null)
-			INSTANCE = new MapillaryFilterDialog();
-		return INSTANCE;
-	}
-
-	@Override
-	public void imagesAdded() {
-		refresh();
-	}
-
-	@Override
-	public void selectedImageChanged(MapillaryAbstractImage oldImage,
-			MapillaryAbstractImage newImage) {
-	}
-
-	public void reset() {
-		imported.setSelected(true);
-		downloaded.setSelected(true);
-		onlySigns.setEnabled(true);
-		onlySigns.setSelected(false);
-		user.setText("");
-		time.setSelectedItem(TIME_LIST[0]);
-		refresh();
-	}
-
-	public synchronized void refresh() {
-		boolean imported = this.imported.isSelected();
-		boolean downloaded = this.downloaded.isSelected();
-		boolean onlySigns = this.onlySigns.isSelected();
-
-		for (MapillaryAbstractImage img : MapillaryData.getInstance()
-				.getImages()) {
-			img.setVisible(true);
-			if (img instanceof MapillaryImportedImage) {
-				if (!imported)
-					img.setVisible(false);
-				continue;
-			} else if (img instanceof MapillaryImage) {
-				if (!downloaded) {
-					img.setVisible(false);
-					continue;
-				}
-				if (onlySigns) {
-					if (((MapillaryImage) img).getSigns().isEmpty()) {
-						img.setVisible(false);
-						continue;
-					}
-					if (!checkSigns((MapillaryImage) img)) {
-						img.setVisible(false);
-						continue;
-					}
-				}
-				if (!user.getText().equals("")
-						&& !user.getText().equals(
-								((MapillaryImage) img).getUser())) {
-					img.setVisible(false);
-					continue;
-				}
-			}
-			// Calculates the amount of days since the image was taken
-			Long currentTime = currentTime();
-			if (time.getSelectedItem() == TIME_LIST[1]) {
-				if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) {
-					img.setVisible(false);
-					continue;
-				}
-			}
-			if (time.getSelectedItem() == TIME_LIST[2]) {
-				if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) {
-					img.setVisible(false);
-					continue;
-				}
-			}
-			if (time.getSelectedItem() == TIME_LIST[3]) {
-				if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) {
-					img.setVisible(false);
-					continue;
-				}
-			}
-		}
-		Main.map.repaint();
-	}
-
-	private boolean checkSigns(MapillaryImage img) {
-		for (int i = 0; i < SIGN_TAGS.length; i++) {
-			if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i]))
-				return true;
-		}
-		return false;
-	}
-
-	private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox,
-			String singString) {
-		boolean contains = false;
-		for (String sign : img.getSigns()) {
-			if (sign.contains(singString))
-				contains = true;
-		}
-		if (contains == signCheckBox.isSelected() && contains)
-			return true;
-		return false;
-	}
-
-	private long currentTime() {
-		Calendar cal = Calendar.getInstance();
-		return cal.getTimeInMillis();
-	}
-
-	private class downloadCheckBoxAction extends AbstractAction {
-
-		public downloadCheckBoxAction() {
-			putValue(NAME, tr("Downloaded images"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			onlySigns.setEnabled(downloaded.isSelected());
-		}
-	}
-
-	private class UpdateAction extends AbstractAction {
-		public UpdateAction() {
-			putValue(NAME, tr("Update"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			MapillaryFilterDialog.getInstance().refresh();
-		}
-	}
-
-	private class ResetAction extends AbstractAction {
-		public ResetAction() {
-			putValue(NAME, tr("Reset"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			MapillaryFilterDialog.getInstance().reset();
-		}
-	}
-
-	private class OnlySignsAction extends AbstractAction {
-		public OnlySignsAction() {
-			putValue(NAME, tr("Only images with signs"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			signChooser.setEnabled(onlySigns.isSelected());
-		}
-	}
-
-	/**
-	 * Opens a new window where you can specifically filter signs.
-	 * 
-	 * @author nokutu
-	 *
-	 */
-	private class SignChooserAction extends AbstractAction {
-		public SignChooserAction() {
-			putValue(NAME, tr("Choose signs"));
-		}
-
-		@Override
-		public void actionPerformed(ActionEvent arg0) {
-			JPanel dialog = MapillaryFilterChooseSigns.getInstance();
-			JOptionPane pane = new JOptionPane(dialog,
-					JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
-			JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs"));
-			dlg.setVisible(true);
-			if ((int) pane.getValue() == JOptionPane.OK_OPTION)
-				MapillaryFilterDialog.getInstance().refresh();
-			dlg.dispose();
-		}
-	}
-
-	public static void destroyInstance() {
-		MapillaryFilterDialog.INSTANCE = null;
-	}
+        MapillaryDataListener {
+
+    public static MapillaryFilterDialog INSTANCE;
+
+    private final static String[] TIME_LIST = { tr("All time"),
+            tr("This year"), tr("This month"), tr("This week") };
+
+    private final static int ROWS = 0;
+    private final static int COLUMNS = 3;
+
+    private final JPanel panel = new JPanel(new GridLayout(ROWS, COLUMNS));
+
+    public final JCheckBox imported = new JCheckBox("Imported images");
+    public final JCheckBox downloaded = new JCheckBox(
+            new downloadCheckBoxAction());
+    public final JCheckBox onlySigns = new JCheckBox(new OnlySignsAction());
+    public final JComboBox<String> time;
+    public final JTextField user;
+
+    public final SideButton updateButton = new SideButton(new UpdateAction());
+    public final SideButton resetButton = new SideButton(new ResetAction());
+    public final JButton signChooser = new JButton(new SignChooserAction());
+
+    public final MapillaryFilterChooseSigns signFilter = MapillaryFilterChooseSigns
+            .getInstance();
+
+    private final String[] SIGN_TAGS = { "prohibitory_speed_limit",
+            "priority_stop", "other_give_way", "mandatory_roundabout",
+            "other_no_entry", "prohibitory_no_traffic_both_ways",
+            "danger_intersection", "mandatory_go", "mandatory_keep",
+            "danger_priority_next_intersection", "danger_uneven_road",
+            "prohibitory_no_parking", "prohibitory_on_overtaking",
+            "danger_pedestrian_crossing", "prohibitory_no_u_turn",
+            "prohibitory_noturn" };
+    private final JCheckBox[] SIGN_CHECKBOXES = { signFilter.maxspeed,
+            signFilter.stop, signFilter.giveWay, signFilter.roundabout,
+            signFilter.access, signFilter.access, signFilter.intersection,
+            signFilter.direction, signFilter.direction,
+            signFilter.intersection, signFilter.uneven, signFilter.noParking,
+            signFilter.noOvertaking, signFilter.crossing, signFilter.noTurn,
+            signFilter.noTurn };
+
+    public MapillaryFilterDialog() {
+        super(tr("Mapillary filter"), "mapillaryfilter.png",
+                tr("Open Mapillary filter dialog"), Shortcut.registerShortcut(
+                        tr("Mapillary filter"),
+                        tr("Open Mapillary filter dialog"), KeyEvent.VK_M,
+                        Shortcut.NONE), 200);
+
+        signChooser.setEnabled(false);
+        JPanel signChooserPanel = new JPanel();
+        signChooserPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        signChooserPanel.add(signChooser);
+
+        JPanel fromPanel = new JPanel();
+        fromPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        fromPanel.add(new JLabel("From"));
+        time = new JComboBox<>(TIME_LIST);
+        fromPanel.add(time);
+
+        JPanel userSearchPanel = new JPanel();
+        userSearchPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
+        user = new JTextField(10);
+        user.addActionListener(new UpdateAction());
+        userSearchPanel.add(new JLabel("User"));
+        userSearchPanel.add(user);
+
+        imported.setSelected(true);
+        downloaded.setSelected(true);
+
+        panel.add(downloaded);
+        panel.add(imported);
+        panel.add(onlySigns);
+        panel.add(fromPanel);
+        panel.add(userSearchPanel);
+        panel.add(signChooserPanel);
+
+        createLayout(panel, true,
+                Arrays.asList(new SideButton[] { updateButton, resetButton }));
+    }
+
+    public static MapillaryFilterDialog getInstance() {
+        if (INSTANCE == null)
+            INSTANCE = new MapillaryFilterDialog();
+        return INSTANCE;
+    }
+
+    @Override
+    public void imagesAdded() {
+        refresh();
+    }
+
+    @Override
+    public void selectedImageChanged(MapillaryAbstractImage oldImage,
+            MapillaryAbstractImage newImage) {
+    }
+
+    public void reset() {
+        imported.setSelected(true);
+        downloaded.setSelected(true);
+        onlySigns.setEnabled(true);
+        onlySigns.setSelected(false);
+        user.setText("");
+        time.setSelectedItem(TIME_LIST[0]);
+        refresh();
+    }
+
+    public synchronized void refresh() {
+        boolean imported = this.imported.isSelected();
+        boolean downloaded = this.downloaded.isSelected();
+        boolean onlySigns = this.onlySigns.isSelected();
+
+        for (MapillaryAbstractImage img : MapillaryData.getInstance()
+                .getImages()) {
+            img.setVisible(true);
+            if (img instanceof MapillaryImportedImage) {
+                if (!imported)
+                    img.setVisible(false);
+                continue;
+            } else if (img instanceof MapillaryImage) {
+                if (!downloaded) {
+                    img.setVisible(false);
+                    continue;
+                }
+                if (onlySigns) {
+                    if (((MapillaryImage) img).getSigns().isEmpty()) {
+                        img.setVisible(false);
+                        continue;
+                    }
+                    if (!checkSigns((MapillaryImage) img)) {
+                        img.setVisible(false);
+                        continue;
+                    }
+                }
+                if (!user.getText().equals("")
+                        && !user.getText().equals(
+                                ((MapillaryImage) img).getUser())) {
+                    img.setVisible(false);
+                    continue;
+                }
+            }
+            // Calculates the amount of days since the image was taken
+            Long currentTime = currentTime();
+            if (time.getSelectedItem() == TIME_LIST[1]) {
+                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 365) {
+                    img.setVisible(false);
+                    continue;
+                }
+            }
+            if (time.getSelectedItem() == TIME_LIST[2]) {
+                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 30) {
+                    img.setVisible(false);
+                    continue;
+                }
+            }
+            if (time.getSelectedItem() == TIME_LIST[3]) {
+                if ((currentTime - img.getCapturedAt()) / (24 * 60 * 60 * 1000) > 7) {
+                    img.setVisible(false);
+                    continue;
+                }
+            }
+        }
+        Main.map.repaint();
+    }
+
+    private boolean checkSigns(MapillaryImage img) {
+        for (int i = 0; i < SIGN_TAGS.length; i++) {
+            if (checkSign(img, SIGN_CHECKBOXES[i], SIGN_TAGS[i]))
+                return true;
+        }
+        return false;
+    }
+
+    private boolean checkSign(MapillaryImage img, JCheckBox signCheckBox,
+            String singString) {
+        boolean contains = false;
+        for (String sign : img.getSigns()) {
+            if (sign.contains(singString))
+                contains = true;
+        }
+        if (contains == signCheckBox.isSelected() && contains)
+            return true;
+        return false;
+    }
+
+    private long currentTime() {
+        Calendar cal = Calendar.getInstance();
+        return cal.getTimeInMillis();
+    }
+
+    private class downloadCheckBoxAction extends AbstractAction {
+
+        public downloadCheckBoxAction() {
+            putValue(NAME, tr("Downloaded images"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            onlySigns.setEnabled(downloaded.isSelected());
+        }
+    }
+
+    private class UpdateAction extends AbstractAction {
+        public UpdateAction() {
+            putValue(NAME, tr("Update"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            MapillaryFilterDialog.getInstance().refresh();
+        }
+    }
+
+    private class ResetAction extends AbstractAction {
+        public ResetAction() {
+            putValue(NAME, tr("Reset"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            MapillaryFilterDialog.getInstance().reset();
+        }
+    }
+
+    private class OnlySignsAction extends AbstractAction {
+        public OnlySignsAction() {
+            putValue(NAME, tr("Only images with signs"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            signChooser.setEnabled(onlySigns.isSelected());
+        }
+    }
+
+    /**
+     * Opens a new window where you can specifically filter signs.
+     * 
+     * @author nokutu
+     *
+     */
+    private class SignChooserAction extends AbstractAction {
+        public SignChooserAction() {
+            putValue(NAME, tr("Choose signs"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent arg0) {
+            JPanel dialog = MapillaryFilterChooseSigns.getInstance();
+            JOptionPane pane = new JOptionPane(dialog,
+                    JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
+            JDialog dlg = pane.createDialog(Main.parent, tr("Choose signs"));
+            dlg.setVisible(true);
+            if ((int) pane.getValue() == JOptionPane.OK_OPTION)
+                MapillaryFilterDialog.getInstance().refresh();
+            dlg.dispose();
+        }
+    }
+
+    public static void destroyInstance() {
+        MapillaryFilterDialog.INSTANCE = 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 31327)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java	(revision 31328)
@@ -20,7 +20,9 @@
     private JCheckBox downloadMode = new JCheckBox(
             tr("Download images manually"));
-    private JCheckBox displayHour = new JCheckBox(tr("Display hour when the picture was taken"));
+    private JCheckBox displayHour = new JCheckBox(
+            tr("Display hour when the picture was taken"));
     private JCheckBox format24 = new JCheckBox(tr("Use 24 hour format"));
-    private JCheckBox moveTo = new JCheckBox(tr("Move to picture's location with next/previous buttons"));
+    private JCheckBox moveTo = new JCheckBox(
+            tr("Move to picture's location with next/previous buttons"));
 
     @Override
@@ -37,7 +39,9 @@
         downloadMode.setSelected(Main.pref
                 .getBoolean("mapillary.download-manually"));
-        displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour", true));
+        displayHour.setSelected(Main.pref.getBoolean("mapillary.display-hour",
+                true));
         format24.setSelected(Main.pref.getBoolean("mapillary.format-24"));
-        moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture", true));
+        moveTo.setSelected(Main.pref.getBoolean("mapillary.move-to-picture",
+                true));
 
         panel.setLayout(new FlowLayout(FlowLayout.LEFT));
@@ -55,6 +59,7 @@
         Main.pref.put("mapillary.reverse-buttons", reverseButtons.isSelected());
         Main.pref.put("mapillary.download-manually", downloadMode.isSelected());
-        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, downloadMode.isSelected());
-        
+        MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU,
+                downloadMode.isSelected());
+
         Main.pref.put("mapillary.display-hour", displayHour.isSelected());
         Main.pref.put("mapillary.format-24", format24.isSelected());
