Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java	(revision 9494)
@@ -47,16 +47,7 @@
 	}
 
-	public void mouseMoved(MouseEvent e) {
-	}
-
 	public void mouseClicked(MouseEvent e) {
 		if (doubleClickZoomEnabled && e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1)
 			map.zoomIn(e.getPoint());
-	}
-
-	public void mouseEntered(MouseEvent e) {
-	}
-
-	public void mouseExited(MouseEvent e) {
 	}
 
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 9494)
@@ -13,4 +13,5 @@
 import javax.swing.JPanel;
 
+
 /**
  * 
@@ -26,4 +27,7 @@
 		setSize(400, 400);
 		final JMapViewer map = new JMapViewer();
+//		final JMapViewer map = new JMapViewer(new MemoryTileCache(),4);
+//		map.setTileLoader(new OsmFileCacheTileLoader(map,OsmTileLoader.MAP_MAPNIK));
+		new DefaultMapController(map);
 		setLayout(new BorderLayout());
 		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
@@ -87,4 +91,7 @@
 	 */
 	public static void main(String[] args) {
+//		Properties systemProperties = System.getProperties();
+//		systemProperties.setProperty("http.proxyHost","localhost");
+//		systemProperties.setProperty("http.proxyPort","8008");
 		new Demo().setVisible(true);
 	}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapController.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapController.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapController.java	(revision 9494)
@@ -26,7 +26,7 @@
 	public JMapController(JMapViewer map) {
 		this.map = map;
-		map.addMouseListener((MouseListener) this);
-		map.addMouseWheelListener((MouseWheelListener) this);
-		map.addMouseMotionListener((MouseMotionListener) this);
+		map.addMouseListener(this);
+		map.addMouseWheelListener(this);
+		map.addMouseMotionListener(this);
 	}
 
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 9494)
@@ -12,7 +12,4 @@
 import java.awt.geom.Point2D;
 import java.awt.image.BufferedImage;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
 import java.util.LinkedList;
 import java.util.List;
@@ -27,4 +24,7 @@
 
 import org.openstreetmap.gui.jmapviewer.JobDispatcher.JobThread;
+import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 
 /**
@@ -49,4 +49,5 @@
 	public static final int MIN_ZOOM = 0;
 
+	protected TileLoader tileLoader;
 	protected TileCache tileCache;
 	protected List<MapMarker> mapMarkerList;
@@ -90,4 +91,5 @@
 	public JMapViewer(TileCache tileCache, int downloadThreadCount) {
 		super();
+		tileLoader = new OsmTileLoader(this);
 		this.tileCache = tileCache;
 		jobDispatcher = new JobDispatcher(downloadThreadCount);
@@ -442,44 +444,5 @@
 		}
 		if (!tile.isLoaded()) {
-			jobDispatcher.addJob(new Job() {
-
-				InputStream input = null;
-
-				public void run() {
-					Tile tile = tileCache.getTile(tilex, tiley, zoom);
-					if (tile == null || tile.isLoaded())
-						return;
-					try {
-						// Thread.sleep(500);
-						URL url;
-						url = new URL("http://tile.openstreetmap.org/" + tile.getKey() + ".png");
-						HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
-						urlConn.setReadTimeout(30000); // 30 seconds read
-						// timeout
-						input = urlConn.getInputStream();
-						tile.setImage(ImageIO.read(input));
-						tile.setLoaded(true);
-						repaint();
-						input.close();
-						input = null;
-					} catch (Exception e) {
-						if (input == null /* || !input.isStopped() */)
-							System.err.println("failed loading " + zoom + "/" + tilex + "/" + tiley
-									+ " " + e.getMessage());
-					}
-				}
-
-				/**
-				 * Terminating all transfers that are currently in progress
-				 */
-				public void stop() {
-
-					try {
-						// if (input != null)
-						// input.stop();
-					} catch (Exception e) {
-					}
-				}
-			});
+			tileLoader.addLoadRequest(tilex, tiley, zoom);
 		}
 		return tile;
@@ -538,3 +501,11 @@
 	}
 
+	public TileLoader getTileLoader() {
+		return tileLoader;
+	}
+
+	public void setTileLoader(TileLoader tileLoader) {
+		this.tileLoader = tileLoader;
+	}
+
 }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Job.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Job.java	(revision 9421)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package org.openstreetmap.gui.jmapviewer;
