Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 5391)
@@ -372,4 +372,5 @@
             layer.addPropertyChangeListener(LayerListDialog.getInstance().getModel());
         }
+        layer.hookUpMapView();
         map.mapView.addLayer(layer);
     }
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 5391)
@@ -1288,5 +1288,5 @@
     }
 
-    private <T> Map<String,String> serializeStruct(T struct, Class<T> klass) {
+    public static <T> Map<String,String> serializeStruct(T struct, Class<T> klass) {
         T structPrototype;
         try {
@@ -1321,5 +1321,5 @@
     }
 
-    private <T> T deserializeStruct(Map<String,String> hash, Class<T> klass) {
+    public static <T> T deserializeStruct(Map<String,String> hash, Class<T> klass) {
         T struct = null;
         try {
Index: trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 5391)
@@ -3,6 +3,6 @@
 
 import java.awt.Image;
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -13,4 +13,8 @@
 import javax.swing.ImageIcon;
 
+import org.openstreetmap.gui.jmapviewer.Coordinate;
+import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
+import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
+import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
@@ -19,9 +23,4 @@
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
-import org.openstreetmap.gui.jmapviewer.Coordinate;
-import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
-import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
-import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
-import org.openstreetmap.josm.tools.CheckParameterUtil;
 
 /**
Index: trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/gui/layer/ImageryLayer.java	(revision 5391)
@@ -83,7 +83,7 @@
             icon = new ImageProvider(info.getIcon()).setOptional(true).
                     setMaxHeight(ICON_SIZE).setMaxWidth(ICON_SIZE).get();
-            if (icon == null) {
-                icon = ImageProvider.get("imagery_small");
-            }
+        }
+        if (icon == null) {
+            icon = ImageProvider.get("imagery_small");
         }
         this.sharpenLevel = PROP_SHARPEN_LEVEL.get();
Index: trunk/src/org/openstreetmap/josm/gui/layer/Layer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/gui/layer/Layer.java	(revision 5391)
@@ -126,4 +126,15 @@
 
     /**
+     * Initialization code, that depends on Main.map.mapView.
+     *
+     * It is always called in the event dispatching thread.
+     * Note that Main.map is null as long as no layer has been added, so do
+     * not execute code in the constructor, that assumes Main.map.mapView is
+     * not null. Instead override this method.
+     */
+    public void hookUpMapView() {
+    }
+
+    /**
      * Paint the dataset using the engine set.
      * @param mv The object that can translate GeoPoints to screen coordinates.
Index: trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java	(revision 5391)
@@ -38,5 +38,4 @@
 import javax.swing.JOptionPane;
 import javax.swing.JPopupMenu;
-import javax.swing.SwingUtilities;
 
 import org.openstreetmap.gui.jmapviewer.AttributionSupport;
@@ -471,5 +470,11 @@
             throw new IllegalStateException("Cannot create TMSLayer with non-TMS ImageryInfo");
         initTileSource(source);
-
+    }
+
+    /**
+     * Adds a context menu to the mapView.
+     */
+    @Override
+    public void hookUpMapView() {
         tileOptionMenu = new JPopupMenu();
 
@@ -521,5 +526,4 @@
             @Override
             public void actionPerformed(ActionEvent ae) {
-                //Main.debug("info tile: " + clickedTile);
                 if (clickedTile != null) {
                     showMetadataTile = clickedTile;
@@ -559,96 +563,86 @@
 
         // increase and decrease commands
-        tileOptionMenu.add(new JMenuItem(
-                new AbstractAction(tr("Increase zoom")) {
+        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 new_factor = Math.sqrt(getScaleFactor(currentZoomLevel));
+                Main.map.mapView.zoomToFactor(new_factor);
+                redraw();
+            }
+        }));
+
+        tileOptionMenu.add(new JMenuItem(new AbstractAction(
+                tr("Flush Tile Cache")) {
+            @Override
+            public void actionPerformed(ActionEvent ae) {
+                new PleaseWaitRunnable(tr("Flush Tile Cache")) {
                     @Override
-                    public void actionPerformed(ActionEvent ae) {
-                        increaseZoomLevel();
-                        redraw();
+                    protected void realRun() throws SAXException, IOException,
+                            OsmTransferException {
+                        clearTileCache(getProgressMonitor());
                     }
-                }));
-
-        tileOptionMenu.add(new JMenuItem(
-                new AbstractAction(tr("Decrease zoom")) {
+
                     @Override
-                    public void actionPerformed(ActionEvent ae) {
-                        decreaseZoomLevel();
-                        redraw();
+                    protected void finish() {
                     }
-                }));
-
-        // FIXME: currently ran in errors
-
-        tileOptionMenu.add(new JMenuItem(
-                new AbstractAction(tr("Snap to tile size")) {
+
                     @Override
-                    public void actionPerformed(ActionEvent ae) {
-                        double new_factor = Math.sqrt(getScaleFactor(currentZoomLevel));
-                        Main.map.mapView.zoomToFactor(new_factor);
-                        redraw();
+                    protected void cancel() {
                     }
-                }));
+                }.run();
+            }
+        }));
         // end of adding menu commands
 
-        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() throws SAXException, IOException,
-                                    OsmTransferException {
-                                clearTileCache(getProgressMonitor());
-                            }
-                            
-                            @Override
-                            protected void finish() {
-                            }
-                            
-                            @Override
-                            protected void cancel() {
-                            }
-                        }.run();
-                        
-                    }
-                }));
-        // end of adding menu commands
-
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                final MouseAdapter adapter = new MouseAdapter() {
-                    @Override
-                    public void mouseClicked(MouseEvent e) {
-                        if (!isVisible()) return;
-                        if (e.getButton() == MouseEvent.BUTTON3) {
-                            clickedTile = getTileForPixelpos(e.getX(), e.getY());
-                            tileOptionMenu.show(e.getComponent(), e.getX(), e.getY());
-                        } else if (e.getButton() == MouseEvent.BUTTON1) {
-                            attribution.handleAttribution(e.getPoint(), true);
-                        }
-                    }
-                };
-                Main.map.mapView.addMouseListener(adapter);
-
-                MapView.addLayerChangeListener(new LayerChangeListener() {
-                    @Override
-                    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-                        //
-                    }
-
-                    @Override
-                    public void layerAdded(Layer newLayer) {
-                        //
-                    }
-
-                    @Override
-                    public void layerRemoved(Layer oldLayer) {
-                        if (oldLayer == TMSLayer.this) {
-                            Main.map.mapView.removeMouseListener(adapter);
-                            MapView.removeLayerChangeListener(this);
-                        }
-                    }
-                });
+        final MouseAdapter adapter = new MouseAdapter() {
+            @Override
+            public void mouseClicked(MouseEvent e) {
+                if (!isVisible()) return;
+                if (e.getButton() == MouseEvent.BUTTON3) {
+                    clickedTile = getTileForPixelpos(e.getX(), e.getY());
+                    tileOptionMenu.show(e.getComponent(), e.getX(), e.getY());
+                } else if (e.getButton() == MouseEvent.BUTTON1) {
+                    attribution.handleAttribution(e.getPoint(), true);
+                }
+            }
+        };
+        Main.map.mapView.addMouseListener(adapter);
+
+        MapView.addLayerChangeListener(new LayerChangeListener() {
+            @Override
+            public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+                //
+            }
+
+            @Override
+            public void layerAdded(Layer newLayer) {
+                //
+            }
+
+            @Override
+            public void layerRemoved(Layer oldLayer) {
+                if (oldLayer == TMSLayer.this) {
+                    Main.map.mapView.removeMouseListener(adapter);
+                    MapView.removeLayerChangeListener(this);
+                }
             }
         });
