Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 28505)
@@ -661,4 +661,6 @@
     /**
      * Decreases the current zoom level by one
+     *
+     * @param mapPoint point to choose as center for new zoom level
      */
     public void zoomOut(Point mapPoint) {
@@ -666,4 +668,10 @@
     }
 
+    /**
+     * Set the zoom level and center point for display
+     *
+     * @param zoom new zoom level
+     * @param mapPoint point to choose as center for new zoom level
+     */
     public void setZoom(int zoom, Point mapPoint) {
         if (zoom > tileController.getTileSource().getMaxZoom() || zoom < tileController.getTileSource().getMinZoom()
@@ -678,4 +686,9 @@
     }
 
+    /**
+     * Set the zoom level
+     *
+     * @param zoom new zoom level
+     */
     public void setZoom(int zoom) {
         setZoom(zoom, new Point(getWidth() / 2, getHeight() / 2));
@@ -859,10 +872,7 @@
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener#getTileCache
-     * ()
+    /**
+     * Return tile information caching class
+     * @see TileLoaderListener#getTileCache()
      */
     public TileCache getTileCache() {
@@ -877,5 +887,5 @@
 
     /**
-     * @param listener to set
+     * @param listener listener to set
      */
     public void addJMVListener(JMapViewerEventListener listener) {
@@ -884,5 +894,5 @@
 
     /**
-     * @param listener to remove
+     * @param listener listener to remove
      */
     public void removeJMVListener(JMapViewerEventListener listener) {
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JobDispatcher.java	(revision 28505)
@@ -3,7 +3,9 @@
 //License: GPL. Copyright 2008 by Jan Peter Stotz
 
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.TimeUnit;
+
+import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
 
 /**
@@ -31,5 +33,5 @@
     }
 
-    protected BlockingQueue<Runnable> jobQueue = new LinkedBlockingQueue<Runnable>();
+    protected BlockingDeque<TileJob> jobQueue = new LinkedBlockingDeque<TileJob>();
 
     public static int WORKER_THREAD_MAX_COUNT = 8;
@@ -42,4 +44,9 @@
      */
     public static int WORKER_THREAD_TIMEOUT = 30;
+
+    /**
+     * Type of queue, FIFO if <code>false</code>, LIFO if <code>true</code>
+     */
+    protected boolean modeLIFO = false;
 
     /**
@@ -65,6 +72,36 @@
     }
 
-    public void addJob(Runnable job) {
+    /**
+     * Function to set the maximum number of workers for tile loading.
+     */
+    static public void setMaxWorkers(int workers) {
+        WORKER_THREAD_MAX_COUNT = workers;
+    }
+
+    /**
+     * Function to set the LIFO/FIFO mode for tile loading job.
+     *
+     * @param lifo <code>true</code> for LIFO mode, <code>false</code> for FIFO mode
+     */
+    public void setLIFO(boolean lifo) {
+        modeLIFO = lifo;
+    }
+
+    /**
+     * Adds a job to the queue.
+     * Jobs for tiles already contained in the are ignored (using a <code>null</code> tile
+     * prevents skipping).
+     *
+     * @param job the the job to be added
+     */
+    public void addJob(TileJob job) {
         try {
+            if(job.getTile() != null) {
+                for(TileJob oldJob : jobQueue) {
+                    if(oldJob.getTile() == job.getTile()) {
+                        return;
+                    }
+                }
+            }
             jobQueue.put(job);
             if (workerThreadIdleCount == 0 && workerThreadCount < WORKER_THREAD_MAX_COUNT)
@@ -108,8 +145,15 @@
                         workerThreadIdleCount++;
                     }
-                    if (firstThread)
-                        job = jobQueue.take();
-                    else
-                        job = jobQueue.poll(WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS);
+                    if(modeLIFO) {
+                        if (firstThread)
+                            job = jobQueue.takeLast();
+                        else
+                            job = jobQueue.pollLast(WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS);
+                    } else {
+                        if (firstThread)
+                            job = jobQueue.take();
+                        else
+                            job = jobQueue.poll(WORKER_THREAD_TIMEOUT, TimeUnit.SECONDS);
+                    }
                 } catch (InterruptedException e1) {
                     return;
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 28505)
@@ -163,5 +163,5 @@
          * Add the element to the head of the list.
          *
-         * @param new element to be added
+         * @param element new element to be added
          */
         public synchronized void addFirst(CacheEntry element) {
@@ -181,8 +181,7 @@
 
         /**
-         * Removes the specified elemntent form the list.
+         * Removes the specified element from the list.
          *
-         * @param element
-         *            to be removed
+         * @param element element to be removed
          */
         public synchronized void removeEntry(CacheEntry element) {
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java	(revision 28505)
@@ -27,5 +27,5 @@
 import java.util.logging.Logger;
 
-import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
@@ -90,6 +90,6 @@
      * Create a OSMFileCacheTileLoader with given cache directory.
      * If cacheDir is not set or invalid, IOException will be thrown.
-     * @param map
-     * @param cacheDir
+     * @param map the listener checking for tile load events (usually the map for display)
+     * @param cacheDir directory to store cached tiles
      */
     public OsmFileCacheTileLoader(TileLoaderListener map, File cacheDir) throws IOException  {
@@ -106,5 +106,5 @@
      * Create a OSMFileCacheTileLoader with system property temp dir.
      * If not set an IOException will be thrown.
-     * @param map
+     * @param map the listener checking for tile load events (usually the map for display)
      */
     public OsmFileCacheTileLoader(TileLoaderListener map) throws SecurityException, IOException {
@@ -113,6 +113,6 @@
 
     @Override
-    public Runnable createTileLoaderJob(final TileSource source, final int tilex, final int tiley, final int zoom) {
-        return new FileLoadJob(source, tilex, tiley, zoom);
+    public TileJob createTileLoaderJob(final Tile tile) {
+        return new FileLoadJob(tile);
     }
 
@@ -128,10 +128,8 @@
     }
     
-    protected class FileLoadJob implements Runnable {
+    protected class FileLoadJob implements TileJob {
         InputStream input = null;
 
-        int tilex, tiley, zoom;
         Tile tile;
-        TileSource source;
         File tileCacheDir;
         File tileFile = null;
@@ -139,16 +137,15 @@
         boolean fileTilePainted = false;
 
-        public FileLoadJob(TileSource source, int tilex, int tiley, int zoom) {
-            this.source = source;
-            this.tilex = tilex;
-            this.tiley = tiley;
-            this.zoom = zoom;
+        public FileLoadJob(Tile tile) {
+            this.tile = tile;
+        }
+
+        public Tile getTile() {
+            return tile;
         }
 
         public void run() {
-            TileCache cache = listener.getTileCache();
-            synchronized (cache) {
-                tile = cache.getTile(source, tilex, tiley, zoom);
-                if (tile == null || (tile.isLoaded() && !tile.hasError()) || tile.loading)
+            synchronized (tile) {
+                if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
                     return;
                 tile.loaded = false;
@@ -156,12 +153,16 @@
                 tile.loading = true;
             }
-            tileCacheDir = getSourceCacheDir(source);
-            if (loadTileFromFile())
+            tileCacheDir = getSourceCacheDir(tile.getSource());
+            if (loadTileFromFile()) {
                 return;
+            }
             if (fileTilePainted) {
-                Runnable job = new Runnable() {
+                TileJob job = new TileJob() {
 
                     public void run() {
                         loadOrUpdateTile();
+                    }
+                    public Tile getTile() {
+                        return tile;
                     }
                 };
@@ -174,8 +175,7 @@
         protected void loadOrUpdateTile() {
             try {
-                // log.finest("Loading tile from OSM: " + tile);
                 URLConnection urlConn = loadTileFromOsm(tile);
                 if (tileFile != null) {
-                    switch (source.getTileUpdate()) {
+                    switch (tile.getSource().getTileUpdate()) {
                     case IfModifiedSince:
                         urlConn.setIfModifiedSince(fileAge);
@@ -191,8 +191,8 @@
                     }
                 }
-                if (source.getTileUpdate() == TileUpdate.ETag || source.getTileUpdate() == TileUpdate.IfNoneMatch) {
+                if (tile.getSource().getTileUpdate() == TileUpdate.ETag || tile.getSource().getTileUpdate() == TileUpdate.IfNoneMatch) {
                     String fileETag = tile.getValue("etag");
                     if (fileETag != null) {
-                        switch (source.getTileUpdate()) {
+                        switch (tile.getSource().getTileUpdate()) {
                         case IfNoneMatch:
                             urlConn.addRequestProperty("If-None-Match", fileETag);
@@ -245,5 +245,8 @@
                 listener.tileLoadingFinished(tile, false);
                 if (input == null) {
-                    System.err.println("failed loading " + zoom + "/" + tilex + "/" + tiley + " " + e.getMessage());
+                    try {
+                        System.err.println("Failed loading " + tile.getUrl() +": " + e.getMessage());
+                    } catch(IOException i) {
+                    }
                 }
             } finally {
@@ -325,9 +328,9 @@
          * <code>LastModified</code> header:
          * <ul>
-         * <li>{@link OsmTileLoader#MAP_OSMA} - supported</li>
-         * <li>{@link OsmTileLoader#MAP_MAPNIK} - not supported</li>
+         * <li>{@link tilesources.OsmTileSource.CycleMap} - supported</li>
+         * <li>{@link tilesources.OsmTileSource.Mapnik} - not supported</li>
          * </ul>
          *
-         * @param fileAge
+         * @param fileAge time of the 
          * @return <code>true</code> if the tile on the server is newer than the
          *         file
@@ -368,5 +371,5 @@
         protected File getTileFile() {
             return new File(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile() + "_" + tile.getYtile() + "."
-                    + source.getTileType());
+                    + tile.getSource().getTileType());
         }
 
@@ -379,5 +382,5 @@
             try {
                 FileOutputStream f = new FileOutputStream(tileCacheDir + "/" + tile.getZoom() + "_" + tile.getXtile()
-                        + "_" + tile.getYtile() + "." + source.getTileType());
+                        + "_" + tile.getYtile() + "." + tile.getSource().getTileType());
                 f.write(rawData);
                 f.close();
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 28505)
@@ -29,6 +29,6 @@
      * TILE_WIDTH where TILE_WIDTH is the width of a tile in pixels
      *
-     * @param aZoomlevel
-     * @return
+     * @param aZoomlevel zoom level to request pixel data
+     * @return number of pixels
      */
     public static int getMaxPixels(int aZoomlevel) {
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 28505)
@@ -12,5 +12,5 @@
 import java.util.HashMap;
 
-import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
+import org.openstreetmap.gui.jmapviewer.interfaces.TileJob;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
@@ -39,15 +39,12 @@
     }
 
-    public Runnable createTileLoaderJob(final TileSource source, final int tilex, final int tiley, final int zoom) {
-        return new Runnable() {
+    public TileJob createTileLoaderJob(final Tile tile) {
+        return new TileJob() {
 
             InputStream input = null;
 
             public void run() {
-                TileCache cache = listener.getTileCache();
-                Tile tile;
-                synchronized (cache) {
-                    tile = cache.getTile(source, tilex, tiley, zoom);
-                    if (tile == null || (tile.isLoaded() && !tile.hasError()) || tile.loading)
+                synchronized (tile) {
+                    if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading())
                         return;
                     tile.loaded = false;
@@ -56,5 +53,4 @@
                 }
                 try {
-                    // Thread.sleep(500);
                     URLConnection conn = loadTileFromOsm(tile);
                     loadTileMetadata(tile, conn);
@@ -73,5 +69,8 @@
                     listener.tileLoadingFinished(tile, false);
                     if (input == null) {
-                        System.err.println("failed loading " + zoom + "/" + tilex + "/" + tiley + " " + e.getMessage());
+                        try {
+                            System.err.println("Failed loading " + tile.getUrl() +": " + e.getMessage());
+                        } catch(IOException i) {
+                        }
                     }
                 } finally {
@@ -81,4 +80,7 @@
             }
 
+            public Tile getTile() {
+                return tile;
+            }
         };
     }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/TileController.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/TileController.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/TileController.java	(revision 28505)
@@ -26,7 +26,7 @@
      * a load job is added to the working queue of {@link JobThread}.
      *
-     * @param tilex
-     * @param tiley
-     * @param zoom
+     * @param tilex the X position of the tile
+     * @param tiley the Y position of the tile
+     * @param zoom the zoom level of the tile
      * @return specified tile from the cache or <code>null</code> if the tile
      *         was not found in the cache.
@@ -43,5 +43,5 @@
         }
         if (!tile.isLoaded()) {
-            jobDispatcher.addJob(tileLoader.createTileLoaderJob(tileSource, tilex, tiley, zoom));
+            jobDispatcher.addJob(tileLoader.createTileLoaderJob(tile));
         }
         return tile;
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/MapRectangle.java	(revision 28505)
@@ -15,5 +15,4 @@
  * @see JMapViewer#addMapRectangle(MapRectangle)
  * @see JMapViewer#getMapRectangleList()
- * @date 21.06.2009S
  */
 public interface MapRectangle {
@@ -33,6 +32,7 @@
      * <code>bottomRight</code> are specifying the coordinates within <code>g</code>
      *
-     * @param g
-     * @param position
+     * @param g graphics structure for painting
+     * @param topLeft lop left edge of painting region
+     * @param bottomRight bottom right edge of painting region
      */
     public void paint(Graphics g, Point topLeft, Point bottomRight);
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileJob.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileJob.java	(revision 28505)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileJob.java	(revision 28505)
@@ -0,0 +1,21 @@
+package org.openstreetmap.gui.jmapviewer.interfaces;
+
+//License: GPL. Copyright 2012 by Dirk Stöcker
+
+import org.openstreetmap.gui.jmapviewer.Tile;
+
+/**
+ * Interface for implementing a tile loading job. Tiles are usually loaded via HTTP
+ * or from a file.
+ *
+ * @author Dirk Stöcker
+ */
+public interface TileJob extends Runnable {
+
+    /**
+     * Function to return the tile associated with the job
+     *
+     * @return {@link Tile} to be handled
+     */
+    public Tile getTile();
+}
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoader.java	(revision 28505)
@@ -2,4 +2,6 @@
 
 //License: GPL. Copyright 2008 by Jan Peter Stotz
+
+import org.openstreetmap.gui.jmapviewer.Tile;
 
 /**
@@ -12,15 +14,11 @@
 
     /**
-     * A typical {@link #createTileLoaderJob(int, int, int)} implementation
-     * should create and return a new {@link Job} instance that performs the
-     * load action.
+     * A typical implementation of this function should create and return a
+     * new {@link TileJob} instance that performs the load action.
      *
-     * @param tileLayerSource
-     * @param tilex
-     * @param tiley
-     * @param zoom
-     * @returns {@link Runnable} implementation that performs the desired load
+     * @param tile the tile to be loaded
+     * @return {@link TileJob} implementation that performs the desired load
      *          action.
      */
-    public Runnable createTileLoaderJob(TileSource tileLayerSource, int tilex, int tiley, int zoom);
+    public TileJob createTileLoaderJob(Tile tile);
 }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/TileLoaderListener.java	(revision 28505)
@@ -15,4 +15,10 @@
     public void tileLoadingFinished(Tile tile, boolean success);
 
+    /**
+     * Return the {@link TileCache} class containing {@link Tile}
+     * data for requested and loaded tiles
+     *
+     * @return tile information caching class
+     */
     public TileCache getTileCache();
 }
Index: applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/package.html
===================================================================
--- applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/package.html	(revision 28427)
+++ applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/package.html	(revision 28505)
@@ -1,5 +1,5 @@
 <html>
+<head><title>org.openstreetmap.gui.jmapviewer</title></head>
 <body>
-<h1>org.openstreetmap.gui.jmapviewer</h1>
 <p>This package and all sub-packages are belonging to the Java
 component <a href="http://wiki.openstreetmap.org/wiki/JMapViewer">JMapViewer</a>
@@ -9,6 +9,4 @@
 depends on other libraries or applications</b>. Only functions and methods
 provided by the runtime library of Java 5 should be used.</p>
-<h2>In particular, this concerns the developer of JOSM!</h2>
-<p>2009-08-10 Jan Peter Stotz jpstotz@gmx.de (maintainer of JMapViewer)</p>
 </body>
 </html>