-
-//License: GPL. Copyright 2008 by Jan Peter Stotz
-
-/**
- * An extension to the {@link Runnable} interface adding the possibility to
- * {@link #stop()} it.
- * 
- * @author Jan Peter Stotz
- */
-public interface Job extends Runnable {
-
-	/**
-	 * Allows to stop / cancel a job without having to interrupt the executing
-	 * {@link Thread}.
-	 */
-	public void stop();
-}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java	(revision 9494)
@@ -5,4 +5,6 @@
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.Job;
 
 /**
@@ -55,4 +57,5 @@
 		public JobThread(int threadId) {
 			super("OSMJobThread " + threadId);
+			setDaemon(true);
 			job = null;
 			start();
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapMarker.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapMarker.java	(revision 9421)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package org.openstreetmap.gui.jmapviewer;
-
-//License: GPL. Copyright 2008 by Jan Peter Stotz
-
-import java.awt.Graphics;
-import java.awt.Point;
-
-/**
- * Interface to be implemented by all elements that can be displayed on the map.
- * 
- * @author Jan Peter Stotz
- * @see JMapViewer#addMapMarker(MapMarker)
- * @see JMapViewer#getMapMarkerList()
- */
-public interface MapMarker {
-
-	/**
-	 * @return Latitude of the map marker position
-	 */
-	public double getLat();
-
-	/**
-	 * @return Longitude of the map marker position
-	 */
-	public double getLon();
-
-	/**
-	 * Paints the map marker on the map. The <code>position</code> specifies the
-	 * coordinates within <code>g</code>
-	 * 
-	 * @param g
-	 * @param position
-	 */
-	public void paint(Graphics g, Point position);
-}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MapMarkerDot.java	(revision 9494)
@@ -6,4 +6,6 @@
 import java.awt.Graphics;
 import java.awt.Point;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
 
 /**
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 9494)
@@ -5,4 +5,6 @@
 import java.util.Hashtable;
 import java.util.logging.Logger;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
 
 /**
@@ -15,5 +17,5 @@
 public class MemoryTileCache implements TileCache {
 
-	private static final Logger log = Logger.getLogger(MemoryTileCache.class.getName());
+	protected static final Logger log = Logger.getLogger(MemoryTileCache.class.getName());
 
 	/**
@@ -35,9 +37,9 @@
 
 	public void addTile(Tile tile) {
-		CacheEntry entry = new CacheEntry(tile);
+		CacheEntry entry = createCacheEntry(tile);
 		hashtable.put(tile.getKey(), entry);
 		lruTiles.addFirst(entry);
 		if (hashtable.size() > cacheSize)
-			removeOldTiles();
+			removeOldEntries();
 	}
 
@@ -56,11 +58,9 @@
 	 * Removes the least recently used tiles
 	 */
