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 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryData.java	(revision 31164)
@@ -152,5 +152,6 @@
 	/**
 	 * Selects a new image and then starts a new MapillaryImageDownloadThread
-	 * thread in order to download its surrounding thumbnails and images.
+	 * thread in order to download its surrounding thumbnails and images. If the
+	 * user does ctrl+click, this isn't triggered.
 	 * 
 	 * @param image
@@ -203,13 +204,23 @@
 	}
 
+	/**
+	 * Returns a list containing all MapillaryImage objects selected with ctrl +
+	 * click
+	 * 
+	 * @return
+	 */
 	public List<MapillaryImage> getMultiSelectedImages() {
 		return multiSelectedImages;
 	}
 
+	/**
+	 * This is empty because it is used just to make sure that certain images
+	 * have already been downloaded.
+	 */
 	@Override
 	public void loadingFinished(CacheEntry data,
 			CacheEntryAttributes attributes, LoadResult result) {
 		// DO NOTHING
-		
+
 	}
 }
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDownloadAction.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDownloadAction.java	(revision 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryDownloadAction.java	(revision 31164)
@@ -53,14 +53,4 @@
 		else
 			this.layer.download();
-		/*
-		 * MapillaryDialog dialog = new MapillaryDialog(); JOptionPane pane =
-		 * new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
-		 * JOptionPane.OK_CANCEL_OPTION); JDialog dlg =
-		 * pane.createDialog(Main.parent, tr("Export"));
-		 * dialog.setOptionPane(pane); dlg.setVisible(true);
-		 * if(((Integer)pane.getValue()) == JOptionPane.OK_OPTION){ //
-		 * MapillaryTask task = new MapillaryTask(); //
-		 * Main.worker.execute(task); } dlg.dispose();
-		 */
 	}
 
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryExportDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryExportDialog.java	(revision 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryExportDialog.java	(revision 31164)
@@ -25,6 +25,11 @@
 
 	protected JOptionPane optionPane;
+	// Button to export all downloaded images.
 	protected JRadioButton all;
+	// Button to export all images in the sequence of the selected
+	// MapillaryImage.
 	protected JRadioButton sequence;
+	// Button to export all images belonging to the selected MapillaryImage
+	// objects.
 	protected JRadioButton selected;
 	protected ButtonGroup group;
@@ -35,6 +40,5 @@
 
 	public MapillaryExportDialog() {
-	setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
-
+		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
 
 		group = new ButtonGroup();
@@ -49,5 +53,5 @@
 			sequence.setEnabled(false);
 		}
-		if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()){
+		if (MapillaryData.getInstance().getMultiSelectedImages().isEmpty()) {
 			selected.setEnabled(false);
 		}
@@ -55,5 +59,5 @@
 		choose = new JButton(tr("Explore"));
 		choose.addActionListener(this);
-		
+
 		JPanel jpanel = new JPanel();
 		jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
@@ -61,32 +65,22 @@
 		jpanel.add(sequence);
 		jpanel.add(selected);
-		//all.setAlignmentX(Component.CENTER_ALIGNMENT);
-		//sequence.setAlignmentX(Component.CENTER_ALIGNMENT);
 		jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
 		path.setAlignmentX(Component.CENTER_ALIGNMENT);
 		choose.setAlignmentX(Component.CENTER_ALIGNMENT);
-		//container.setAlignmentX(Component.CENTER_ALIGNMENT);
 
-		
 		add(jpanel);
 		add(path);
 		add(choose);
 
-
 	}
 
 	/**
-	 * Has to be called after this dialog has been added to a JOptionPane.
-	 * 
-	 * @param optionPane
+	 * Creates the folder choser GUI.
 	 */
