Index: trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 9463)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 9464)
@@ -26,4 +26,5 @@
 import java.net.URL;
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -48,4 +49,5 @@
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
+import javax.swing.JSeparator;
 import javax.swing.JTextField;
 
@@ -86,4 +88,5 @@
 import org.openstreetmap.josm.io.WMSLayerImporter;
 import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 
 /**
@@ -126,4 +129,5 @@
 
     private final AttributionSupport attribution = new AttributionSupport();
+    private final TileHolder clickedTileHolder = new TileHolder();
 
     // needed public access for session exporter
@@ -246,5 +250,5 @@
     protected void redraw() {
         needRedraw = true;
-        Main.map.repaint();
+        if (isVisible()) Main.map.repaint();
     }
 
@@ -309,9 +313,7 @@
 
     private final class ShowTileInfoAction extends AbstractAction {
-        private final transient TileHolder clickedTileHolder;
-
-        private ShowTileInfoAction(TileHolder clickedTileHolder) {
-            super(tr("Show Tile Info"));
-            this.clickedTileHolder = clickedTileHolder;
+
+        private ShowTileInfoAction() {
+            super(tr("Show tile info"));
         }
 
@@ -375,7 +377,23 @@
     }
 
+    private class LoadTileAction extends AbstractAction {
+
+        private LoadTileAction() {
+            super(tr("Load tile"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent ae) {
+            Tile clickedTile = clickedTileHolder.getTile();
+            if (clickedTile != null) {
+                loadTile(clickedTile, true);
+                redraw();
+            }
+        }
+    }
+
     private class AutoZoomAction extends AbstractAction implements LayerAction {
         AutoZoomAction() {
-            super(tr("Auto Zoom"));
+            super(tr("Auto zoom"));
         }
 
@@ -383,4 +401,8 @@
         public void actionPerformed(ActionEvent ae) {
             autoZoom = !autoZoom;
+            if (autoZoom && getBestZoom() != currentZoomLevel) {
+                setZoomLevel(getBestZoom());
+                redraw();
+            }
         }
 
@@ -406,4 +428,5 @@
         public void actionPerformed(ActionEvent ae) {
             autoLoad = !autoLoad;
+            if (autoLoad) redraw();
         }
 
@@ -420,7 +443,30 @@
     }
 
+    private class ShowErrorsAction extends AbstractAction implements LayerAction {
+        ShowErrorsAction() {
+            super(tr("Show errors"));
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent ae) {
+            showErrors = !showErrors;
+            redraw();
+        }
+
+        public Component createMenuComponent() {
+            JCheckBoxMenuItem item = new JCheckBoxMenuItem(this);
+            item.setSelected(showErrors);
+            return item;
+        }
+
+        @Override
+        public boolean supportLayers(List<Layer> layers) {
+            return actionSupportLayers(layers);
+        }
+    }
+
     private class LoadAllTilesAction extends AbstractAction {
         LoadAllTilesAction() {
-            super(tr("Load All Tiles"));
+            super(tr("Load all tiles"));
         }
 
@@ -434,5 +480,5 @@
     private class LoadErroneusTilesAction extends AbstractAction {
         LoadErroneusTilesAction() {
-            super(tr("Load All Error Tiles"));
+            super(tr("Load all error tiles"));
         }
 
@@ -460,4 +506,5 @@
         ZoomToBestAction() {
             super(tr("Change resolution"));
+            setEnabled(!autoZoom && getBestZoom() != currentZoomLevel);
         }
 
@@ -465,4 +512,58 @@
         public void actionPerformed(ActionEvent ae) {
             setZoomLevel(getBestZoom());
+            redraw();
+        }
+    }
+
+    private class IncreaseZoomAction extends AbstractAction {
+        IncreaseZoomAction() {
+            super(tr("Increase zoom"));
+            setEnabled(!autoZoom && zoomIncreaseAllowed());
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent ae) {
+            increaseZoomLevel();
+            redraw();
+        }
+    }
+
+    private class DecreaseZoomAction extends AbstractAction {
+        DecreaseZoomAction() {
+            super(tr("Decrease zoom"));
+            setEnabled(!autoZoom && zoomDecreaseAllowed());
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent ae) {
+            decreaseZoomLevel();
+            redraw();
+        }
+    }
+
+    private class FlushTileCacheAction extends AbstractAction {
+        FlushTileCacheAction() {
+            super(tr("Flush tile cache"));
+            setEnabled(tileLoader instanceof CachedTileLoader);
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent ae) {
+            new PleaseWaitRunnable(tr("Flush tile cache")) {
+                @Override
+                protected void realRun() {
+                    clearTileCache(getProgressMonitor());
+                }
+
+                @Override
+                protected void finish() {
+                    // empty - flush is instaneus
+                }
+
+                @Override
+                protected void cancel() {
+                    // empty - flush is instaneus
+                }
+            }.run();
         }
     }
@@ -517,109 +618,7 @@
         initTileSource(this.tileSource);
 
-        // keep them final here, so we avoid namespace clutter in the class
-        final JPopupMenu tileOptionMenu = new JPopupMenu();
-        final TileHolder clickedTileHolder = new TileHolder();
-        Field autoZoomField;
-        Field autoLoadField;
-        Field showErrorsField;
-        try {
-            autoZoomField = AbstractTileSourceLayer.class.getField("autoZoom");
-            autoLoadField = AbstractTileSourceLayer.class.getDeclaredField("autoLoad");
-            showErrorsField = AbstractTileSourceLayer.class.getDeclaredField("showErrors");
-        } catch (NoSuchFieldException | SecurityException e) {
-            // shoud not happen
-            throw new RuntimeException(e);
-        }
-
+        autoLoad = PROP_DEFAULT_AUTOLOAD.get();
         autoZoom = PROP_DEFAULT_AUTOZOOM.get();
-        JCheckBoxMenuItem autoZoomPopup = new JCheckBoxMenuItem();
-        autoZoomPopup.setModel(new BooleanButtonModel(autoZoomField));
-        autoZoomPopup.setAction(new AutoZoomAction());
-        tileOptionMenu.add(autoZoomPopup);
-
-        autoLoad = PROP_DEFAULT_AUTOLOAD.get();
-        JCheckBoxMenuItem autoLoadPopup = new JCheckBoxMenuItem();
-        autoLoadPopup.setAction(new AutoLoadTilesAction());
-        autoLoadPopup.setModel(new BooleanButtonModel(autoLoadField));
-        tileOptionMenu.add(autoLoadPopup);
-
         showErrors = PROP_DEFAULT_SHOWERRORS.get();
-        JCheckBoxMenuItem showErrorsPopup = new JCheckBoxMenuItem();
-        showErrorsPopup.setAction(new AbstractAction(tr("Show Errors")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                showErrors = !showErrors;
-            }
-        });
-        showErrorsPopup.setModel(new BooleanButtonModel(showErrorsField));
-        tileOptionMenu.add(showErrorsPopup);
-
-        tileOptionMenu.add(new JMenuItem(new AbstractAction(tr("Load Tile")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                Tile clickedTile = clickedTileHolder.getTile();
-                if (clickedTile != null) {
-                    loadTile(clickedTile, true);
-                    redraw();
-                }
-            }
-        }));
-
-        tileOptionMenu.add(new JMenuItem(new ShowTileInfoAction(clickedTileHolder)));
-
-        tileOptionMenu.add(new JMenuItem(new LoadAllTilesAction()));
-        tileOptionMenu.add(new JMenuItem(new LoadErroneusTilesAction()));
-
-        // increase and decrease commands
-        tileOptionMenu.add(new JMenuItem(new AbstractAction(
-                tr("Increase zoom")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                increaseZoomLevel();
-                redraw();
-            }
-        }));
-
-        tileOptionMenu.add(new JMenuItem(new AbstractAction(
-                tr("Decrease zoom")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                decreaseZoomLevel();
-                redraw();
-            }
-        }));
-
-        tileOptionMenu.add(new JMenuItem(new AbstractAction(
-                tr("Snap to tile size")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                double newFactor = Math.sqrt(getScaleFactor(currentZoomLevel));
-                Main.map.mapView.zoomToFactor(newFactor);
-                redraw();
-            }
-        }));
-
-        tileOptionMenu.add(new JMenuItem(new AbstractAction(
-                tr("Flush Tile Cache")) {
-            @Override
-            public void actionPerformed(ActionEvent ae) {
-                new PleaseWaitRunnable(tr("Flush Tile Cache")) {
-                    @Override
-                    protected void realRun() {
-                        clearTileCache(getProgressMonitor());
-                    }
-
-                    @Override
-                    protected void finish() {
-                        // empty - flush is instaneus
-                    }
-
-                    @Override
-                    protected void cancel() {
-                        // empty - flush is instaneus
-                    }
-                }.run();
-            }
-        }));
 
         final MouseAdapter adapter = new MouseAdapter() {
@@ -629,5 +628,5 @@
                 if (e.getButton() == MouseEvent.BUTTON3) {
                     clickedTileHolder.setTile(getTileForPixelpos(e.getX(), e.getY()));
-                    tileOptionMenu.show(e.getComponent(), e.getX(), e.getY());
+                    new TileSourceLayerPopup().show(e.getComponent(), e.getX(), e.getY());
                 } else if (e.getButton() == MouseEvent.BUTTON1) {
                     attribution.handleAttribution(e.getPoint(), true);
@@ -661,4 +660,20 @@
         // start loading.
         Main.map.repaint(500);
+    }
+
+    public class TileSourceLayerPopup extends JPopupMenu {
+        public TileSourceLayerPopup() {
+
+            for (Action a : getCommonEntries()) {
+                if (a instanceof LayerAction) {
+                    add(((LayerAction) a).createMenuComponent());
+                } else {
+                    add(new JMenuItem(a));
+                }
+            }
+            add(new JSeparator());
+            add(new JMenuItem(new LoadTileAction()));
+            add(new JMenuItem(new ShowTileInfoAction()));
+        }
     }
 
@@ -781,5 +796,8 @@
 
     protected int getMinZoomLvl() {
-        return getMinZoomLvl(tileSource);
+        if (info.getMinZoom() != 0)
+            return checkMinZoomLvl(info.getMinZoom(), tileSource);
+        else
+            return getMinZoomLvl(tileSource);
     }
 
@@ -836,5 +854,9 @@
      */
     public boolean zoomDecreaseAllowed() {
-        return currentZoomLevel > this.getMinZoomLvl();
+        boolean zda = currentZoomLevel > this.getMinZoomLvl();
+        if (Main.isDebugEnabled()) {
+            Main.debug("zoomDecreaseAllowed(): " + zda + ' ' + currentZoomLevel + " vs. " + this.getMinZoomLvl());
+        }
+        return zda;
     }
 