Index: trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/gui/layer/WMSLayer.java	(revision 5391)
@@ -121,5 +121,5 @@
     protected boolean settingsChanged;
     protected ImageryInfo info;
-    protected final MapView mv;
+    protected MapView mv;
     public WmsCache cache;
     private AttributionSupport attribution = new AttributionSupport();
@@ -160,7 +160,20 @@
         super(info);
         imageSize = PROP_IMAGE_SIZE.get();
-        mv = Main.map.mapView;
         setBackgroundLayer(true); /* set global background variable */
         initializeImages();
+        this.info = new ImageryInfo(info);
+
+        attribution.initialize(this.info);
+
+        if(info.getUrl() != null) {
+            startGrabberThreads();
+        }
+        
+        Main.pref.addPreferenceChangeListener(this);
+    }
+
+    @Override
+    public void hookUpMapView() {
+        mv = Main.map.mapView;
         if (info.getUrl() != null) {
             for (WMSLayer layer: Main.map.mapView.getLayersOfType(WMSLayer.class)) {
@@ -175,5 +188,4 @@
             }
         }
-        this.info = new ImageryInfo(info);
         if(this.info.getPixelPerDegree() == 0.0) {
             this.info.setPixelPerDegree(getPPD());
@@ -181,46 +193,32 @@
         resolution = mv.getDist100PixelText();
 
-        attribution.initialize(this.info);
-
-        if(info.getUrl() != null) {
-            startGrabberThreads();
-        }
-
-
-        Main.pref.addPreferenceChangeListener(this);
-
-        SwingUtilities.invokeLater(new Runnable() {
+        final MouseAdapter adapter = new MouseAdapter() {
             @Override
-            public void run() {
-                final MouseAdapter adapter = new MouseAdapter() {
-                    @Override
-                    public void mouseClicked(MouseEvent e) {
-                        if (!isVisible()) return;
-                        if (e.getButton() == MouseEvent.BUTTON1) {
-                            attribution.handleAttribution(e.getPoint(), true);
-                        }
-                    }
-                };
-                Main.map.mapView.addMouseListener(adapter);
-
-                MapView.addLayerChangeListener(new LayerChangeListener() {
-                    @Override
-                    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
-                        //
-                    }
-
-                    @Override
-                    public void layerAdded(Layer newLayer) {
-                        //
-                    }
-
-                    @Override
-                    public void layerRemoved(Layer oldLayer) {
-                        if (oldLayer == WMSLayer.this) {
-                            Main.map.mapView.removeMouseListener(adapter);
-                            MapView.removeLayerChangeListener(this);
-                        }
-                    }
-                });
+            public void mouseClicked(MouseEvent e) {
+                if (!isVisible()) return;
+                if (e.getButton() == MouseEvent.BUTTON1) {
+                    attribution.handleAttribution(e.getPoint(), true);
+                }
+            }
+        };
+        Main.map.mapView.addMouseListener(adapter);
+
+        MapView.addLayerChangeListener(new LayerChangeListener() {
+            @Override
+            public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+                //
+            }
+
+            @Override
+            public void layerAdded(Layer newLayer) {
+                //
+            }
+
+            @Override
+            public void layerRemoved(Layer oldLayer) {
+                if (oldLayer == WMSLayer.this) {
+                    Main.map.mapView.removeMouseListener(adapter);
+                    MapView.removeLayerChangeListener(this);
+                }
             }
         });
Index: trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java	(revision 5391)
+++ trunk/src/org/openstreetmap/josm/io/session/ImagerySessionExporter.java	(revision 5391)
@@ -0,0 +1,90 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import java.awt.Component;
+import java.awt.GridBagLayout;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
+import org.openstreetmap.josm.gui.layer.ImageryLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.TMSLayer;
+import org.openstreetmap.josm.gui.layer.WMSLayer;
+import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport;
+import org.openstreetmap.josm.tools.GBC;
+import org.w3c.dom.Element;
+
+/**
+ * Session exporter for TMSLayer and WMSLayer.
+ */
+public class ImagerySessionExporter implements SessionLayerExporter {
+
+    private ImageryLayer layer;
+
+    public ImagerySessionExporter(ImageryLayer layer) {
+        this.layer = layer;
+    }
+
+    public ImagerySessionExporter(TMSLayer layer) {
+        this((ImageryLayer) layer);
+    }
+
+    public ImagerySessionExporter(WMSLayer layer) {
+        this((ImageryLayer) layer);
+    }
+
+    private JCheckBox export;
+
+    @Override
+    public Collection<Layer> getDependencies() {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public Component getExportPanel() {
+        final JPanel p = new JPanel(new GridBagLayout());
+        export = new JCheckBox();
+        export.setSelected(true);
+        final JLabel lbl = new JLabel(layer.getName(), layer.getIcon(), SwingConstants.LEFT);
+        lbl.setToolTipText(layer.getToolTipText());
+        p.add(export, GBC.std());
+        p.add(lbl, GBC.std());
+        p.add(GBC.glue(1,0), GBC.std().fill(GBC.HORIZONTAL));
+        return p;
+    }
+
+    @Override
+    public boolean shallExport() {
+        return export.isSelected();
+    }
+
+    @Override
+    public boolean requiresZip() {
+        return false;
+    }
+
+    @Override
+    public Element export(ExportSupport support) throws IOException {
+        Element layerElem = support.createElement("layer");
+        layerElem.setAttribute("type", "imagery");
+        layerElem.setAttribute("version", "0.1");
+        ImageryPreferenceEntry e = new ImageryPreferenceEntry(layer.getInfo());
+        Map<String,String> data = Preferences.serializeStruct(e, ImageryPreferenceEntry.class);
+        for (Map.Entry<String,String> entry : data.entrySet()) {
+            Element attrElem = support.createElement(entry.getKey());
+            layerElem.appendChild(attrElem);
+            attrElem.appendChild(support.createTextNode(entry.getValue()));
+        }
+        return layerElem;
+    }
+
+}
Index: trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 5391)
+++ trunk/src/org/openstreetmap/josm/io/session/ImagerySessionImporter.java	(revision 5391)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.imagery.ImageryInfo;
+import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
+import org.openstreetmap.josm.gui.layer.ImageryLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.io.session.SessionReader.ImportSupport;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Session importer for both TMSLayer and WMSLayer.
+ */
+public class ImagerySessionImporter implements SessionLayerImporter {
+
+    @Override
+    public Layer load(Element elem, ImportSupport support, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
+        String version = elem.getAttribute("version");
+        if (!"0.1".equals(version)) {
+            throw new IllegalDataException(tr("Version ''{0}'' of meta data for imagery layer is not supported. Expected: 0.1", version));
+        }
+        Map<String, String> attributes = new HashMap<String, String>();
+
+        NodeList nodes = elem.getChildNodes();
+
+        for (int i=0; i<nodes.getLength(); ++i) {
+            Node node = nodes.item(i);
+            if (node.getNodeType() == Node.ELEMENT_NODE) {
+                Element e = (Element) node;
+                attributes.put(e.getTagName(), e.getTextContent());
+            }
+        }
+        ImageryPreferenceEntry prefEntry = Preferences.deserializeStruct(attributes, ImageryPreferenceEntry.class);
+        ImageryInfo i = new ImageryInfo(prefEntry);
+        final ImageryLayer layer = ImageryLayer.create(i);
+        return layer;
+    }
+    
+}
Index: trunk/src/org/openstreetmap/josm/io/session/SessionLayerExporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionLayerExporter.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionLayerExporter.java	(revision 5391)
@@ -42,6 +42,6 @@
 
     /**
-     * Save meta data to the .jos file. Return a <layer> element.
-     * Use support to save files in the zip archive as needed.
+     * Save meta data to the .jos file. Return a layer XML element.
+     * Use <code>support</code> to save files in the zip archive as needed.
      */
     Element export(ExportSupport support) throws IOException;
Index: trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 5391)
@@ -56,4 +56,5 @@
     static {
         registerSessionLayerImporter("osm-data", OsmDataSessionImporter.class);
+        registerSessionLayerImporter("imagery", ImagerySessionImporter.class);
     }
 
@@ -166,5 +167,5 @@
 
         /**
-         * Return a File for a URI from a .jos file.
+         * Return a File for a URI from a .jos/.joz file.
          *
          * Returns null if the URI points to a file inside the zip archive.
Index: trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java	(revision 5390)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionWriter.java	(revision 5391)
@@ -34,4 +34,6 @@
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.TMSLayer;
+import org.openstreetmap.josm.gui.layer.WMSLayer;
 import org.openstreetmap.josm.tools.MultiMap;
 import org.openstreetmap.josm.tools.Utils;
@@ -43,4 +45,6 @@
     static {
         registerSessionLayerExporter(OsmDataLayer.class , OsmDataSessionExporter.class);
+        registerSessionLayerExporter(TMSLayer.class , ImagerySessionExporter.class);
+        registerSessionLayerExporter(WMSLayer.class , ImagerySessionExporter.class);
     }
 