-	public void setOptionPane(JOptionPane optionPane) {
-		this.optionPane = optionPane;
-	}
-
 	@Override
 	public void actionPerformed(ActionEvent e) {
 		chooser = new JFileChooser();
-		chooser.setCurrentDirectory(new java.io.File(System.getProperty("user.home")));
+		chooser.setCurrentDirectory(new java.io.File(System
+				.getProperty("user.home")));
 		chooser.setDialogTitle("Select a directory");
 		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
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 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImage.java	(revision 31164)
@@ -12,16 +12,6 @@
 	private String key;
 	private LatLon latLon;
-
-	/**
-	 * 0 means north.
-	 */
 	private Double ca;
 	private boolean isModified = false;
-
-	/**
-	 * Used to prevent old running threads from setting images in an object
-	 * which are no longer needed.
-	 */
-
 	public MapillarySequence sequence;
 
@@ -44,16 +34,36 @@
 	}
 
+	/**
+	 * Returns whether the object has been modified or not.
+	 * 
+	 * @return true if the object has been modified; false otherwise.
+	 */
 	public boolean isModified() {
 		return this.isModified;
 	}
 
+	/**
+	 * Returns a LatLon object containing the coordintes of the object.
+	 * 
+	 * @return The LatLon object with the position of the object.
+	 */
 	public LatLon getLatLon() {
 		return latLon;
 	}
 
+	/**
+	 * Returns the direction towards the image has been taken.
+	 * 
+	 * @return The direction of the image (0 means north and goes clockwise).
+	 */
 	public Double getCa() {
 		return ca;
 	}
 
+	/**
+	 * Returns the unique identifier of the object.
+	 * 
+	 * @return A String containing the unique identifier of the object.
+	 */
 	public String getKey() {
 		return this.key;
@@ -70,4 +80,9 @@
 	}
 