-	protected void removeOldTiles() {
+	protected void removeOldEntries() {
 		synchronized (lruTiles) {
 			try {
 				while (lruTiles.getElementCount() > cacheSize) {
-					CacheEntry entry = lruTiles.getLastElement();
-					hashtable.remove(entry.tile.getKey());
-					lruTiles.removeEntry(entry);
+					removeEntry(lruTiles.getLastElement());
 				}
 			} catch (Exception e) {
@@ -68,4 +68,13 @@
 			}
 		}
+	}
+
+	protected void removeEntry(CacheEntry entry) {
+		hashtable.remove(entry.tile.getKey());
+		lruTiles.removeEntry(entry);
+	}
+
+	protected CacheEntry createCacheEntry(Tile tile) {
+		return new CacheEntry(tile);
 	}
 
@@ -87,5 +96,5 @@
 		this.cacheSize = cacheSize;
 		if (hashtable.size() > cacheSize)
-			removeOldTiles();
+			removeOldEntries();
 	}
 
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java	(revision 9494)
@@ -0,0 +1,208 @@
+package org.openstreetmap.gui.jmapviewer;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Date;
+
+import javax.imageio.ImageIO;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.Job;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
+
+/**
+ * A {@link TileLoader} implementation that loads tiles from OSM via HTTP and
+ * saves all loaded files in a directory located in the the temporary directory.
+ * If a tile is present in this file cache it will not be loaded from OSM again.
+ * 
+ * @author Jan Peter Stotz
+ */
+public class OsmFileCacheTileLoader extends OsmTileLoader {
+
+	private static final String FILE_EXT = ".png";
+
+	public static final long FILE_AGE_ONE_DAY = 1000 * 60 * 60 * 24;
+	public static final long FILE_AGE_ONE_WEEK = FILE_AGE_ONE_DAY * 7;
+
+	protected String tileCacheDir;
+
+	protected long maxFileAge = 0;// FILE_AGE_ONE_DAY;//
+
+	// FILE_AGE_ONE_WEEK;
+
+	public OsmFileCacheTileLoader(JMapViewer map, String baseUrl) {
+		super(map, baseUrl);
+		String tempDir = System.getProperty("java.io.tmpdir");
+		try {
+			if (tempDir == null)
+				throw new IOException();
+			File cacheDir = new File(tempDir, "JMapViewerTiles");
+			cacheDir = new File(cacheDir, Integer.toString(baseUrl.hashCode()));
+			// System.out.println(cacheDir);
+			if (!cacheDir.exists() && !cacheDir.mkdirs())
+				throw new IOException();
+			tileCacheDir = cacheDir.getAbsolutePath();
+		} catch (Exception e) {
+			tileCacheDir = "tiles";
+		}
+	}
+
+	public OsmFileCacheTileLoader(JMapViewer map) {
+		this(map, MAP_MAPNIK);
+	}
+
+	public void addLoadRequest(final int tilex, final int tiley, final int zoom) {
+		map.jobDispatcher.addJob(new FileLoadJob(tilex, tiley, zoom));
+	}
+
+	protected class FileLoadJob implements Job {
+		InputStream input = null;
+
+		int tilex, tiley, zoom;
+
+		public FileLoadJob(int tilex, int tiley, int zoom) {
+			super();
+			this.tilex = tilex;
+			this.tiley = tiley;
+			this.zoom = zoom;
+		}
+
+		public void run() {
+			TileCache cache = map.getTileCache();
+			Tile tile;
+			synchronized (cache) {
+				tile = cache.getTile(tilex, tiley, zoom);
+				if (tile == null || tile.isLoaded() || tile.loading)
+					return;
+				tile.loading = true;
+			}
+			try {
+				long fileAge = 0;
+				FileInputStream fin = null;
+				File f = null;
+				try {
+					f = getTileFile(tile);
+					fin = new FileInputStream(f);
+					tile.setImage(ImageIO.read(fin));
+					fin.close();
+					fileAge = f.lastModified();
+					boolean oldTile = System.currentTimeMillis() - fileAge > maxFileAge;
+					System.out.println("Loaded from file: " + tile);
+					if (!oldTile) {
+						tile.setLoaded(true);
+						map.repaint();
+						return;
+					}
+					System.out.println("Cache hit for " + tile + " but file age is high: "
+							+ new Date(fileAge));
+					map.repaint();
+					// if (!isOsmTileNewer(tile, fileAge)) {
+					// tile.setLoaded(true);
+					// return;
+					// }
+				} catch (Exception e) {
+					try {
+						if (fin != null) {
+							fin.close();
+							f.delete();
+						}
+					} catch (Exception e1) {
+					}
+				}
+				// Thread.sleep(500);
+				System.out.println("Loading tile from OSM: " + tile);
+				HttpURLConnection urlConn = loadTileFromOsm(tile);
+				if (fileAge > 0)
+					urlConn.setIfModifiedSince(fileAge);
+
+				if (urlConn.getResponseCode() == 304) {
+					System.out.println("Local version is up to date");
+					tile.setLoaded(true);
+					return;
+				}
+				byte[] buffer = loadTileInBuffer(urlConn);
+				tile.setImage(ImageIO.read(new ByteArrayInputStream(buffer)));
+				tile.setLoaded(true);
+				map.repaint();
+				input = null;
+				saveTileToFile(tile, buffer);
+			} catch (Exception e) {
+				if (input == null /* || !input.isStopped() */)
+					System.err.println("failed loading " + zoom + "/" + tilex + "/" + tiley + " "
+							+ e.getMessage());
+			} finally {
+				tile.loading = false;
+			}
+		}
+
+		protected byte[] loadTileInBuffer(URLConnection urlConn) throws IOException {
+			input = urlConn.getInputStream();
+			ByteArrayOutputStream bout = new ByteArrayOutputStream(input.available());
+			byte[] buffer = new byte[2048];
+			boolean finished = false;
+			do {
+				int read = input.read(buffer);
+				if (read >= 0)
+					bout.write(buffer, 0, read);
+				else
+					finished = true;
+			} while (!finished);
+			return bout.toByteArray();
+		}
+
+		protected boolean isOsmTileNewer(Tile tile, long fileAge) throws IOException {
+			URL url;
+			url = new URL(baseUrl + "/" + tile.getKey() + ".png");
+			HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
+			urlConn.setRequestMethod("HEAD");
+			urlConn.setReadTimeout(30000); // 30 seconds read
+			System.out.println("Tile age: " + new Date(urlConn.getLastModified()) + " / "
+					+ new Date(fileAge));
+			long lastModified = urlConn.getLastModified();
+			if (lastModified == 0)
+				return true;
+			return (lastModified > fileAge);
+		}
+
+		protected File getTileFile(Tile tile) throws IOException {
+			return new File(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile() + "_"
+					+ tile.getYtile() + FILE_EXT);
+		}
+
+		protected void saveTileToFile(Tile tile, byte[] rawData) {
+			try {
+				FileOutputStream f =
+						new FileOutputStream(tileCacheDir + "/" + tile.getZoom() + "_"
+								+ tile.getXtile() + "_" + tile.getYtile() + FILE_EXT);
+				f.write(rawData);
+				f.close();
+				// System.out.println("Saved tile to file: " + tile);
+			} catch (Exception e) {
+				System.err.println("Failed to save tile content: " + e.getLocalizedMessage());
+			}
+		}
+
+		/**
+		 * Terminating all transfers that are currently in progress
+		 */
+		public void stop() {
+
+			try {
+				// if (input != null)
+				// input.stop();
+			} catch (Exception e) {
+			}
+		}
+	}
+
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 9494)
@@ -0,0 +1,92 @@
+package org.openstreetmap.gui.jmapviewer;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.imageio.ImageIO;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.Job;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
+
+/**
+ * A {@link TileLoader} implementation that loads tiles from OSM via HTTP.
+ * 
+ * @author Jan Peter Stotz
+ */
+public class OsmTileLoader implements TileLoader {
+
+	public static final String MAP_MAPNIK = "http://tile.openstreetmap.org";
+	public static final String MAP_OSMA = "http://tah.openstreetmap.org/Tiles/tile";
+
+	protected String baseUrl;
+
+	protected JMapViewer map;
+
+	public OsmTileLoader(JMapViewer map) {
+		this(map, MAP_MAPNIK);
+	}
+
+	public OsmTileLoader(JMapViewer map, String baseUrl) {
+		this.map = map;
+		this.baseUrl = baseUrl;
+	}
+
+	public void addLoadRequest(final int tilex, final int tiley, final int zoom) {
+		map.jobDispatcher.addJob(new Job() {
+
+			InputStream input = null;
+
+			public void run() {
+				TileCache cache = map.getTileCache();
+				Tile tile;
+				synchronized (cache) {
+					tile = cache.getTile(tilex, tiley, zoom);
+					if (tile == null || tile.isLoaded() || tile.loading)
+						return;
+					tile.loading = true;
+				}
+				try {
+					// Thread.sleep(500);
+					input = loadTileFromOsm(tile).getInputStream();
+					tile.setImage(ImageIO.read(input));
+					tile.setLoaded(true);
+					map.repaint();
+					input.close();
+					input = null;
+				} catch (Exception e) {
+					if (input == null /* || !input.isStopped() */)
+						System.err.println("failed loading " + zoom + "/" + tilex + "/" + tiley
+								+ " " + e.getMessage());
+				} finally {
+					tile.loading = false;
+				}
+			}
+
+			/**
+			 * Terminating all transfers that are currently in progress
+			 */
+			public void stop() {
+
+				try {
+					// if (input != null)
+					// input.stop();
+				} catch (Exception e) {
+				}
+			}
+		});
+	}
+
+	protected HttpURLConnection loadTileFromOsm(Tile tile) throws IOException {
+		URL url;
+		url = new URL(baseUrl + "/" + tile.getKey() + ".png");
+		HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
+		urlConn.setReadTimeout(30000); // 30 seconds read
+		// timeout
+		return urlConn;
+	}
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java	(revision 9421)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java	(revision 9494)
@@ -7,4 +7,6 @@
 import java.awt.geom.AffineTransform;
 import java.awt.image.BufferedImage;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
 
 /**
@@ -22,4 +24,5 @@
 	protected String key;
 	protected boolean loaded = false;
+	protected boolean loading = false;
 	public static final int WIDTH = 256;
 	public static final int HEIGHT = 256;
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/TileCache.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/TileCache.java	(revision 9421)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package org.openstreetmap.gui.jmapviewer;
-
-//License: GPL. Copyright 2008 by Jan Peter Stotz
-
-/**
- * Implement this interface for creating your custom tile cache for
- * {@link JMapViewer}.
- * 
- * @author Jan Peter Stotz
- */
-public interface TileCache {
-
-	/**
-	 * Retrieves a tile from the cache if present, otherwise <code>null</code>
-	 * will be returned.
-	 * 
-	 * @param x
-	 *            tile number on the x axis of the tile to be retrieved
-	 * @param y
-	 *            tile number on the y axis of the tile to be retrieved
-	 * @param z
-	 *            zoom level of the tile to be retrieved
-	 * @return the requested tile or <code>null</code> if the tile is not
-	 *         present in the cache
-	 */
-	public Tile getTile(int x, int y, int z);
-
-	/**
-	 * Adds a tile to the cache. How long after adding a tile can be retrieved
-	 * via {@link #getTile(int, int, int)} is unspecified and depends on the
-	 * implementation.
-	 * 
-	 * @param tile
-	 */
-	public void addTile(Tile tile);
-
-	/**
-	 * @return the number of tiles hold by the cache
-	 */
-	public int getTileCount();
-}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/Job.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/Job.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/Job.java	(revision 9494)
@@ -0,0 +1,18 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+/**
+ * An extension to the {@link Runnable} interface adding the possibility to
+ * {@link #stop()} it.
+ * 
+ * @author Jan Peter Stotz
+ */
+public interface Job extends Runnable {
+
+	/**
+	 * Allows to stop / cancel a job without having to interrupt the executing
+	 * {@link Thread}.
+	 */
+	public void stop();
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapMarker.java	(revision 9494)
@@ -0,0 +1,37 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+import java.awt.Graphics;
+import java.awt.Point;
+
+import org.openstreetmap.gui.jmapviewer.JMapViewer;
+
+/**
+ * Interface to be implemented by all elements that can be displayed on the map.
+ * 
+ * @author Jan Peter Stotz
+ * @see JMapViewer#addMapMarker(MapMarker)
+ * @see JMapViewer#getMapMarkerList()
+ */
+public interface MapMarker {
+
+	/**
+	 * @return Latitude of the map marker position
+	 */
+	public double getLat();
+
+	/**
+	 * @return Longitude of the map marker position
+	 */
+	public double getLon();
+
+	/**
+	 * Paints the map marker on the map. The <code>position</code> specifies the
+	 * coordinates within <code>g</code>
+	 * 
+	 * @param g
+	 * @param position
+	 */
+	public void paint(Graphics g, Point position);
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileCache.java	(revision 9494)
@@ -0,0 +1,44 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+import org.openstreetmap.gui.jmapviewer.JMapViewer;
+import org.openstreetmap.gui.jmapviewer.Tile;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+/**
+ * Implement this interface for creating your custom tile cache for
+ * {@link JMapViewer}.
+ * 
+ * @author Jan Peter Stotz
+ */
+public interface TileCache {
+
+	/**
+	 * Retrieves a tile from the cache if present, otherwise <code>null</code>
+	 * will be returned.
+	 * 
+	 * @param x
+	 *            tile number on the x axis of the tile to be retrieved
+	 * @param y
+	 *            tile number on the y axis of the tile to be retrieved
+	 * @param z
+	 *            zoom level of the tile to be retrieved
+	 * @return the requested tile or <code>null</code> if the tile is not
+	 *         present in the cache
+	 */
+	public Tile getTile(int x, int y, int z);
+
+	/**
+	 * Adds a tile to the cache. How long after adding a tile can be retrieved
+	 * via {@link #getTile(int, int, int)} is unspecified and depends on the
+	 * implementation.
+	 * 
+	 * @param tile
+	 */
+	public void addTile(Tile tile);
+
+	/**
+	 * @return the number of tiles hold by the cache
+	 */
+	public int getTileCount();
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java	(revision 9494)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java	(revision 9494)
@@ -0,0 +1,26 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL. Copyright 2008 by Jan Peter Stotz
+
+/**
+ * Interface for implementing a tile loader. Tiles are usually loaded via HTTP
+ * or from a file. The {@link TileLoader} implementation is responsible for
+ * performing the loading action asynchronously by creating a new
+ * {@link Runnable} or {@link Job}.
+ * 
+ * @author Jan Peter Stotz
+ */
+public interface TileLoader {
+
+	/**
+	 * A typical {@link #addLoadRequest(int, int, int)} implementation should
+	 * create a new {@link Job} instance that performs the load action. This
+	 * {@link Job} instance is then handed over to
+	 * <code>map.jobDispatcher</code>.
+	 * 
+	 * @param tilex
+	 * @param tiley
+	 * @param zoom
+	 */
+	public void addLoadRequest(int tilex, int tiley, int zoom);
+}