@@ -1607,20 +1629,37 @@
     @Override
     public Action[] getMenuEntries() {
+        ArrayList<Action> actions = new ArrayList<Action>();
+        actions.addAll(Arrays.asList(getLayerListEntries()));
+        actions.addAll(Arrays.asList(getCommonEntries()));
+        actions.add(SeparatorLayerAction.INSTANCE);
+        actions.add(new LayerListPopup.InfoAction(this));
+        return actions.toArray(new Action[actions.size()]);
+    }
+
+    public Action[] getLayerListEntries() {
         return new Action[] {
-                LayerListDialog.getInstance().createActivateLayerAction(this),
-                LayerListDialog.getInstance().createShowHideLayerAction(),
-                LayerListDialog.getInstance().createDeleteLayerAction(),
-                SeparatorLayerAction.INSTANCE,
-                // color,
-                new OffsetAction(),
-                new RenameLayerAction(this.getAssociatedFile(), this),
-                SeparatorLayerAction.INSTANCE,
-                new AutoLoadTilesAction(),
-                new AutoZoomAction(),
-                new ZoomToBestAction(),
-                new ZoomToNativeLevelAction(),
-                new LoadErroneusTilesAction(),
-                new LoadAllTilesAction(),
-                new LayerListPopup.InfoAction(this)
+            LayerListDialog.getInstance().createActivateLayerAction(this),
+            LayerListDialog.getInstance().createShowHideLayerAction(),
+            LayerListDialog.getInstance().createDeleteLayerAction(),
+            SeparatorLayerAction.INSTANCE,
+            // color,
+            new OffsetAction(),
+            new RenameLayerAction(this.getAssociatedFile(), this),
+            SeparatorLayerAction.INSTANCE
+        };
+    }
+
+    public Action[] getCommonEntries() {
+        return new Action[] {
+            new AutoLoadTilesAction(),
+            new AutoZoomAction(),
+            new ShowErrorsAction(),
+            new IncreaseZoomAction(),
+            new DecreaseZoomAction(),
+            new ZoomToBestAction(),
+            new ZoomToNativeLevelAction(),
+            new FlushTileCacheAction(),
+            new LoadErroneusTilesAction(),
+            new LoadAllTilesAction()
         };
     }