+	/**
+	 * Returns the sequence which contains this image.
+	 * 
+	 * @return The MapillarySequence object that contains this MapillaryImage.
+	 */
 	public MapillarySequence getSequence() {
 		return this.sequence;
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImageDisplay.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImageDisplay.java	(revision 31164)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryImageDisplay.java	(revision 31164)
@@ -0,0 +1,477 @@
+package org.openstreetmap.josm.plugins.mapillary;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JComponent;
+
+/**
+ * This object is a responsible JComponent which lets you zoom and drag. It is
+ * included in a {@link MapillaryToggleDialog} object.
+ * 
+ * @author Jorge
+ *
+ */
+public class MapillaryImageDisplay extends JComponent {
+
+	private static final int DRAG_BUTTON = 3;
+	private static final int ZOOM_BUTTON = 1;
+
+	/** The image currently displayed */
+	private transient Image image = null;
+
+	/**
+	 * The rectangle (in image coordinates) of the image that is visible. This
+	 * rectangle is calculated each time the zoom is modified
+	 */
+	private Rectangle visibleRect = null;
+	/**
+	 * When a selection is done, the rectangle of the selection (in image
+	 * coordinates)
+	 */
+	private Rectangle selectedRect = null;
+
+	private class ImgDisplayMouseListener implements MouseListener,
+			MouseWheelListener, MouseMotionListener {
+		private boolean mouseIsDragging = false;
+		private long lastTimeForMousePoint = 0L;
+		private Point mousePointInImg = null;
+
+		/**
+		 * Zoom in and out, trying to preserve the point of the image that was
+		 * under the mouse cursor at the same place
+		 */
+		@Override
+		public void mouseWheelMoved(MouseWheelEvent e) {
+			Image image;
+			Rectangle visibleRect;
+			synchronized (MapillaryImageDisplay.this) {
+				image = MapillaryImageDisplay.this.image;
+				visibleRect = MapillaryImageDisplay.this.visibleRect;
+			}
+			mouseIsDragging = false;
+			selectedRect = null;
+			if (image == null)
+				return;
+			// Calculate the mouse cursor position in image coordinates, so that
+			// we can center the zoom
+			// on that mouse position.
+			// To avoid issues when the user tries to zoom in on the image
+			// borders, this point is not calculated
+			// again if there was less than 1.5seconds since the last event.
+			if (e.getWhen() - lastTimeForMousePoint > 1500
+					|| mousePointInImg == null) {
+				lastTimeForMousePoint = e.getWhen();
+				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+			}
+			// Applicate the zoom to the visible rectangle in image coordinates
+			if (e.getWheelRotation() > 0) {
+				visibleRect.width = visibleRect.width * 3 / 2;
+				visibleRect.height = visibleRect.height * 3 / 2;
+			} else {
+				visibleRect.width = visibleRect.width * 2 / 3;
+				visibleRect.height = visibleRect.height * 2 / 3;
+			}
+			// Check that the zoom doesn't exceed 2:1
+			if (visibleRect.width < getSize().width / 2) {
+				visibleRect.width = getSize().width / 2;
+			}
+			if (visibleRect.height < getSize().height / 2) {
+				visibleRect.height = getSize().height / 2;
+			}
+			// Set the same ratio for the visible rectangle and the display area
+			int hFact = visibleRect.height * getSize().width;
+			int wFact = visibleRect.width * getSize().height;
+			if (hFact > wFact) {
+				visibleRect.width = hFact / getSize().height;
+			} else {
+				visibleRect.height = wFact / getSize().width;
+			}
+			// The size of the visible rectangle is limited by the image size.
+			checkVisibleRectSize(image, visibleRect);
+			// Set the position of the visible rectangle, so that the mouse
+			// cursor doesn't move on the image.
+			Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+			visibleRect.x = mousePointInImg.x
+					+ ((drawRect.x - e.getX()) * visibleRect.width)
+					/ drawRect.width;
+			visibleRect.y = mousePointInImg.y
+					+ ((drawRect.y - e.getY()) * visibleRect.height)
+					/ drawRect.height;
+			// The position is also limited by the image size
+			checkVisibleRectPos(image, visibleRect);
+			synchronized (MapillaryImageDisplay.this) {
+				MapillaryImageDisplay.this.visibleRect = visibleRect;
+			}
+			MapillaryImageDisplay.this.repaint();
+		}
+
+		/** Center the display on the point that has been clicked */
+		@Override
+		public void mouseClicked(MouseEvent e) {
+			// Move the center to the clicked point.
+			Image image;
+			Rectangle visibleRect;
+			synchronized (MapillaryImageDisplay.this) {
+				image = MapillaryImageDisplay.this.image;
+				visibleRect = MapillaryImageDisplay.this.visibleRect;
+			}
+			if (image == null)
+				return;
+			if (e.getButton() != DRAG_BUTTON)
+				return;
+			// Calculate the translation to set the clicked point the center of
+			// the view.
+			Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
+			Point center = getCenterImgCoord(visibleRect);
+			visibleRect.x += click.x - center.x;
+			visibleRect.y += click.y - center.y;
+			checkVisibleRectPos(image, visibleRect);
+			synchronized (MapillaryImageDisplay.this) {
+				MapillaryImageDisplay.this.visibleRect = visibleRect;
+			}
+			MapillaryImageDisplay.this.repaint();
+		}
+
+		/**
+		 * Initialize the dragging, either with button 1 (simple dragging) or
+		 * button 3 (selection of a picture part)
+		 */
+		@Override
+		public void mousePressed(MouseEvent e) {
+			if (image == null) {
+				mouseIsDragging = false;
+				selectedRect = null;
+				return;
+			}
+			Image image;
+			Rectangle visibleRect;
+			synchronized (MapillaryImageDisplay.this) {
+				image = MapillaryImageDisplay.this.image;
+				visibleRect = MapillaryImageDisplay.this.visibleRect;
+			}
+			if (image == null)
+				return;
+			if (e.getButton() == DRAG_BUTTON) {
+				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+				mouseIsDragging = true;
+				selectedRect = null;
+			} else if (e.getButton() == ZOOM_BUTTON) {
+				mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+				checkPointInVisibleRect(mousePointInImg, visibleRect);
+				mouseIsDragging = false;
+				selectedRect = new Rectangle(mousePointInImg.x,
+						mousePointInImg.y, 0, 0);
+				MapillaryImageDisplay.this.repaint();
+			} else {
+				mouseIsDragging = false;
+				selectedRect = null;
+			}
+		}
+
+		@Override
+		public void mouseDragged(MouseEvent e) {
+			if (!mouseIsDragging && selectedRect == null)
+				return;
+			Image image;
+			Rectangle visibleRect;
+			synchronized (MapillaryImageDisplay.this) {
+				image = MapillaryImageDisplay.this.image;
+				visibleRect = MapillaryImageDisplay.this.visibleRect;
+			}
+			if (image == null) {
+				mouseIsDragging = false;
+				selectedRect = null;
+				return;
+			}
+			if (mouseIsDragging) {
+				Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+				visibleRect.x += mousePointInImg.x - p.x;
+				visibleRect.y += mousePointInImg.y - p.y;
+				checkVisibleRectPos(image, visibleRect);
+				synchronized (MapillaryImageDisplay.this) {
+					MapillaryImageDisplay.this.visibleRect = visibleRect;
+				}
+				MapillaryImageDisplay.this.repaint();
+			} else if (selectedRect != null) {
+				Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+				checkPointInVisibleRect(p, visibleRect);
+				Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
+						: mousePointInImg.x, p.y < mousePointInImg.y ? p.y
+						: mousePointInImg.y,
+						p.x < mousePointInImg.x ? mousePointInImg.x - p.x : p.x
+								- mousePointInImg.x,
+						p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
+								- mousePointInImg.y);
+				checkVisibleRectSize(image, rect);
+				checkVisibleRectPos(image, rect);
+				MapillaryImageDisplay.this.selectedRect = rect;
+				MapillaryImageDisplay.this.repaint();
+			}
+		}
+
+		@Override
+		public void mouseReleased(MouseEvent e) {
+			if (!mouseIsDragging && selectedRect == null)
+				return;
+			Image image;
+			synchronized (MapillaryImageDisplay.this) {
+				image = MapillaryImageDisplay.this.image;
+			}
+			if (image == null) {
+				mouseIsDragging = false;
+				selectedRect = null;
+				return;
+			}
+			if (mouseIsDragging) {
+				mouseIsDragging = false;
+			} else if (selectedRect != null) {
+				int oldWidth = selectedRect.width;
+				int oldHeight = selectedRect.height;
+				// Check that the zoom doesn't exceed 2:1
+				if (selectedRect.width < getSize().width / 2) {
+					selectedRect.width = getSize().width / 2;
+				}
+				if (selectedRect.height < getSize().height / 2) {
+					selectedRect.height = getSize().height / 2;
+				}
+				// Set the same ratio for the visible rectangle and the display
+				// area
+				int hFact = selectedRect.height * getSize().width;
+				int wFact = selectedRect.width * getSize().height;
+				if (hFact > wFact) {
+					selectedRect.width = hFact / getSize().height;
+				} else {
+					selectedRect.height = wFact / getSize().width;
+				}
+				// Keep the center of the selection
+				if (selectedRect.width != oldWidth) {
+					selectedRect.x -= (selectedRect.width - oldWidth) / 2;
+				}
+				if (selectedRect.height != oldHeight) {
+					selectedRect.y -= (selectedRect.height - oldHeight) / 2;
+				}
+				checkVisibleRectSize(image, selectedRect);
+				checkVisibleRectPos(image, selectedRect);
+				synchronized (MapillaryImageDisplay.this) {
+					MapillaryImageDisplay.this.visibleRect = selectedRect;
+				}
+				selectedRect = null;
+				MapillaryImageDisplay.this.repaint();
+			}
+		}
+
+		@Override
+		public void mouseEntered(MouseEvent e) {
+		}
+
+		@Override
+		public void mouseExited(MouseEvent e) {
+		}
+
+		@Override
+		public void mouseMoved(MouseEvent e) {
+		}
+
+		private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
+			if (p.x < visibleRect.x) {
+				p.x = visibleRect.x;
+			}
+			if (p.x > visibleRect.x + visibleRect.width) {
+				p.x = visibleRect.x + visibleRect.width;
+			}
+			if (p.y < visibleRect.y) {
+				p.y = visibleRect.y;
+			}
+			if (p.y > visibleRect.y + visibleRect.height) {
+				p.y = visibleRect.y + visibleRect.height;
+			}
+		}
+	}
+
+	public MapillaryImageDisplay() {
+		ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
+		addMouseListener(mouseListener);
+		addMouseWheelListener(mouseListener);
+		addMouseMotionListener(mouseListener);
+	}
+
+	public void setImage(BufferedImage image) {
+		synchronized (this) {
+			this.image = image;
+			selectedRect = null;
+			if (image != null)
+				this.visibleRect = new Rectangle(0, 0, image.getWidth(null),
+						image.getHeight(null));
+		}
+		repaint();
+	}
+
+	public void paintComponent(Graphics g) {
+		Image image;
+		Rectangle visibleRect;
+		synchronized (this) {
+			image = this.image;
+			visibleRect = this.visibleRect;
+		}
+		if (image == null) {
+			g.setColor(Color.black);
+			String noImageStr = tr("No image");
+			Rectangle2D noImageSize = g.getFontMetrics(g.getFont())
+					.getStringBounds(noImageStr, g);
+			Dimension size = getSize();
+			g.drawString(noImageStr,
+					(int) ((size.width - noImageSize.getWidth()) / 2),
+					(int) ((size.height - noImageSize.getHeight()) / 2));
+		} else {
+			Rectangle target = calculateDrawImageRectangle(visibleRect);
+			g.drawImage(image, target.x, target.y, target.x + target.width,
+					target.y + target.height, visibleRect.x, visibleRect.y,
+					visibleRect.x + visibleRect.width, visibleRect.y
+							+ visibleRect.height, null);
+			if (selectedRect != null) {
+				Point topLeft = img2compCoord(visibleRect, selectedRect.x,
+						selectedRect.y);
+				Point bottomRight = img2compCoord(visibleRect, selectedRect.x
+						+ selectedRect.width, selectedRect.y
+						+ selectedRect.height);
+				g.setColor(new Color(128, 128, 128, 180));
+				g.fillRect(target.x, target.y, target.width, topLeft.y
+						- target.y);
+				g.fillRect(target.x, target.y, topLeft.x - target.x,
+						target.height);
+				g.fillRect(bottomRight.x, target.y, target.x + target.width
+						- bottomRight.x, target.height);
+				g.fillRect(target.x, bottomRight.y, target.width, target.y
+						+ target.height - bottomRight.y);
+				g.setColor(Color.black);
+				g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
+						bottomRight.y - topLeft.y);
+			}
+		}
+	}
+
+	private final Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
+		Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+		return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
+				/ visibleRect.width, drawRect.y
+				+ ((yImg - visibleRect.y) * drawRect.height)
+				/ visibleRect.height);
+	}
+
+	private final Point comp2imgCoord(Rectangle visibleRect, int xComp,
+			int yComp) {
+		Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+		return new Point(visibleRect.x
+				+ ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
+				visibleRect.y + ((yComp - drawRect.y) * visibleRect.height)
+						/ drawRect.height);
+	}
+
+	private final Point getCenterImgCoord(Rectangle visibleRect) {
+		return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y
+				+ visibleRect.height / 2);
+	}
+
+	private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
+		return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0,
+				getSize().width, getSize().height));
+	}
+
+	/**
+	 * calculateDrawImageRectangle
+	 *
+	 * @param imgRect
+	 *            the part of the image that should be drawn (in image
+	 *            coordinates)
+	 * @param compRect
+	 *            the part of the component where the image should be drawn (in
+	 *            component coordinates)
+	 * @return the part of compRect with the same width/height ratio as the
+	 *         image
+	 */
+	static Rectangle calculateDrawImageRectangle(Rectangle imgRect,
+			Rectangle compRect) {
+		int x, y, w, h;
+		x = 0;
+		y = 0;
+		w = compRect.width;
+		h = compRect.height;
+		int wFact = w * imgRect.height;
+		int hFact = h * imgRect.width;
+		if (wFact != hFact) {
+			if (wFact > hFact) {
+				w = hFact / imgRect.height;
+				x = (compRect.width - w) / 2;
+			} else {
+				h = wFact / imgRect.width;
+				y = (compRect.height - h) / 2;
+			}
+		}
+		return new Rectangle(x + compRect.x, y + compRect.y, w, h);
+	}
+
+	public void zoomBestFitOrOne() {
+		Image image;
+		Rectangle visibleRect;
+		synchronized (this) {
+			image = MapillaryImageDisplay.this.image;
+			visibleRect = MapillaryImageDisplay.this.visibleRect;
+		}
+		if (image == null)
+			return;
+		if (visibleRect.width != image.getWidth(null)
+				|| visibleRect.height != image.getHeight(null)) {
+			// The display is not at best fit. => Zoom to best fit
+			visibleRect = new Rectangle(0, 0, image.getWidth(null),
+					image.getHeight(null));
+		} else {
+			// The display is at best fit => zoom to 1:1
+			Point center = getCenterImgCoord(visibleRect);
+			visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
+					- getHeight() / 2, getWidth(), getHeight());
+			checkVisibleRectPos(image, visibleRect);
+		}
+		synchronized (this) {
+			this.visibleRect = visibleRect;
+		}
+		repaint();
+	}
+
+	private final void checkVisibleRectPos(Image image, Rectangle visibleRect) {
+		if (visibleRect.x < 0) {
+			visibleRect.x = 0;
+		}
+		if (visibleRect.y < 0) {
+			visibleRect.y = 0;
+		}
+		if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
+			visibleRect.x = image.getWidth(null) - visibleRect.width;
+		}
+		if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
+			visibleRect.y = image.getHeight(null) - visibleRect.height;
+		}
+	}
+
+	private void checkVisibleRectSize(Image image, Rectangle visibleRect) {
+		if (visibleRect.width > image.getWidth(null)) {
+			visibleRect.width = image.getWidth(null);
+		}
+		if (visibleRect.height > image.getHeight(null)) {
+			visibleRect.height = image.getHeight(null);
+		}
+	}
+}
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryLayer.java	(revision 31164)
@@ -56,4 +56,7 @@
 	}
 
