Index: /trunk/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java	(revision 12083)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/OffsetBookmark.java	(revision 12084)
@@ -7,9 +7,10 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Preferences.pref;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
@@ -19,65 +20,104 @@
     private static final List<OffsetBookmark> allBookmarks = new ArrayList<>();
 
-    public String projectionCode;
-    public String layerName;
-    public String name;
-    public double dx, dy;
-    public double centerX, centerY;
+    @pref private String projection_code;
+    @pref private String imagery_name;
+    @pref private String name;
+    @pref private double dx, dy;
+    @pref private double center_lon, center_lat;
 
     public boolean isUsable(ImageryLayer layer) {
-        if (projectionCode == null) return false;
-        if (!Main.getProjection().toCode().equals(projectionCode)) return false;
-        return layer.getInfo().getName().equals(layerName);
-    }
-
-    public OffsetBookmark(String projectionCode, String layerName, String name, double dx, double dy) {
-        this(projectionCode, layerName, name, dx, dy, 0, 0);
-    }
-
-    public OffsetBookmark(String projectionCode, String layerName, String name, double dx, double dy, double centerX, double centerY) {
-        this.projectionCode = projectionCode;
-        this.layerName = layerName;
+        if (projection_code == null) return false;
+        if (!Main.getProjection().toCode().equals(projection_code)) return false;
+        return layer.getInfo().getName().equals(imagery_name);
+    }
+
+    /**
+     * Construct new empty OffsetBookmark.
+     *
+     * Only used for preferences handling.
+     */
+    public OffsetBookmark() {
+        // do nothing
+    }
+
+    public OffsetBookmark(String projectionCode, String imageryName, String name, double dx, double dy) {
+        this(projectionCode, imageryName, name, dx, dy, 0, 0);
+    }
+
+    public OffsetBookmark(String projectionCode, String imageryName, String name, double dx, double dy, double centerLon, double centerLat) {
+        this.projection_code = projectionCode;
+        this.imagery_name = imageryName;
         this.name = name;
         this.dx = dx;
         this.dy = dy;
-        this.centerX = centerX;
-        this.centerY = centerY;
+        this.center_lon = centerLon;
+        this.center_lat = centerLat;
     }
 
     public OffsetBookmark(Collection<String> list) {
         List<String> array = new ArrayList<>(list);
-        this.projectionCode = array.get(0);
-        this.layerName = array.get(1);
+        this.projection_code = array.get(0);
+        this.imagery_name = array.get(1);
         this.name = array.get(2);
         this.dx = Double.parseDouble(array.get(3));
         this.dy = Double.parseDouble(array.get(4));
         if (array.size() >= 7) {
-            this.centerX = Double.parseDouble(array.get(5));
-            this.centerY = Double.parseDouble(array.get(6));
-        }
-        if (projectionCode == null) {
-            Main.error(tr("Projection ''{0}'' is not found, bookmark ''{1}'' is not usable", projectionCode, name));
-        }
-    }
-
-    public List<String> getInfoArray() {
-        List<String> res = new ArrayList<>(7);
-        if (projectionCode != null) {
-            res.add(projectionCode);
+            this.center_lon = Double.parseDouble(array.get(5));
+            this.center_lat = Double.parseDouble(array.get(6));
+        }
+        if (projection_code == null) {
+            Main.error(tr("Projection ''{0}'' is not found, bookmark ''{1}'' is not usable", projection_code, name));
+        }
+    }
+
+    public String getProjectionCode() {
+        return projection_code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getImageryName() {
+        return imagery_name;
+    }
+
+    public EastNorth getOffset() {
+        return new EastNorth(dx, dy);
+    }
+
+    public LatLon getCenter() {
+        return new LatLon(center_lat, center_lon);
+    }
+
+    public void setProjectionCode(String projectionCode) {
+        this.projection_code = projectionCode;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setImageryName(String imageryName) {
+        this.imagery_name = imageryName;
+    }
+
+    public void setOffset(EastNorth offset) {
+        this.dx = offset.east();
+        this.dy = offset.north();
+    }
+
+    public static void loadBookmarks() {
+        List<OffsetBookmark> bookmarks = Main.pref.getListOfStructs("imagery.offsetbookmarks", null, OffsetBookmark.class);
+        if (bookmarks == null) {
+            loadBookmarksOld();
+            saveBookmarks();
         } else {
-            res.add("");
-        }
-        res.add(layerName);
-        res.add(name);
-        res.add(String.valueOf(dx));
-        res.add(String.valueOf(dy));
-        if (centerX != 0 || centerY != 0) {
-            res.add(String.valueOf(centerX));
-            res.add(String.valueOf(centerY));
-        }
-        return res;
-    }
-
-    public static void loadBookmarks() {
+            allBookmarks.addAll(bookmarks);
+        }
+    }
+
+    // migration code - remove Nov. 2017
+    private static void loadBookmarksOld() {
         for (Collection<String> c : Main.pref.getArray("imagery.offsets",
                 Collections.<Collection<String>>emptySet())) {
@@ -87,9 +127,5 @@
 
     public static void saveBookmarks() {
-        List<Collection<String>> coll = new LinkedList<>();
-        for (OffsetBookmark b : allBookmarks) {
-            coll.add(b.getInfoArray());
-        }
-        Main.pref.putArray("imagery.offsets", coll);
+        Main.pref.putListOfStructs("imagery.offsetbookmarks", allBookmarks, OffsetBookmark.class);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 12083)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 12084)
@@ -54,4 +54,5 @@
 import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
@@ -783,8 +784,8 @@
 
         private static boolean confirmEulaAcceptance(PreferenceTabbedPane gui, String eulaUrl) {
-            URL url = null;
+            URL url;
             try {
                 url = new URL(eulaUrl.replaceAll("\\{lang\\}", LanguageInfo.getWikiLanguagePrefix()));
-                JosmEditorPane htmlPane = null;
+                JosmEditorPane htmlPane;
                 try {
                     htmlPane = new JosmEditorPane(url);
@@ -904,14 +905,14 @@
                 switch (column) {
                 case 0:
-                    if (info.projectionCode == null) return "";
-                    return info.projectionCode;
+                    if (info.getProjectionCode() == null) return "";
+                    return info.getProjectionCode();
                 case 1:
-                    return info.layerName;
+                    return info.getImageryName();
                 case 2:
-                    return info.name;
+                    return info.getName();
                 case 3:
-                    return info.dx;
+                    return info.getOffset().east();
                 case 4:
-                    return info.dy;
+                    return info.getOffset().north();
                 default:
                     throw new ArrayIndexOutOfBoundsException();
@@ -924,14 +925,16 @@
                 switch (column) {
                 case 1:
-                    info.layerName = o.toString();
+                    info.setImageryName(o.toString());
                     break;
                 case 2:
-                    info.name = o.toString();
+                    info.setName(o.toString());
                     break;
                 case 3:
-                    info.dx = Double.parseDouble((String) o);
+                    double dx = Double.parseDouble((String) o);
+                    info.setOffset(new EastNorth(dx, info.getOffset().north()));
                     break;
                 case 4:
-                    info.dy = Double.parseDouble((String) o);
+                    double dy = Double.parseDouble((String) o);
+                    info.setOffset(new EastNorth(info.getOffset().east(), dy));
                     break;
                 default:
