diff --git a/src/org/openstreetmap/josm/gui/MapStatus.java b/src/org/openstreetmap/josm/gui/MapStatus.java
index c46580e..abb735a 100644
--- a/src/org/openstreetmap/josm/gui/MapStatus.java
+++ b/src/org/openstreetmap/josm/gui/MapStatus.java
@@ -386,7 +386,7 @@ public final class MapStatus extends JPanel implements Helpful, Destroyable, Pre
                             return; // exit, if new parent.
 
                         // Do nothing, if required data is missing
-                        if (ms.mousePos == null || mv.center == null) {
+                        if (ms.mousePos == null || mv.getCenter() == null) {
                             continue;
                         }
 
@@ -867,7 +867,7 @@ public final class MapStatus extends JPanel implements Helpful, Destroyable, Pre
 
             @Override
             public void mouseMoved(MouseEvent e) {
-                if (mv.center == null)
+                if (mv.getCenter() == null)
                     return;
                 // Do not update the view if ctrl is pressed.
                 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == 0) {
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
index 5f4df08..cb22f7a 100644
--- a/src/org/openstreetmap/josm/gui/MapView.java
+++ b/src/org/openstreetmap/josm/gui/MapView.java
@@ -935,6 +935,7 @@ LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener {
      * @return <code>true</code> if the view can be drawn, <code>false</code> otherwise.
      */
     public boolean prepareToDraw() {
+        updateLocationState();
         if (initialViewport != null) {
             zoomTo(initialViewport);
             initialViewport = null;
diff --git a/src/org/openstreetmap/josm/gui/MapViewState.java b/src/org/openstreetmap/josm/gui/MapViewState.java
index a507f39..521d03d 100644
--- a/src/org/openstreetmap/josm/gui/MapViewState.java
+++ b/src/org/openstreetmap/josm/gui/MapViewState.java
@@ -1,11 +1,13 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui;
 
+import java.awt.Container;
 import java.awt.Point;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.awt.geom.Point2D.Double;
 
-import javax.swing.SwingUtilities;
+import javax.swing.JComponent;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
@@ -13,6 +15,7 @@ import org.openstreetmap.josm.data.ProjectionBounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.projection.Projection;
+import org.openstreetmap.josm.gui.download.DownloadDialog;
 
 /**
  * This class represents a state of the {@link MapView}.
@@ -21,7 +24,7 @@ import org.openstreetmap.josm.data.projection.Projection;
  */
 public class MapViewState {
 
-    private final Projection projection = Main.getProjection();
+    private final Projection projection;
 
     private final int viewWidth;
     private final int viewHeight;
@@ -33,20 +36,74 @@ public class MapViewState {
      */
     private final EastNorth topLeft;
 
-    private final NavigatableComponent navigatableComponent;
+    private final Point topLeftOnScreen;
+    private final Point topLeftInWindow;
 
     /**
-     * Create a new {@link MapViewState} object for the given map view.
-     * @param navigatableComponent The view.
+     * Create a new {@link MapViewState}
+     * @param projection The projection to use.
+     * @param viewWidth The view width
+     * @param viewHeight The view height
+     * @param scale The scale to use
+     * @param topLeft The top left corner in east/north space.
      */
-    public MapViewState(NavigatableComponent navigatableComponent) {
-        this.navigatableComponent = navigatableComponent;
-        viewWidth = navigatableComponent.getWidth();
-        viewHeight = navigatableComponent.getHeight();
-
-        scale = navigatableComponent.getScale();
-        EastNorth center = navigatableComponent.getCenter();
-        topLeft = new EastNorth(center.east() - viewWidth / 2.0 * scale, center.north() + viewHeight / 2.0 * scale);
+    private MapViewState(Projection projection, int viewWidth, int viewHeight, double scale, EastNorth topLeft) {
+        this.projection = projection;
+        this.scale = scale;
+        this.topLeft = topLeft;
+
+        this.viewWidth = viewWidth;
+        this.viewHeight = viewHeight;
+        topLeftInWindow = new Point(0, 0);
+        topLeftOnScreen = new Point(0, 0);
+    }
+
+    private MapViewState(EastNorth topLeft, MapViewState mapViewState) {
+        this.projection = mapViewState.projection;
+        this.scale = mapViewState.scale;
+        this.topLeft = topLeft;
+
+        viewWidth = mapViewState.viewWidth;
+        viewHeight = mapViewState.viewHeight;
+        topLeftInWindow = mapViewState.topLeftInWindow;
+        topLeftOnScreen = mapViewState.topLeftOnScreen;
+    }
+
+    private MapViewState(double scale, MapViewState mapViewState) {
+        this.projection = mapViewState.projection;
+        this.scale = scale;
+        this.topLeft = mapViewState.topLeft;
+
+        viewWidth = mapViewState.viewWidth;
+        viewHeight = mapViewState.viewHeight;
+        topLeftInWindow = mapViewState.topLeftInWindow;
+        topLeftOnScreen = mapViewState.topLeftOnScreen;
+    }
+
+    private MapViewState(JComponent position, MapViewState mapViewState) {
+        this.projection = mapViewState.projection;
+        this.scale = mapViewState.scale;
+        this.topLeft = mapViewState.topLeft;
+
+        viewWidth = position.getWidth();
+        viewHeight = position.getHeight();
+        topLeftInWindow = new Point();
+        // better than using swing utils, since this allows us to use the mehtod if no screen is present.
+        Container component = position;
+        while (component != null) {
+            topLeftInWindow.x += component.getX();
+            topLeftInWindow.y += component.getY();
+            component = component.getParent();
+        }
+        topLeftOnScreen = position.getLocationOnScreen();
+    }
+
+    /**
+     * The scale in east/north units per pixel.
+     * @return The scale.
+     */
+    public double getScale() {
+        return scale;
     }
 
     /**
@@ -109,6 +166,88 @@ public class MapViewState {
     }
 
     /**
+     * Creates an affine transform that is used to convert the east/north coordinates to view coordinates.
+     * @return The affine transform. It should not be changed.
+     * @since xxx
+     */
+    public AffineTransform getAffineTransform() {
+        return new AffineTransform(1.0 / scale, 0.0, 0.0, -1.0 / scale, topLeft.east() / scale,
+                topLeft.north() / scale);
+    }
+
+    /**
+     * Creates a new state that is the same as the current state except for that it is using a new center.
+     * @param newCenter The new center coordinate.
+     * @return The new state.
+     * @since xxx
+     */
+    public MapViewState usingCenter(EastNorth newCenter) {
+        return movedTo(getCenter(), newCenter);
+    }
+
+    /**
+     * @param mapViewPoint The reference point.
+     * @param newEastNorthThere The east/north coordinate that should be there.
+     * @return The new state.
+     * @since xxx
+     */
+    public MapViewState movedTo(MapViewPoint mapViewPoint, EastNorth newEastNorthThere) {
+        EastNorth delta = newEastNorthThere.subtract(mapViewPoint.getEastNorth());
+        if (delta.distanceSq(0, 0) < .000001) {
+            return this;
+        } else {
+            return new MapViewState(topLeft.add(delta), this);
+        }
+    }
+
+    /**
+     * Creates a new state that is the same as the current state except for that it is using a new scale.
+     * @param newScale The new scale to use.
+     * @return The new state.
+     * @since xxx
+     */
+    public MapViewState usingScale(double newScale) {
+        return new MapViewState(newScale, this);
+    }
+
+    /**
+     * Creates a new state that is the same as the current state except for that it is using the location of the given component.
+     * <p>
+     * The view is moved so that the center is the same as the old center.
+     * @param positon The new location to use.
+     * @return The new state.
+     * @since xxx
+     */
+    public MapViewState usingLocation(JComponent positon) {
+        EastNorth center = this.getCenter().getEastNorth();
+        return new MapViewState(positon, this).usingCenter(center);
+    }
+
+    /**
+     * Create the default {@link MapViewState} object for the given map view. The screen position won't be set so that this method can be used
+     * before the view was added to the hirarchy.
+     * @param width The view width
+     * @param height The view height
+     * @return The state
+     * @since xxx
+     */
+    public static MapViewState createDefaultState(int width, int height) {
+        Projection projection = Main.getProjection();
+        double scale = projection.getDefaultZoomInPPD();
+        MapViewState state = new MapViewState(projection, width, height, scale, new EastNorth(0, 0));
+        EastNorth center = calculateDefaultCenter();
+        return state.movedTo(state.getCenter(), center);
+    }
+
+    private static EastNorth calculateDefaultCenter() {
+        Bounds b = DownloadDialog.getSavedDownloadBounds();
+        if (b == null) {
+            b = Main.getProjection().getWorldBoundsLatLon();
+        }
+        return Main.getProjection().latlon2eastNorth(b.getCenter());
+    }
+
+    /**
      * A class representing a point in the map view. It allows to convert between the different coordinate systems.
      * @author Michael Zangl
      */
@@ -131,8 +270,7 @@ public class MapViewState {
          * @return The point in window coordinates.
          */
         public Point2D getInWindow() {
-            Point corner = SwingUtilities.convertPoint(navigatableComponent, new Point(0, 0), null);
-            return getUsingCorner(corner);
+            return getUsingCorner(topLeftInWindow);
         }
 
         /**
@@ -140,9 +278,7 @@ public class MapViewState {
          * @return The point in screen coordinates.
          */
         public Point2D getOnScreen() {
-            Point corner = new Point(0, 0);
-            SwingUtilities.convertPointToScreen(corner, navigatableComponent);
-            return getUsingCorner(corner);
+            return getUsingCorner(topLeftOnScreen);
         }
 
         private Double getUsingCorner(Point corner) {
@@ -267,4 +403,5 @@ public class MapViewState {
             return b;
         }
     }
+
 }
diff --git a/src/org/openstreetmap/josm/gui/NavigatableComponent.java b/src/org/openstreetmap/josm/gui/NavigatableComponent.java
index 631fa7a..6c6371a 100644
--- a/src/org/openstreetmap/josm/gui/NavigatableComponent.java
+++ b/src/org/openstreetmap/josm/gui/NavigatableComponent.java
@@ -4,6 +4,10 @@ package org.openstreetmap.josm.gui;
 import java.awt.Cursor;
 import java.awt.Point;
 import java.awt.Rectangle;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.HierarchyListener;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.nio.charset.StandardCharsets;
@@ -24,6 +28,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.zip.CRC32;
 
 import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
@@ -47,7 +52,6 @@ import org.openstreetmap.josm.data.preferences.IntegerProperty;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.projection.Projections;
 import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
-import org.openstreetmap.josm.gui.download.DownloadDialog;
 import org.openstreetmap.josm.gui.help.Helpful;
 import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
 import org.openstreetmap.josm.gui.layer.NativeScaleLayer.Scale;
@@ -134,21 +138,60 @@ public class NavigatableComponent extends JComponent implements Helpful {
         }
     }
 
-    private double scale = Main.getProjection().getDefaultZoomInPPD();
-    /**
-     * Center n/e coordinate of the desired screen center.
-     */
-    protected EastNorth center = calculateDefaultCenter();
+    // The only events that may move/resize this map view are window movements or changes to the map view size.
+    // We can clean this up more by only recalculating the state on repaint.
+    private final HierarchyListener hierarchyListener = new HierarchyListener() {
+        @Override
+        public void hierarchyChanged(HierarchyEvent e) {
+            long interestingFlags = HierarchyEvent.ANCESTOR_MOVED | HierarchyEvent.SHOWING_CHANGED;
+            if ((e.getChangeFlags() & interestingFlags) != 0) {
+                updateLocationState();
+            }
+        }
+    };
+
+    private final ComponentAdapter componentListener = new ComponentAdapter() {
+        @Override
+        public void componentShown(ComponentEvent e) {
+            updateLocationState();
+        }
+
+        @Override
+        public void componentResized(ComponentEvent e) {
+            updateLocationState();
+        }
+    };
 
     protected transient ViewportData initialViewport;
 
     protected final transient CursorManager cursorManager = new CursorManager(this);
 
     /**
+     * The current state (scale, center, ...) of this map view.
+     */
+    private MapViewState state;
+
+    /**
      * Constructs a new {@code NavigatableComponent}.
      */
     public NavigatableComponent() {
         setLayout(null);
+        state = MapViewState.createDefaultState(getWidth(), getHeight());
+    }
+
+    @Override
+    public void addNotify() {
+        updateLocationState();
+        addHierarchyListener(hierarchyListener);
+        addComponentListener(componentListener);
+        super.addNotify();
+    }
+
+    @Override
+    public void removeNotify() {
+        removeHierarchyListener(hierarchyListener);
+        removeComponentListener(componentListener);
+        super.removeNotify();
     }
 
     /**
@@ -157,7 +200,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
      */
     public void setNativeScaleLayer(NativeScaleLayer nativeScaleLayer) {
         this.nativeScaleLayer = nativeScaleLayer;
-        zoomTo(center, scaleRound(scale));
+        zoomTo(getCenter(), scaleRound(getScale()));
         repaint();
     }
 
@@ -250,26 +293,32 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * Zoom in current view. Use configured zoom step and scaling settings.
      */
     public void zoomIn() {
-        zoomTo(center, scaleZoomIn());
+        zoomTo(getCenter(), scaleZoomIn());
     }
 
     /**
      * Zoom out current view. Use configured zoom step and scaling settings.
      */
     public void zoomOut() {
-        zoomTo(center, scaleZoomOut());
+        zoomTo(getCenter(), scaleZoomOut());
     }
 
     protected DataSet getCurrentDataSet() {
         return Main.main.getCurrentDataSet();
     }
 
-    private static EastNorth calculateDefaultCenter() {
-        Bounds b = DownloadDialog.getSavedDownloadBounds();
-        if (b == null) {
-            b = Main.getProjection().getWorldBoundsLatLon();
+    protected void updateLocationState() {
+        if (SwingUtilities.getWindowAncestor(this) != null && isShowing()) {
+            state = state.usingLocation(this);
         }
-        return Main.getProjection().latlon2eastNorth(b.getCenter());
+    }
+
+    /**
+     * Gets the current view state. This includes the scale, the current view area and the position.
+     * @return The current state.
+     */
+    public MapViewState getState() {
+        return state;
     }
 
     /**
@@ -338,7 +387,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @return the current center of the viewport
      */
     public EastNorth getCenter() {
-        return center;
+        return state.getCenter().getEastNorth();
     }
 
     /**
@@ -349,7 +398,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @return the current scale
      */
     public double getScale() {
-        return scale;
+        return state.getScale();
     }
 
     /**
@@ -359,13 +408,11 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @return Geographic coordinates from a specific pixel coordination on the screen.
      */
     public EastNorth getEastNorth(int x, int y) {
-        return new EastNorth(
-                center.east() + (x - getWidth()/2.0)*scale,
-                center.north() - (y - getHeight()/2.0)*scale);
+        return state.getForView(x, y).getEastNorth();
     }
 
     public ProjectionBounds getProjectionBounds() {
-        return new MapViewState(this).getViewArea().getProjectionBounds();
+        return getState().getViewArea().getProjectionBounds();
     }
 
     /* FIXME: replace with better method - used by MapSlider */
@@ -377,7 +424,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
 
     /* FIXME: replace with better method - used by Main to reset Bounds when projection changes, don't use otherwise */
     public Bounds getRealBounds() {
-        return new MapViewState(this).getViewArea().getCornerBounds();
+        return getState().getViewArea().getCornerBounds();
     }
 
     /**
@@ -396,7 +443,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     }
 
     public ProjectionBounds getProjectionBounds(Rectangle r) {
-        MapViewState state = new MapViewState(this);
+        MapViewState state = getState();
         MapViewPoint p1 = state.getForView(r.getMinX(), r.getMinY());
         MapViewPoint p2 = state.getForView(r.getMaxX(), r.getMaxY());
         return p1.rectTo(p2).getProjectionBounds();
@@ -411,8 +458,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     }
 
     public AffineTransform getAffineTransform() {
-        return new AffineTransform(
-                1.0/scale, 0.0, 0.0, -1.0/scale, getWidth()/2.0 - center.east()/scale, getHeight()/2.0 + center.north()/scale);
+        return getState().getAffineTransform();
     }
 
     /**
@@ -424,9 +470,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     public Point2D getPoint2D(EastNorth p) {
         if (null == p)
             return new Point();
-        double x = (p.east()-center.east())/scale + getWidth()/2d;
-        double y = (center.north()-p.north())/scale + getHeight()/2d;
-        return new Point2D.Double(x, y);
+        return getState().getPointFor(p).getInView();
     }
 
     public Point2D getPoint2D(LatLon latlon) {
@@ -512,7 +556,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
         LatLon ll2 = getLatLon(width / 2 + 50, height / 2);
         if (ll1.isValid() && ll2.isValid() && b.contains(ll1) && b.contains(ll2)) {
             double dm = ll1.greatCircleDistance(ll2);
-            double den = 100 * scale;
+            double den = 100 * getScale();
             double scaleMin = 0.01 * den / dm / 100;
             if (!Double.isInfinite(scaleMin) && newScale < scaleMin) {
                 newScale = scaleMin;
@@ -520,11 +564,11 @@ public class NavigatableComponent extends JComponent implements Helpful {
         }
 
         // snap scale to imagery if needed
-        scale = scaleRound(scale);
+        newScale = scaleRound(newScale);
 
-        if (!newCenter.equals(center) || !Utils.equalsEpsilon(scale, newScale)) {
+        if (!newCenter.equals(getCenter()) || !Utils.equalsEpsilon(getScale(), newScale)) {
             if (!initial) {
-                pushZoomUndo(center, scale);
+                pushZoomUndo(getCenter(), getScale());
             }
             zoomNoUndoTo(newCenter, newScale, initial);
         }
@@ -538,16 +582,18 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @param initial true if this call initializes the viewport.
      */
     private void zoomNoUndoTo(EastNorth newCenter, double newScale, boolean initial) {
-        if (!newCenter.equals(center)) {
-            EastNorth oldCenter = center;
-            center = newCenter;
+        if (!newCenter.equals(getCenter())) {
+            EastNorth oldCenter = getCenter();
+            state = state.usingCenter(newCenter);
             if (!initial) {
                 firePropertyChange(PROPNAME_CENTER, oldCenter, newCenter);
             }
         }
-        if (!Utils.equalsEpsilon(scale, newScale)) {
-            double oldScale = scale;
-            scale = newScale;
+        if (!Utils.equalsEpsilon(getScale(), newScale)) {
+            double oldScale = getScale();
+            state = state.usingScale(newScale);
+            // temporary. Zoom logic needs to be moved.
+            state = state.movedTo(state.getCenter(), newCenter);
             if (!initial) {
                 firePropertyChange(PROPNAME_SCALE, oldScale, newScale);
             }
@@ -560,7 +606,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     }
 
     public void zoomTo(EastNorth newCenter) {
-        zoomTo(newCenter, scale);
+        zoomTo(newCenter, getScale());
     }
 
     public void zoomTo(LatLon newCenter) {
@@ -575,9 +621,9 @@ public class NavigatableComponent extends JComponent implements Helpful {
         // FIXME make these configurable.
         final int fps = 20;     // animation frames per second
         final int speed = 1500; // milliseconds for full-screen-width pan
-        if (!newCenter.equals(center)) {
-            final EastNorth oldCenter = center;
-            final double distance = newCenter.distance(oldCenter) / scale;
+        if (!newCenter.equals(getCenter())) {
+            final EastNorth oldCenter = getCenter();
+            final double distance = newCenter.distance(oldCenter) / getScale();
             final double milliseconds = distance / getWidth() * speed;
             final double frames = milliseconds * fps / 1000;
             final EastNorth finalNewCenter = newCenter;
@@ -600,27 +646,25 @@ public class NavigatableComponent extends JComponent implements Helpful {
     }
 
     public void zoomManyTimes(double x, double y, int times) {
-        double oldScale = scale;
+        double oldScale = getScale();
         double newScale = scaleZoomManyTimes(times);
         zoomToFactor(x, y, newScale / oldScale);
     }
 
     public void zoomToFactor(double x, double y, double factor) {
-        double newScale = scale*factor;
-        // New center position so that point under the mouse pointer stays the same place as it was before zooming
-        // You will get the formula by simplifying this expression: newCenter = oldCenter + mouseCoordinatesInNewZoom - mouseCoordinatesInOldZoom
-        zoomTo(new EastNorth(
-                center.east() - (x - getWidth()/2.0) * (newScale - scale),
-                center.north() + (y - getHeight()/2.0) * (newScale - scale)),
-                newScale);
+        double newScale = getScale()*factor;
+        EastNorth oldUnderMouse = getState().getForView(x, y).getEastNorth();
+        MapViewState newState = getState().usingScale(newScale);
+        newState = newState.movedTo(newState.getForView(x, y), oldUnderMouse);
+        zoomTo(newState.getCenter().getEastNorth(), newScale);
     }
 
     public void zoomToFactor(EastNorth newCenter, double factor) {
-        zoomTo(newCenter, scale*factor);
+        zoomTo(newCenter, getScale()*factor);
     }
 
     public void zoomToFactor(double factor) {
-        zoomTo(center, scale*factor);
+        zoomTo(getCenter(), getScale()*factor);
     }
 
     public void zoomTo(ProjectionBounds box) {
@@ -713,7 +757,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     public void zoomPrevious() {
         if (!zoomUndoBuffer.isEmpty()) {
             ZoomData zoom = zoomUndoBuffer.pop();
-            zoomRedoBuffer.push(new ZoomData(center, scale));
+            zoomRedoBuffer.push(new ZoomData(getCenter(), getScale()));
             zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false);
         }
     }
@@ -721,7 +765,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
     public void zoomNext() {
         if (!zoomRedoBuffer.isEmpty()) {
             ZoomData zoom = zoomRedoBuffer.pop();
-            zoomUndoBuffer.push(new ZoomData(center, scale));
+            zoomUndoBuffer.push(new ZoomData(getCenter(), getScale()));
             zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false);
         }
     }
@@ -1442,7 +1486,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @return The projection to be used in calculating stuff.
      */
     public Projection getProjection() {
-        return Main.getProjection();
+        return state.getProjection();
     }
 
     @Override
@@ -1456,7 +1500,7 @@ public class NavigatableComponent extends JComponent implements Helpful {
      * @return A unique ID, as long as viewport dimensions are the same
      */
     public int getViewID() {
-        String x = center.east() + '_' + center.north() + '_' + scale + '_' +
+        String x = getCenter().east() + '_' + getCenter().north() + '_' + getScale() + '_' +
                 getWidth() + '_' + getHeight() + '_' + getProjection().toString();
         CRC32 id = new CRC32();
         id.update(x.getBytes(StandardCharsets.UTF_8));
diff --git a/test/unit/org/openstreetmap/josm/gui/MapViewStateTest.java b/test/unit/org/openstreetmap/josm/gui/MapViewStateTest.java
index f8324a8..334a020 100644
--- a/test/unit/org/openstreetmap/josm/gui/MapViewStateTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/MapViewStateTest.java
@@ -3,8 +3,6 @@ package org.openstreetmap.josm.gui;
 
 import static org.junit.Assert.assertEquals;
 
-import java.awt.Rectangle;
-
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -13,7 +11,6 @@ import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.coor.EastNorth;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.gui.MapViewState.MapViewPoint;
-import org.openstreetmap.josm.gui.util.GuiHelper;
 
 /**
  * Test {@link MapViewState}
@@ -21,9 +18,8 @@ import org.openstreetmap.josm.gui.util.GuiHelper;
  */
 public class MapViewStateTest {
 
-    private static final int HEIGHT = 200;
     private static final int WIDTH = 300;
-    private NavigatableComponent component;
+    private static final int HEIGHT = 200;
     private MapViewState state;
 
     /**
@@ -35,19 +31,11 @@ public class MapViewStateTest {
     }
 
     /**
-     * Create a new, fresh {@link NavigatableComponent}
+     * Create the default state.
      */
     @Before
     public void setUp() {
-        component = new NavigatableComponent();
-        component.setBounds(new Rectangle(WIDTH, HEIGHT));
-        // wait for the event to be propagated.
-        GuiHelper.runInEDTAndWait(new Runnable() {
-            @Override
-            public void run() {
-            }
-        });
-        state = new MapViewState(component);
+        state = MapViewState.createDefaultState(WIDTH, HEIGHT);
     }
 
     /**
@@ -58,15 +46,15 @@ public class MapViewStateTest {
         MapViewPoint center = state.getCenter();
         assertHasViewCoords(WIDTH / 2, HEIGHT / 2, center);
 
-        component.zoomTo(new LatLon(3, 4));
+        MapViewState newState = state.movedTo(center, new EastNorth(3, 4));
 
         // state should not change, but new state should.
         center = state.getCenter();
         assertHasViewCoords(WIDTH / 2, HEIGHT / 2, center);
 
-        center = new MapViewState(component).getCenter();
-        assertEquals("x", 3, center.getLatLon().lat(), 0.01);
-        assertEquals("y", 4, center.getLatLon().lon(), 0.01);
+        center = newState.getCenter();
+        assertEquals("east", 3, center.getEastNorth().east(), 0.01);
+        assertEquals("north", 4, center.getEastNorth().north(), 0.01);
     }
 
     private void assertHasViewCoords(double x, double y, MapViewPoint center) {
@@ -108,18 +96,19 @@ public class MapViewStateTest {
      */
     @Test
     public void testPointConversions() {
-        MapViewPoint p = state.getForView(50, 70);
-        assertHasViewCoords(50, 70, p);
+        MapViewPoint p = state.getForView(WIDTH / 2, HEIGHT / 2);
+        assertHasViewCoords(WIDTH / 2, HEIGHT / 2, p);
+
 
         EastNorth eastnorth = p.getEastNorth();
-        EastNorth shouldEastNorth = component.getEastNorth(50, 70);
+        LatLon shouldLatLon = Main.getProjection().getWorldBoundsLatLon().getCenter();
+        EastNorth shouldEastNorth = Main.getProjection().latlon2eastNorth(shouldLatLon);
         assertEquals("east", shouldEastNorth.east(), eastnorth.east(), 0.01);
         assertEquals("north", shouldEastNorth.north(), eastnorth.north(), 0.01);
         MapViewPoint reversed = state.getPointFor(shouldEastNorth);
-        assertHasViewCoords(50, 70, reversed);
+        assertHasViewCoords(WIDTH / 2, HEIGHT / 2, reversed);
 
         LatLon latlon = p.getLatLon();
-        LatLon shouldLatLon = Main.getProjection().eastNorth2latlon(shouldEastNorth);
         assertEquals("lat", shouldLatLon.lat(), latlon.lat(), 0.01);
         assertEquals("lon", shouldLatLon.lon(), latlon.lon(), 0.01);
 
diff --git a/test/unit/org/openstreetmap/josm/gui/NavigatableComponentTest.java b/test/unit/org/openstreetmap/josm/gui/NavigatableComponentTest.java
index 2680d57..2d8bad6 100644
--- a/test/unit/org/openstreetmap/josm/gui/NavigatableComponentTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/NavigatableComponentTest.java
@@ -4,9 +4,12 @@ package org.openstreetmap.josm.gui;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertThat;
 
+import java.awt.Point;
 import java.awt.Rectangle;
 import java.awt.geom.Point2D;
 
+import javax.swing.JFrame;
+
 import org.CustomMatchers;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -43,7 +46,12 @@ public class NavigatableComponentTest {
      */
     @Before
     public void setUp() {
-        component = new NavigatableComponent();
+        component = new NavigatableComponent() {
+            @Override
+            public Point getLocationOnScreen() {
+                return new Point(30, 40);
+            }
+        };
         component.setBounds(new Rectangle(WIDTH, HEIGHT));
         // wait for the event to be propagated.
         GuiHelper.runInEDTAndWait(new Runnable() {
@@ -51,6 +59,10 @@ public class NavigatableComponentTest {
             public void run() {
             }
         });
+        component.setVisible(true);
+        JFrame window = new JFrame();
+        window.add(component);
+        component.updateLocationState();
     }
 
     /**