+	/**
+	 * Initializes the Layer.
+	 */
 	private void init() {
 		INSTANCED = true;
@@ -81,4 +84,7 @@
 	}
 
+	/**
+	 * Downloads all images of the area covered by the OSM data.
+	 */
 	protected void download() {
 		for (Bounds bounds : Main.map.mapView.getEditLayer().data
@@ -92,11 +98,20 @@
 	}
 
+	/**
+	 * Returs the MapillaryData object, which acts as the database of the Layer.
+	 * 
+	 * @return
+	 */
 	public MapillaryData getMapillaryData() {
 		return mapillaryData;
 	}
 
+	/**
+	 * Method invoqued when the layer is destroyed.
+	 */
 	@Override
 	public void destroy() {
-		MapillaryToggleDialog.getInstance().mapillaryImageDisplay.setImage(null);
+		MapillaryToggleDialog.getInstance().mapillaryImageDisplay
+				.setImage(null);
 		INSTANCED = false;
 		MapillaryPlugin.setMenuEnabled(MapillaryPlugin.EXPORT_MENU, false);
@@ -108,4 +123,7 @@
 	}
 
+	/**
+	 * Returns true any of the images from the database has been modified.
+	 */
 	@Override
 	public boolean isModified() {
@@ -118,4 +136,7 @@
 	}
 
+	/**
+	 * Paints the database in the map.
+	 */
 	@Override
 	public void paint(Graphics2D g, MapView mv, Bounds box) {
@@ -150,5 +171,5 @@
 	@Override
 	public boolean isMergable(Layer other) {
-		return other instanceof MapillaryLayer;
+		return false;
 	}
 
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 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryPlugin.java	(revision 31164)
@@ -12,5 +12,5 @@
 
 /**
- * This is the main class for the mapillary plugin.
+ * This is the main class of the Mapillary plugin.
  * 
  * @author nokutu
@@ -49,4 +49,7 @@
 			MapillaryToggleDialog.deleteInstance ();
 		}
+		if (oldFrame != null && newFrame == null) { // map frame added
+			System.out.println("Mapframe destroyed");
+		}
 	}
 	
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java	(revision 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillarySequence.java	(revision 31164)
@@ -21,12 +21,27 @@
 	}
 
+	/**
+	 * Returns all MapillaryImages objects contained by this object.
+	 * 
+	 * @return
+	 */
 	public List<MapillaryImage> getImages() {
 		return this.images;
 	}
 
+	/**
+	 * Adds a new MapillaryImage object to this object.
+	 * 
+	 * @param image
+	 */
 	public synchronized void add(MapillaryImage image) {
 		this.images.add(image);
 	}
 
+	/**
+	 * Adds a set of MapillaryImage objects to this object.
+	 * 
+	 * @param images
+	 */
 	public synchronized void add(List<MapillaryImage> images) {
 		for (MapillaryImage image : images) {
@@ -35,4 +50,9 @@
 	}
 
+	/**
+	 * Removes a MapillaryImage object from this object.
+	 * 
+	 * @param image
+	 */
 	public void remove(MapillaryImage image) {
 		this.images.remove(image);
@@ -71,4 +91,12 @@
 	}
 
+	/**
+	 * Returns the difference of index between two MapillaryImage objects
+	 * belonging to the same MapillarySequence.
+	 * 
+	 * @param image1
+	 * @param image2
+	 * @return
+	 */
 	public int getDistance(MapillaryImage image1, MapillaryImage image2) {
 		if (!this.images.contains(image1) || !this.images.contains(image2))
Index: /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryToggleDialog.java
===================================================================
--- /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryToggleDialog.java	(revision 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/MapillaryToggleDialog.java	(revision 31164)
@@ -103,12 +103,28 @@
 	}
 
+	/**
+	 * Sets a new MapillaryImage to be shown.
+	 * 
+	 * @param image
+	 */
 	public synchronized void setImage(MapillaryImage image) {
 		this.image = image;
 	}
 
+	/**
+	 * Returns the MapillaryImage objects which is being shown.
+	 * 
+	 * @return
+	 */
 	public synchronized MapillaryImage getImage() {
 		return this.image;
 	}
 
+	/**
+	 * Action class form the next image button.
+	 * 
+	 * @author Jorge
+	 *
+	 */
 	class nextPictureAction extends AbstractAction {
 		public nextPictureAction() {
@@ -128,4 +144,10 @@
 	}
 
+	/**
+	 * Action class for the previous image button.
+	 * 
+	 * @author Jorge
+	 *
+	 */
 	class previousPictureAction extends AbstractAction {
 		public previousPictureAction() {
@@ -145,4 +167,8 @@
 	}
 
+	/**
+	 * When the pictures are returned from the cache, they are set in the
+	 * {@link MapillaryImageDisplay} object.
+	 */
 	@Override
 	public void loadingFinished(CacheEntry data,
@@ -157,11 +183,4 @@
 		} else {
 			try {
-				/*
-				 * BufferedImage img = ImageIO.read(new
-				 * ByteArrayInputStream(data .getContent()));
-				 * this.remove(active); JLabel label = new JLabel("", new
-				 * ImageIcon(img), JLabel.CENTER); active = label;
-				 * this.add(active); this.updateUI();
-				 */
 				BufferedImage img = ImageIO.read(new ByteArrayInputStream(data
 						.getContent()));
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 31163)
+++ /applications/editors/josm/plugins/mapillary/src/org/openstreetmap/josm/plugins/mapillary/downloads/MapillaryDownloader.java	(revision 31164)
@@ -26,14 +26,4 @@
 		this.data = data;
 	}
-
-	/*
-	 * public List<MapillaryImage> getImagesAround(LatLon latLon, double
-	 * distance) { String u rl = BASE_URL; url += "search/im/close/";
-	 * Hashtable<String, Double> hash = new Hashtable<String, Double>();
-	 * hash.put("lat", latLon.lat()); hash.put("lon", latLon.lon());
-	 * hash.put("distance", distance); url += buildParameters(hash); try {
-	 * return parseImages(parseUrl(url)); } catch (Exception e) { return null; }
-	 * }
-	 */
 
 	/**
