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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31399)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.gui.MapView.EditLayerChangeListener;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
+import org.openstreetmap.josm.gui.NavigatableComponent;
 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
@@ -63,12 +64,13 @@
  *
  */
-public class MapillaryLayer extends AbstractModifiableLayer implements DataSetListener, EditLayerChangeListener,
-    LayerChangeListener {
+public class MapillaryLayer extends AbstractModifiableLayer implements
+    DataSetListener, EditLayerChangeListener, LayerChangeListener {
 
   /** Maximum distance for the red/blue lines. */
-  public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref
-      .getInteger("mapillary.sequence-max-jump-distance", 100);
-
-  private boolean TEMP_MANUAL = false;
+  public final static int SEQUENCE_MAX_JUMP_DISTANCE = Main.pref.getInteger(
+      "mapillary.sequence-max-jump-distance", 100);
+
+  /** If the download is in manual mode during the rest of the session */
+  public boolean TEMP_SEMIAUTOMATIC = false;
 
   /** Unique instance of the class */
@@ -105,8 +107,6 @@
    */
   private void init() {
-    mode = new SelectMode();
     if (Main.map != null && Main.map.mapView != null) {
-      Main.map.mapView.addMouseListener(mode);
-      Main.map.mapView.addMouseMotionListener(mode);
+      setMode(new SelectMode());
       Main.map.mapView.addLayer(this);
       MapView.addEditLayerChangeListener(this, false);
@@ -130,13 +130,17 @@
    *
    * @param mode
-   *        The mode that is going to be activated.
+   *          The mode that is going to be activated.
    */
   public void setMode(AbstractMode mode) {
-    Main.map.mapView.removeMouseListener(this.mode);
-    Main.map.mapView.removeMouseMotionListener(this.mode);
+    if (this.mode != null) {
+      Main.map.mapView.removeMouseListener(this.mode);
+      Main.map.mapView.removeMouseMotionListener(this.mode);
+      NavigatableComponent.removeZoomChangeListener(this.mode);
+    }
     this.mode = mode;
     Main.map.mapView.setNewCursor(mode.cursor, this);
     Main.map.mapView.addMouseListener(mode);
     Main.map.mapView.addMouseMotionListener(mode);
+    NavigatableComponent.addZoomChangeListener(mode);
     updateHelpText();
   }
@@ -145,5 +149,5 @@
    * Returns the unique instance of this class.
    *
-   * @return The unique isntance of this class.
+   * @return The unique instance of this class.
    */
   public synchronized static MapillaryLayer getInstance() {
@@ -159,5 +163,7 @@
   public void download() {
     checkAreaTooBig();
-    if (Main.pref.getBoolean("mapillary.download-manually") || TEMP_MANUAL)
+    if (!Main.pref.get("mapillary.download-mode").equals(
+        MapillaryDownloader.MODES[0])
+        || TEMP_SEMIAUTOMATIC)
       return;
     for (Bounds bounds : Main.map.mapView.getEditLayer().data
@@ -165,5 +171,5 @@
       if (!this.bounds.contains(bounds)) {
         this.bounds.add(bounds);
-        new MapillaryDownloader().getImages(bounds.getMin(), bounds.getMax());
+        MapillaryDownloader.getImages(bounds.getMin(), bounds.getMax());
       }
     }
@@ -183,5 +189,5 @@
     }
     if (area > MapillaryDownloadViewAction.MAX_AREA) {
-      TEMP_MANUAL = true;
+      TEMP_SEMIAUTOMATIC = true;
       MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, true);
       JOptionPane
@@ -223,5 +229,6 @@
 
   /**
-   * Zooms to fit all the {@link MapillaryAbstractImage} icons into the map view.
+   * Zooms to fit all the {@link MapillaryAbstractImage} icons into the map
+   * view.
    */
   public void showAllPictures() {
@@ -240,5 +247,6 @@
         maxLon = img.getLatLon().lon();
     }
-    Main.map.mapView.zoomTo(new Bounds(new LatLon(minLat, minLon), new LatLon (maxLat, maxLon)));
+    Main.map.mapView.zoomTo(new Bounds(new LatLon(minLat, minLon), new LatLon(
+        maxLat, maxLon)));
   }
 
@@ -437,8 +445,11 @@
     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);
+    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.getHighlighted() == image) {
       drawPointHighlight(g, p, 16);
@@ -458,5 +469,6 @@
   @Override
   public void mergeFrom(Layer from) {
-    throw new UnsupportedOperationException("This layer does not support merging yet");
+    throw new UnsupportedOperationException(
+        "This layer does not support merging yet");
   }
 
@@ -480,5 +492,6 @@
     MapillaryImage selected = (MapillaryImage) data.getSelectedImage();
     MapillaryImage[] ret = new MapillaryImage[2];
-    double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE, SEQUENCE_MAX_JUMP_DISTANCE };
+    double[] distances = { SEQUENCE_MAX_JUMP_DISTANCE,
+        SEQUENCE_MAX_JUMP_DISTANCE };
     LatLon selectedCoords = data.getSelectedImage().getLatLon();
     for (MapillaryAbstractImage imagePrev : data.getImages()) {
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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31399)
@@ -15,4 +15,5 @@
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.mapillary.downloads.MapillaryDownloader;
 import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryFilterDialog;
 import org.openstreetmap.josm.plugins.mapillary.gui.MapillaryHistoryDialog;
@@ -134,5 +135,6 @@
       Main.map.addToggleDialog(MapillaryFilterDialog.getInstance(), false);
       setMenuEnabled(DOWNLOAD_MENU, true);
-      if (Main.pref.getBoolean("mapillary.download-manually"))
+      if (Main.pref.get("mapillary.download-mode").equals(
+          MapillaryDownloader.MODES[2]))
         setMenuEnabled(DOWNLOAD_VIEW_MENU, true);
       setMenuEnabled(IMPORT_MENU, true);
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java	(revision 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/actions/MapillaryDownloadViewAction.java	(revision 31399)
@@ -27,5 +27,5 @@
   /** Max area to be downloaded */
   public static final double MAX_AREA = Main.pref.getDouble(
-      "mapillary.max-download-area", 0.020);
+      "mapillary.max-download-area", 0.015);
 
   /**
@@ -45,5 +45,5 @@
     MapillaryLayer.getInstance().bounds.add(Main.map.mapView.getRealBounds());
     if (Main.map.mapView.getRealBounds().getArea() <= MAX_AREA) {
-      new MapillaryDownloader().getImages(Main.map.mapView.getRealBounds());
+      MapillaryDownloader.getImages(Main.map.mapView.getRealBounds());
     } else {
       JOptionPane.showMessageDialog(Main.parent,
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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31399)
@@ -9,4 +9,5 @@
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer;
+import org.openstreetmap.josm.plugins.mapillary.actions.MapillaryDownloadViewAction;
 
 /**
@@ -19,4 +20,8 @@
 public class MapillaryDownloader {
 
+  /** Possible download modes.*/
+  public static final String[] MODES = new String[] { "Automatic", "Semiautomatic",
+  "Manual" };
+
   /** Base URL of the Mapillary API. */
   public final static String BASE_URL = "https://a.mapillary.com/v2/";
@@ -25,5 +30,4 @@
   /** Executor that will run the petitions */
   public final static Executor EXECUTOR = Executors.newSingleThreadExecutor();
-
 
   /**
@@ -36,5 +40,5 @@
    *          The maximum latitude and longitude of the rectangle
    */
-  public void getImages(LatLon minLatLon, LatLon maxLatLon) {
+  public static void getImages(LatLon minLatLon, LatLon maxLatLon) {
     ConcurrentHashMap<String, Double> queryStringParts = new ConcurrentHashMap<>();
     queryStringParts.put("min_lat", minLatLon.lat());
@@ -44,8 +48,29 @@
 
     try {
-      EXECUTOR.execute(new MapillarySquareDownloadManagerThread(queryStringParts, MapillaryLayer.getInstance()));
+      EXECUTOR.execute(new MapillarySquareDownloadManagerThread(
+          queryStringParts, MapillaryLayer.getInstance()));
     } catch (Exception e) {
       Main.error(e);
     }
+  }
+
+  /**
+   * If some part of the current view has not been downloaded, it is downloaded.
+   *
+   */
+  public static void completeView() {
+    Bounds view = Main.map.mapView.getRealBounds();
+    if (view.getArea() > MapillaryDownloadViewAction.MAX_AREA)
+      return;
+    for (Bounds bound : MapillaryLayer.getInstance().bounds) {
+      if (!view.intersects(bound))
+        continue;
+      if (bound.equals(view)) {
+        // Already downloaded
+        return;
+      }
+    }
+    MapillaryLayer.getInstance().bounds.add(view);
+    getImages(view);
   }
 
@@ -55,5 +80,5 @@
    * @param bounds
    */
-  public void getImages(Bounds bounds) {
+  public static void getImages(Bounds bounds) {
     getImages(bounds.getMin(), bounds.getMax());
   }
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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySequenceDownloadThread.java	(revision 31399)
@@ -40,5 +40,5 @@
   /**
    * Main constructor.
-   * 
+   *
    * @param ex
    * @param queryString
@@ -90,5 +90,4 @@
             jsonobj.getString("key"), jsonobj.getJsonNumber("captured_at")
                 .longValue());
-
         List<MapillaryImage> finalImages = new ArrayList<>(images);
         // Here it gets only those images which are in the downloaded
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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillarySquareDownloadManagerThread.java	(revision 31399)
@@ -36,8 +36,8 @@
   /**
    * Main constructor.
-   * 
+   *
    * @param queryStringParts
    * @param layer
-   * 
+   *
    */
   public MapillarySquareDownloadManagerThread(
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java	(revision 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/HyperlinkLabel.java	(revision 31399)
@@ -47,5 +47,6 @@
   @Override
   public void setText(String text) {
-    super.setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
+    super
+        .setText("<html><font color=\"#0000CF\" size=\"2\">" + text + "</font></html>"); //$NON-NLS-1$ //$NON-NLS-2$
     this.text = text;
   }
@@ -70,5 +71,5 @@
   /**
    * Returns the text set by the user.
-   * 
+   *
    * @return The plain-text written in the label.
    */
@@ -84,5 +85,6 @@
     super.processMouseEvent(evt);
     if (evt.getID() == MouseEvent.MOUSE_CLICKED)
-      fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getNormalText()));
+      fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
+          getNormalText()));
   }
 
@@ -90,5 +92,5 @@
    * Adds an ActionListener to the list of listeners receiving notifications
    * when the label is clicked.
-   * 
+   *
    * @param listener
    */
@@ -100,5 +102,5 @@
    * Removes the given ActionListener from the list of listeners receiving
    * notifications when the label is clicked.
-   * 
+   *
    * @param listener
    */
@@ -109,5 +111,6 @@
   /**
    * Fires an ActionEvent to all interested listeners.
-   * @param evt 
+   *
+   * @param evt
    */
   protected void fireActionPerformed(ActionEvent evt) {
@@ -126,9 +129,11 @@
       return;
     Desktop desktop = Desktop.getDesktop();
-    try {
-      desktop.browse(url.toURI());
-    } catch (IOException | URISyntaxException ex) {
-      ex.printStackTrace();
-    } catch (UnsupportedOperationException ex) {
+    if (desktop.isSupported(Desktop.Action.BROWSE)) {
+      try {
+        desktop.browse(url.toURI());
+      } catch (IOException | URISyntaxException e1) {
+        Main.error(e1);
+      }
+    } else {
       Runtime runtime = Runtime.getRuntime();
       try {
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 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/gui/MapillaryPreferenceSetting.java	(revision 31399)
@@ -13,4 +13,6 @@
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 
@@ -20,4 +22,5 @@
 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
 import org.openstreetmap.josm.plugins.mapillary.MapillaryPlugin;
+import org.openstreetmap.josm.plugins.mapillary.downloads.MapillaryDownloader;
 import org.openstreetmap.josm.plugins.mapillary.oauth.PortListener;
 
@@ -32,5 +35,6 @@
   private JCheckBox reverseButtons = new JCheckBox(
       tr("Reverse buttons position when displaying images."));
-  private JCheckBox downloadMode = new JCheckBox(tr("Download images manually"));
+  private JComboBox<String> downloadMode = new JComboBox<>(
+      MapillaryDownloader.MODES);
   private JCheckBox displayHour = new JCheckBox(
       tr("Display hour when the picture was taken"));
@@ -50,6 +54,4 @@
     reverseButtons.setSelected(Main.pref
         .getBoolean("mapillary.reverse-buttons"));
-    downloadMode.setSelected(Main.pref
-        .getBoolean("mapillary.download-manually"));
     displayHour.setSelected(Main.pref
         .getBoolean("mapillary.display-hour", true));
@@ -59,5 +61,10 @@
     panel.setLayout(new FlowLayout(FlowLayout.LEFT));
     panel.add(reverseButtons);
-    panel.add(downloadMode);
+
+    JPanel downloadModePanel = new JPanel();
+    downloadModePanel.add(new JLabel(tr("Download mode: ")));
+    downloadModePanel.add(downloadMode);
+    panel.add(downloadModePanel);
+
     panel.add(displayHour);
     panel.add(format24);
@@ -67,5 +74,5 @@
       oauth.setText("Login");
     else
-       oauth.setText("Already loged in, click to relogin.");
+      oauth.setText("Already loged in, click to relogin.");
     panel.add(oauth);
     gui.getDisplayPreference().addSubTab(this, "Mapillary", panel);
@@ -76,7 +83,14 @@
     boolean mod = false;
     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, false);
+    if (downloadMode.getSelectedItem().equals(MapillaryDownloader.MODES[0]))
+      Main.pref.put("mapillary.download-mode", MapillaryDownloader.MODES[0]);
+    if (downloadMode.getSelectedItem().equals(MapillaryDownloader.MODES[1]))
+      Main.pref.put("mapillary.download-mode", MapillaryDownloader.MODES[1]);
+    if (downloadMode.getSelectedItem().equals(MapillaryDownloader.MODES[2])) {
+      Main.pref.put("mapillary.download-mode", MapillaryDownloader.MODES[2]);
+      MapillaryPlugin.setMenuEnabled(MapillaryPlugin.DOWNLOAD_VIEW_MENU, true);
+    }
 
     Main.pref.put("mapillary.display-hour", displayHour.isSelected());
@@ -108,9 +122,11 @@
       String url = "http://www.mapillary.io/connect?redirect_uri=http:%2F%2Flocalhost:8763%2F&client_id=MkJKbDA0bnZuZlcxeTJHTmFqN3g1dzplZTlkZjQyYjYyZTczOTdi&response_type=token&scope=user:email";
       Desktop desktop = Desktop.getDesktop();
-      try {
-        desktop.browse(new URI(url));
-      } catch (IOException | URISyntaxException ex) {
-        ex.printStackTrace();
-      } catch (UnsupportedOperationException ex) {
+      if (desktop.isSupported(Desktop.Action.BROWSE)) {
+        try {
+          desktop.browse(new URI(url));
+        } catch (IOException | URISyntaxException e1) {
+          Main.error(e1);
+        }
+      } else {
         Runtime runtime = Runtime.getRuntime();
         try {
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java	(revision 31398)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/mode/AbstractMode.java	(revision 31399)
@@ -5,10 +5,14 @@
 import java.awt.Point;
 import java.awt.event.MouseAdapter;
+import java.util.Calendar;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener;
 import org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage;
 import org.openstreetmap.josm.plugins.mapillary.MapillaryData;
+import org.openstreetmap.josm.plugins.mapillary.MapillaryLayer;
+import org.openstreetmap.josm.plugins.mapillary.downloads.MapillaryDownloader;
 
 /**
@@ -19,7 +23,10 @@
  *
  */
-public abstract class AbstractMode extends MouseAdapter {
+public abstract class AbstractMode extends MouseAdapter implements
+    ZoomChangeListener {
 
   protected MapillaryData data = MapillaryData.getInstance();
+
+  private long lastDownload;
 
   /**
@@ -54,3 +61,25 @@
   public abstract void paint(Graphics2D g, MapView mv, Bounds box);
 
+  @Override
+  public synchronized void zoomChanged() {
+    if (Main.pref.get("mapillary.download-mode").equals(
+        MapillaryDownloader.MODES[1])
+        || MapillaryLayer.getInstance().TEMP_SEMIAUTOMATIC) {
+      if (Calendar.getInstance().getTimeInMillis() - lastDownload >= 2000) {
+        lastDownload = Calendar.getInstance().getTimeInMillis();
+        MapillaryDownloader.completeView();
+      } else {
+        new Thread() {
+          @Override
+          public synchronized void run() {
+            try {
+              wait(100);
+            } catch (InterruptedException e) {
+            }
+            zoomChanged();
+          }
+        }.start();
+      }
+    }
+  }
 }
