Ticket #12959: patch-mapview-add-state-getter.patch
| File patch-mapview-add-state-getter.patch, 30.5 KB (added by , 10 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/MapStatus.java
diff --git a/src/org/openstreetmap/josm/gui/MapStatus.java b/src/org/openstreetmap/josm/gui/MapStatus.java index c46580e..abb735a 100644
a b public final class MapStatus extends JPanel implements Helpful, Destroyable, Pre 386 386 return; // exit, if new parent. 387 387 388 388 // Do nothing, if required data is missing 389 if (ms.mousePos == null || mv. center== null) {389 if (ms.mousePos == null || mv.getCenter() == null) { 390 390 continue; 391 391 } 392 392 … … public final class MapStatus extends JPanel implements Helpful, Destroyable, Pre 867 867 868 868 @Override 869 869 public void mouseMoved(MouseEvent e) { 870 if (mv. center== null)870 if (mv.getCenter() == null) 871 871 return; 872 872 // Do not update the view if ctrl is pressed. 873 873 if ((e.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) == 0) { -
src/org/openstreetmap/josm/gui/MapView.java
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java index 5f4df08..cb22f7a 100644
a b LayerManager.LayerChangeListener, MainLayerManager.ActiveLayerChangeListener { 935 935 * @return <code>true</code> if the view can be drawn, <code>false</code> otherwise. 936 936 */ 937 937 public boolean prepareToDraw() { 938 updateLocationState(); 938 939 if (initialViewport != null) { 939 940 zoomTo(initialViewport); 940 941 initialViewport = null; -
src/org/openstreetmap/josm/gui/MapViewState.java
diff --git a/src/org/openstreetmap/josm/gui/MapViewState.java b/src/org/openstreetmap/josm/gui/MapViewState.java index a507f39..521d03d 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui; 3 3 4 import java.awt.Container; 4 5 import java.awt.Point; 6 import java.awt.geom.AffineTransform; 5 7 import java.awt.geom.Point2D; 6 8 import java.awt.geom.Point2D.Double; 7 9 8 import javax.swing. SwingUtilities;10 import javax.swing.JComponent; 9 11 10 12 import org.openstreetmap.josm.Main; 11 13 import org.openstreetmap.josm.data.Bounds; … … import org.openstreetmap.josm.data.ProjectionBounds; 13 15 import org.openstreetmap.josm.data.coor.EastNorth; 14 16 import org.openstreetmap.josm.data.coor.LatLon; 15 17 import org.openstreetmap.josm.data.projection.Projection; 18 import org.openstreetmap.josm.gui.download.DownloadDialog; 16 19 17 20 /** 18 21 * This class represents a state of the {@link MapView}. … … import org.openstreetmap.josm.data.projection.Projection; 21 24 */ 22 25 public class MapViewState { 23 26 24 private final Projection projection = Main.getProjection();27 private final Projection projection; 25 28 26 29 private final int viewWidth; 27 30 private final int viewHeight; … … public class MapViewState { 33 36 */ 34 37 private final EastNorth topLeft; 35 38 36 private final NavigatableComponent navigatableComponent; 39 private final Point topLeftOnScreen; 40 private final Point topLeftInWindow; 37 41 38 42 /** 39 * Create a new {@link MapViewState} object for the given map view. 40 * @param navigatableComponent The view. 43 * Create a new {@link MapViewState} 44 * @param projection The projection to use. 45 * @param viewWidth The view width 46 * @param viewHeight The view height 47 * @param scale The scale to use 48 * @param topLeft The top left corner in east/north space. 41 49 */ 42 public MapViewState(NavigatableComponent navigatableComponent) { 43 this.navigatableComponent = navigatableComponent; 44 viewWidth = navigatableComponent.getWidth(); 45 viewHeight = navigatableComponent.getHeight(); 46 47 scale = navigatableComponent.getScale(); 48 EastNorth center = navigatableComponent.getCenter(); 49 topLeft = new EastNorth(center.east() - viewWidth / 2.0 * scale, center.north() + viewHeight / 2.0 * scale); 50 private MapViewState(Projection projection, int viewWidth, int viewHeight, double scale, EastNorth topLeft) { 51 this.projection = projection; 52 this.scale = scale; 53 this.topLeft = topLeft; 54 55 this.viewWidth = viewWidth; 56 this.viewHeight = viewHeight; 57 topLeftInWindow = new Point(0, 0); 58 topLeftOnScreen = new Point(0, 0); 59 } 60 61 private MapViewState(EastNorth topLeft, MapViewState mapViewState) { 62 this.projection = mapViewState.projection; 63 this.scale = mapViewState.scale; 64 this.topLeft = topLeft; 65 66 viewWidth = mapViewState.viewWidth; 67 viewHeight = mapViewState.viewHeight; 68 topLeftInWindow = mapViewState.topLeftInWindow; 69 topLeftOnScreen = mapViewState.topLeftOnScreen; 70 } 71 72 private MapViewState(double scale, MapViewState mapViewState) { 73 this.projection = mapViewState.projection; 74 this.scale = scale; 75 this.topLeft = mapViewState.topLeft; 76 77 viewWidth = mapViewState.viewWidth; 78 viewHeight = mapViewState.viewHeight; 79 topLeftInWindow = mapViewState.topLeftInWindow; 80 topLeftOnScreen = mapViewState.topLeftOnScreen; 81 } 82 83 private MapViewState(JComponent position, MapViewState mapViewState) { 84 this.projection = mapViewState.projection; 85 this.scale = mapViewState.scale; 86 this.topLeft = mapViewState.topLeft; 87 88 viewWidth = position.getWidth(); 89 viewHeight = position.getHeight(); 90 topLeftInWindow = new Point(); 91 // better than using swing utils, since this allows us to use the mehtod if no screen is present. 92 Container component = position; 93 while (component != null) { 94 topLeftInWindow.x += component.getX(); 95 topLeftInWindow.y += component.getY(); 96 component = component.getParent(); 97 } 98 topLeftOnScreen = position.getLocationOnScreen(); 99 } 100 101 /** 102 * The scale in east/north units per pixel. 103 * @return The scale. 104 */ 105 public double getScale() { 106 return scale; 50 107 } 51 108 52 109 /** … … public class MapViewState { 109 166 } 110 167 111 168 /** 169 * Creates an affine transform that is used to convert the east/north coordinates to view coordinates. 170 * @return The affine transform. It should not be changed. 171 * @since xxx 172 */ 173 public AffineTransform getAffineTransform() { 174 return new AffineTransform(1.0 / scale, 0.0, 0.0, -1.0 / scale, topLeft.east() / scale, 175 topLeft.north() / scale); 176 } 177 178 /** 179 * Creates a new state that is the same as the current state except for that it is using a new center. 180 * @param newCenter The new center coordinate. 181 * @return The new state. 182 * @since xxx 183 */ 184 public MapViewState usingCenter(EastNorth newCenter) { 185 return movedTo(getCenter(), newCenter); 186 } 187 188 /** 189 * @param mapViewPoint The reference point. 190 * @param newEastNorthThere The east/north coordinate that should be there. 191 * @return The new state. 192 * @since xxx 193 */ 194 public MapViewState movedTo(MapViewPoint mapViewPoint, EastNorth newEastNorthThere) { 195 EastNorth delta = newEastNorthThere.subtract(mapViewPoint.getEastNorth()); 196 if (delta.distanceSq(0, 0) < .000001) { 197 return this; 198 } else { 199 return new MapViewState(topLeft.add(delta), this); 200 } 201 } 202 203 /** 204 * Creates a new state that is the same as the current state except for that it is using a new scale. 205 * @param newScale The new scale to use. 206 * @return The new state. 207 * @since xxx 208 */ 209 public MapViewState usingScale(double newScale) { 210 return new MapViewState(newScale, this); 211 } 212 213 /** 214 * Creates a new state that is the same as the current state except for that it is using the location of the given component. 215 * <p> 216 * The view is moved so that the center is the same as the old center. 217 * @param positon The new location to use. 218 * @return The new state. 219 * @since xxx 220 */ 221 public MapViewState usingLocation(JComponent positon) { 222 EastNorth center = this.getCenter().getEastNorth(); 223 return new MapViewState(positon, this).usingCenter(center); 224 } 225 226 /** 227 * 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 228 * before the view was added to the hirarchy. 229 * @param width The view width 230 * @param height The view height 231 * @return The state 232 * @since xxx 233 */ 234 public static MapViewState createDefaultState(int width, int height) { 235 Projection projection = Main.getProjection(); 236 double scale = projection.getDefaultZoomInPPD(); 237 MapViewState state = new MapViewState(projection, width, height, scale, new EastNorth(0, 0)); 238 EastNorth center = calculateDefaultCenter(); 239 return state.movedTo(state.getCenter(), center); 240 } 241 242 private static EastNorth calculateDefaultCenter() { 243 Bounds b = DownloadDialog.getSavedDownloadBounds(); 244 if (b == null) { 245 b = Main.getProjection().getWorldBoundsLatLon(); 246 } 247 return Main.getProjection().latlon2eastNorth(b.getCenter()); 248 } 249 250 /** 112 251 * A class representing a point in the map view. It allows to convert between the different coordinate systems. 113 252 * @author Michael Zangl 114 253 */ … … public class MapViewState { 131 270 * @return The point in window coordinates. 132 271 */ 133 272 public Point2D getInWindow() { 134 Point corner = SwingUtilities.convertPoint(navigatableComponent, new Point(0, 0), null); 135 return getUsingCorner(corner); 273 return getUsingCorner(topLeftInWindow); 136 274 } 137 275 138 276 /** … … public class MapViewState { 140 278 * @return The point in screen coordinates. 141 279 */ 142 280 public Point2D getOnScreen() { 143 Point corner = new Point(0, 0); 144 SwingUtilities.convertPointToScreen(corner, navigatableComponent); 145 return getUsingCorner(corner); 281 return getUsingCorner(topLeftOnScreen); 146 282 } 147 283 148 284 private Double getUsingCorner(Point corner) { … … public class MapViewState { 267 403 return b; 268 404 } 269 405 } 406 270 407 } -
src/org/openstreetmap/josm/gui/NavigatableComponent.java
diff --git a/src/org/openstreetmap/josm/gui/NavigatableComponent.java b/src/org/openstreetmap/josm/gui/NavigatableComponent.java index 631fa7a..6c6371a 100644
a b package org.openstreetmap.josm.gui; 4 4 import java.awt.Cursor; 5 5 import java.awt.Point; 6 6 import java.awt.Rectangle; 7 import java.awt.event.ComponentAdapter; 8 import java.awt.event.ComponentEvent; 9 import java.awt.event.HierarchyEvent; 10 import java.awt.event.HierarchyListener; 7 11 import java.awt.geom.AffineTransform; 8 12 import java.awt.geom.Point2D; 9 13 import java.nio.charset.StandardCharsets; … … import java.util.concurrent.CopyOnWriteArrayList; 24 28 import java.util.zip.CRC32; 25 29 26 30 import javax.swing.JComponent; 31 import javax.swing.SwingUtilities; 27 32 28 33 import org.openstreetmap.josm.Main; 29 34 import org.openstreetmap.josm.data.Bounds; … … import org.openstreetmap.josm.data.preferences.IntegerProperty; 47 52 import org.openstreetmap.josm.data.projection.Projection; 48 53 import org.openstreetmap.josm.data.projection.Projections; 49 54 import org.openstreetmap.josm.gui.MapViewState.MapViewPoint; 50 import org.openstreetmap.josm.gui.download.DownloadDialog;51 55 import org.openstreetmap.josm.gui.help.Helpful; 52 56 import org.openstreetmap.josm.gui.layer.NativeScaleLayer; 53 57 import org.openstreetmap.josm.gui.layer.NativeScaleLayer.Scale; … … public class NavigatableComponent extends JComponent implements Helpful { 134 138 } 135 139 } 136 140 137 private double scale = Main.getProjection().getDefaultZoomInPPD(); 138 /** 139 * Center n/e coordinate of the desired screen center. 140 */ 141 protected EastNorth center = calculateDefaultCenter(); 141 // The only events that may move/resize this map view are window movements or changes to the map view size. 142 // We can clean this up more by only recalculating the state on repaint. 143 private final HierarchyListener hierarchyListener = new HierarchyListener() { 144 @Override 145 public void hierarchyChanged(HierarchyEvent e) { 146 long interestingFlags = HierarchyEvent.ANCESTOR_MOVED | HierarchyEvent.SHOWING_CHANGED; 147 if ((e.getChangeFlags() & interestingFlags) != 0) { 148 updateLocationState(); 149 } 150 } 151 }; 152 153 private final ComponentAdapter componentListener = new ComponentAdapter() { 154 @Override 155 public void componentShown(ComponentEvent e) { 156 updateLocationState(); 157 } 158 159 @Override 160 public void componentResized(ComponentEvent e) { 161 updateLocationState(); 162 } 163 }; 142 164 143 165 protected transient ViewportData initialViewport; 144 166 145 167 protected final transient CursorManager cursorManager = new CursorManager(this); 146 168 147 169 /** 170 * The current state (scale, center, ...) of this map view. 171 */ 172 private MapViewState state; 173 174 /** 148 175 * Constructs a new {@code NavigatableComponent}. 149 176 */ 150 177 public NavigatableComponent() { 151 178 setLayout(null); 179 state = MapViewState.createDefaultState(getWidth(), getHeight()); 180 } 181 182 @Override 183 public void addNotify() { 184 updateLocationState(); 185 addHierarchyListener(hierarchyListener); 186 addComponentListener(componentListener); 187 super.addNotify(); 188 } 189 190 @Override 191 public void removeNotify() { 192 removeHierarchyListener(hierarchyListener); 193 removeComponentListener(componentListener); 194 super.removeNotify(); 152 195 } 153 196 154 197 /** … … public class NavigatableComponent extends JComponent implements Helpful { 157 200 */ 158 201 public void setNativeScaleLayer(NativeScaleLayer nativeScaleLayer) { 159 202 this.nativeScaleLayer = nativeScaleLayer; 160 zoomTo( center, scaleRound(scale));203 zoomTo(getCenter(), scaleRound(getScale())); 161 204 repaint(); 162 205 } 163 206 … … public class NavigatableComponent extends JComponent implements Helpful { 250 293 * Zoom in current view. Use configured zoom step and scaling settings. 251 294 */ 252 295 public void zoomIn() { 253 zoomTo( center, scaleZoomIn());296 zoomTo(getCenter(), scaleZoomIn()); 254 297 } 255 298 256 299 /** 257 300 * Zoom out current view. Use configured zoom step and scaling settings. 258 301 */ 259 302 public void zoomOut() { 260 zoomTo( center, scaleZoomOut());303 zoomTo(getCenter(), scaleZoomOut()); 261 304 } 262 305 263 306 protected DataSet getCurrentDataSet() { 264 307 return Main.main.getCurrentDataSet(); 265 308 } 266 309 267 private static EastNorth calculateDefaultCenter() { 268 Bounds b = DownloadDialog.getSavedDownloadBounds(); 269 if (b == null) { 270 b = Main.getProjection().getWorldBoundsLatLon(); 310 protected void updateLocationState() { 311 if (SwingUtilities.getWindowAncestor(this) != null && isShowing()) { 312 state = state.usingLocation(this); 271 313 } 272 return Main.getProjection().latlon2eastNorth(b.getCenter()); 314 } 315 316 /** 317 * Gets the current view state. This includes the scale, the current view area and the position. 318 * @return The current state. 319 */ 320 public MapViewState getState() { 321 return state; 273 322 } 274 323 275 324 /** … … public class NavigatableComponent extends JComponent implements Helpful { 338 387 * @return the current center of the viewport 339 388 */ 340 389 public EastNorth getCenter() { 341 return center;390 return state.getCenter().getEastNorth(); 342 391 } 343 392 344 393 /** … … public class NavigatableComponent extends JComponent implements Helpful { 349 398 * @return the current scale 350 399 */ 351 400 public double getScale() { 352 return s cale;401 return state.getScale(); 353 402 } 354 403 355 404 /** … … public class NavigatableComponent extends JComponent implements Helpful { 359 408 * @return Geographic coordinates from a specific pixel coordination on the screen. 360 409 */ 361 410 public EastNorth getEastNorth(int x, int y) { 362 return new EastNorth( 363 center.east() + (x - getWidth()/2.0)*scale, 364 center.north() - (y - getHeight()/2.0)*scale); 411 return state.getForView(x, y).getEastNorth(); 365 412 } 366 413 367 414 public ProjectionBounds getProjectionBounds() { 368 return new MapViewState(this).getViewArea().getProjectionBounds();415 return getState().getViewArea().getProjectionBounds(); 369 416 } 370 417 371 418 /* FIXME: replace with better method - used by MapSlider */ … … public class NavigatableComponent extends JComponent implements Helpful { 377 424 378 425 /* FIXME: replace with better method - used by Main to reset Bounds when projection changes, don't use otherwise */ 379 426 public Bounds getRealBounds() { 380 return new MapViewState(this).getViewArea().getCornerBounds();427 return getState().getViewArea().getCornerBounds(); 381 428 } 382 429 383 430 /** … … public class NavigatableComponent extends JComponent implements Helpful { 396 443 } 397 444 398 445 public ProjectionBounds getProjectionBounds(Rectangle r) { 399 MapViewState state = new MapViewState(this);446 MapViewState state = getState(); 400 447 MapViewPoint p1 = state.getForView(r.getMinX(), r.getMinY()); 401 448 MapViewPoint p2 = state.getForView(r.getMaxX(), r.getMaxY()); 402 449 return p1.rectTo(p2).getProjectionBounds(); … … public class NavigatableComponent extends JComponent implements Helpful { 411 458 } 412 459 413 460 public AffineTransform getAffineTransform() { 414 return new AffineTransform( 415 1.0/scale, 0.0, 0.0, -1.0/scale, getWidth()/2.0 - center.east()/scale, getHeight()/2.0 + center.north()/scale); 461 return getState().getAffineTransform(); 416 462 } 417 463 418 464 /** … … public class NavigatableComponent extends JComponent implements Helpful { 424 470 public Point2D getPoint2D(EastNorth p) { 425 471 if (null == p) 426 472 return new Point(); 427 double x = (p.east()-center.east())/scale + getWidth()/2d; 428 double y = (center.north()-p.north())/scale + getHeight()/2d; 429 return new Point2D.Double(x, y); 473 return getState().getPointFor(p).getInView(); 430 474 } 431 475 432 476 public Point2D getPoint2D(LatLon latlon) { … … public class NavigatableComponent extends JComponent implements Helpful { 512 556 LatLon ll2 = getLatLon(width / 2 + 50, height / 2); 513 557 if (ll1.isValid() && ll2.isValid() && b.contains(ll1) && b.contains(ll2)) { 514 558 double dm = ll1.greatCircleDistance(ll2); 515 double den = 100 * scale;559 double den = 100 * getScale(); 516 560 double scaleMin = 0.01 * den / dm / 100; 517 561 if (!Double.isInfinite(scaleMin) && newScale < scaleMin) { 518 562 newScale = scaleMin; … … public class NavigatableComponent extends JComponent implements Helpful { 520 564 } 521 565 522 566 // snap scale to imagery if needed 523 scale = scaleRound(scale);567 newScale = scaleRound(newScale); 524 568 525 if (!newCenter.equals( center) || !Utils.equalsEpsilon(scale, newScale)) {569 if (!newCenter.equals(getCenter()) || !Utils.equalsEpsilon(getScale(), newScale)) { 526 570 if (!initial) { 527 pushZoomUndo( center, scale);571 pushZoomUndo(getCenter(), getScale()); 528 572 } 529 573 zoomNoUndoTo(newCenter, newScale, initial); 530 574 } … … public class NavigatableComponent extends JComponent implements Helpful { 538 582 * @param initial true if this call initializes the viewport. 539 583 */ 540 584 private void zoomNoUndoTo(EastNorth newCenter, double newScale, boolean initial) { 541 if (!newCenter.equals( center)) {542 EastNorth oldCenter = center;543 center = newCenter;585 if (!newCenter.equals(getCenter())) { 586 EastNorth oldCenter = getCenter(); 587 state = state.usingCenter(newCenter); 544 588 if (!initial) { 545 589 firePropertyChange(PROPNAME_CENTER, oldCenter, newCenter); 546 590 } 547 591 } 548 if (!Utils.equalsEpsilon(scale, newScale)) { 549 double oldScale = scale; 550 scale = newScale; 592 if (!Utils.equalsEpsilon(getScale(), newScale)) { 593 double oldScale = getScale(); 594 state = state.usingScale(newScale); 595 // temporary. Zoom logic needs to be moved. 596 state = state.movedTo(state.getCenter(), newCenter); 551 597 if (!initial) { 552 598 firePropertyChange(PROPNAME_SCALE, oldScale, newScale); 553 599 } … … public class NavigatableComponent extends JComponent implements Helpful { 560 606 } 561 607 562 608 public void zoomTo(EastNorth newCenter) { 563 zoomTo(newCenter, scale);609 zoomTo(newCenter, getScale()); 564 610 } 565 611 566 612 public void zoomTo(LatLon newCenter) { … … public class NavigatableComponent extends JComponent implements Helpful { 575 621 // FIXME make these configurable. 576 622 final int fps = 20; // animation frames per second 577 623 final int speed = 1500; // milliseconds for full-screen-width pan 578 if (!newCenter.equals( center)) {579 final EastNorth oldCenter = center;580 final double distance = newCenter.distance(oldCenter) / scale;624 if (!newCenter.equals(getCenter())) { 625 final EastNorth oldCenter = getCenter(); 626 final double distance = newCenter.distance(oldCenter) / getScale(); 581 627 final double milliseconds = distance / getWidth() * speed; 582 628 final double frames = milliseconds * fps / 1000; 583 629 final EastNorth finalNewCenter = newCenter; … … public class NavigatableComponent extends JComponent implements Helpful { 600 646 } 601 647 602 648 public void zoomManyTimes(double x, double y, int times) { 603 double oldScale = scale;649 double oldScale = getScale(); 604 650 double newScale = scaleZoomManyTimes(times); 605 651 zoomToFactor(x, y, newScale / oldScale); 606 652 } 607 653 608 654 public void zoomToFactor(double x, double y, double factor) { 609 double newScale = scale*factor; 610 // New center position so that point under the mouse pointer stays the same place as it was before zooming 611 // You will get the formula by simplifying this expression: newCenter = oldCenter + mouseCoordinatesInNewZoom - mouseCoordinatesInOldZoom 612 zoomTo(new EastNorth( 613 center.east() - (x - getWidth()/2.0) * (newScale - scale), 614 center.north() + (y - getHeight()/2.0) * (newScale - scale)), 615 newScale); 655 double newScale = getScale()*factor; 656 EastNorth oldUnderMouse = getState().getForView(x, y).getEastNorth(); 657 MapViewState newState = getState().usingScale(newScale); 658 newState = newState.movedTo(newState.getForView(x, y), oldUnderMouse); 659 zoomTo(newState.getCenter().getEastNorth(), newScale); 616 660 } 617 661 618 662 public void zoomToFactor(EastNorth newCenter, double factor) { 619 zoomTo(newCenter, scale*factor);663 zoomTo(newCenter, getScale()*factor); 620 664 } 621 665 622 666 public void zoomToFactor(double factor) { 623 zoomTo( center, scale*factor);667 zoomTo(getCenter(), getScale()*factor); 624 668 } 625 669 626 670 public void zoomTo(ProjectionBounds box) { … … public class NavigatableComponent extends JComponent implements Helpful { 713 757 public void zoomPrevious() { 714 758 if (!zoomUndoBuffer.isEmpty()) { 715 759 ZoomData zoom = zoomUndoBuffer.pop(); 716 zoomRedoBuffer.push(new ZoomData( center, scale));760 zoomRedoBuffer.push(new ZoomData(getCenter(), getScale())); 717 761 zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false); 718 762 } 719 763 } … … public class NavigatableComponent extends JComponent implements Helpful { 721 765 public void zoomNext() { 722 766 if (!zoomRedoBuffer.isEmpty()) { 723 767 ZoomData zoom = zoomRedoBuffer.pop(); 724 zoomUndoBuffer.push(new ZoomData( center, scale));768 zoomUndoBuffer.push(new ZoomData(getCenter(), getScale())); 725 769 zoomNoUndoTo(zoom.getCenterEastNorth(), zoom.getScale(), false); 726 770 } 727 771 } … … public class NavigatableComponent extends JComponent implements Helpful { 1442 1486 * @return The projection to be used in calculating stuff. 1443 1487 */ 1444 1488 public Projection getProjection() { 1445 return Main.getProjection();1489 return state.getProjection(); 1446 1490 } 1447 1491 1448 1492 @Override … … public class NavigatableComponent extends JComponent implements Helpful { 1456 1500 * @return A unique ID, as long as viewport dimensions are the same 1457 1501 */ 1458 1502 public int getViewID() { 1459 String x = center.east() + '_' + center.north() + '_' + scale+ '_' +1503 String x = getCenter().east() + '_' + getCenter().north() + '_' + getScale() + '_' + 1460 1504 getWidth() + '_' + getHeight() + '_' + getProjection().toString(); 1461 1505 CRC32 id = new CRC32(); 1462 1506 id.update(x.getBytes(StandardCharsets.UTF_8)); -
test/unit/org/openstreetmap/josm/gui/MapViewStateTest.java
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 b package org.openstreetmap.josm.gui; 3 3 4 4 import static org.junit.Assert.assertEquals; 5 5 6 import java.awt.Rectangle;7 8 6 import org.junit.Before; 9 7 import org.junit.BeforeClass; 10 8 import org.junit.Test; … … import org.openstreetmap.josm.Main; 13 11 import org.openstreetmap.josm.data.coor.EastNorth; 14 12 import org.openstreetmap.josm.data.coor.LatLon; 15 13 import org.openstreetmap.josm.gui.MapViewState.MapViewPoint; 16 import org.openstreetmap.josm.gui.util.GuiHelper;17 14 18 15 /** 19 16 * Test {@link MapViewState} … … import org.openstreetmap.josm.gui.util.GuiHelper; 21 18 */ 22 19 public class MapViewStateTest { 23 20 24 private static final int HEIGHT = 200;25 21 private static final int WIDTH = 300; 26 private NavigatableComponent component;22 private static final int HEIGHT = 200; 27 23 private MapViewState state; 28 24 29 25 /** … … public class MapViewStateTest { 35 31 } 36 32 37 33 /** 38 * Create a new, fresh {@link NavigatableComponent}34 * Create the default state. 39 35 */ 40 36 @Before 41 37 public void setUp() { 42 component = new NavigatableComponent(); 43 component.setBounds(new Rectangle(WIDTH, HEIGHT)); 44 // wait for the event to be propagated. 45 GuiHelper.runInEDTAndWait(new Runnable() { 46 @Override 47 public void run() { 48 } 49 }); 50 state = new MapViewState(component); 38 state = MapViewState.createDefaultState(WIDTH, HEIGHT); 51 39 } 52 40 53 41 /** … … public class MapViewStateTest { 58 46 MapViewPoint center = state.getCenter(); 59 47 assertHasViewCoords(WIDTH / 2, HEIGHT / 2, center); 60 48 61 component.zoomTo(new LatLon(3, 4));49 MapViewState newState = state.movedTo(center, new EastNorth(3, 4)); 62 50 63 51 // state should not change, but new state should. 64 52 center = state.getCenter(); 65 53 assertHasViewCoords(WIDTH / 2, HEIGHT / 2, center); 66 54 67 center = new MapViewState(component).getCenter();68 assertEquals(" x", 3, center.getLatLon().lat(), 0.01);69 assertEquals(" y", 4, center.getLatLon().lon(), 0.01);55 center = newState.getCenter(); 56 assertEquals("east", 3, center.getEastNorth().east(), 0.01); 57 assertEquals("north", 4, center.getEastNorth().north(), 0.01); 70 58 } 71 59 72 60 private void assertHasViewCoords(double x, double y, MapViewPoint center) { … … public class MapViewStateTest { 108 96 */ 109 97 @Test 110 98 public void testPointConversions() { 111 MapViewPoint p = state.getForView(50, 70); 112 assertHasViewCoords(50, 70, p); 99 MapViewPoint p = state.getForView(WIDTH / 2, HEIGHT / 2); 100 assertHasViewCoords(WIDTH / 2, HEIGHT / 2, p); 101 113 102 114 103 EastNorth eastnorth = p.getEastNorth(); 115 EastNorth shouldEastNorth = component.getEastNorth(50, 70); 104 LatLon shouldLatLon = Main.getProjection().getWorldBoundsLatLon().getCenter(); 105 EastNorth shouldEastNorth = Main.getProjection().latlon2eastNorth(shouldLatLon); 116 106 assertEquals("east", shouldEastNorth.east(), eastnorth.east(), 0.01); 117 107 assertEquals("north", shouldEastNorth.north(), eastnorth.north(), 0.01); 118 108 MapViewPoint reversed = state.getPointFor(shouldEastNorth); 119 assertHasViewCoords( 50, 70, reversed);109 assertHasViewCoords(WIDTH / 2, HEIGHT / 2, reversed); 120 110 121 111 LatLon latlon = p.getLatLon(); 122 LatLon shouldLatLon = Main.getProjection().eastNorth2latlon(shouldEastNorth);123 112 assertEquals("lat", shouldLatLon.lat(), latlon.lat(), 0.01); 124 113 assertEquals("lon", shouldLatLon.lon(), latlon.lon(), 0.01); 125 114 -
test/unit/org/openstreetmap/josm/gui/NavigatableComponentTest.java
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 b package org.openstreetmap.josm.gui; 4 4 import static org.junit.Assert.assertEquals; 5 5 import static org.junit.Assert.assertThat; 6 6 7 import java.awt.Point; 7 8 import java.awt.Rectangle; 8 9 import java.awt.geom.Point2D; 9 10 11 import javax.swing.JFrame; 12 10 13 import org.CustomMatchers; 11 14 import org.junit.Before; 12 15 import org.junit.BeforeClass; … … public class NavigatableComponentTest { 43 46 */ 44 47 @Before 45 48 public void setUp() { 46 component = new NavigatableComponent(); 49 component = new NavigatableComponent() { 50 @Override 51 public Point getLocationOnScreen() { 52 return new Point(30, 40); 53 } 54 }; 47 55 component.setBounds(new Rectangle(WIDTH, HEIGHT)); 48 56 // wait for the event to be propagated. 49 57 GuiHelper.runInEDTAndWait(new Runnable() { … … public class NavigatableComponentTest { 51 59 public void run() { 52 60 } 53 61 }); 62 component.setVisible(true); 63 JFrame window = new JFrame(); 64 window.add(component); 65 component.updateLocationState(); 54 66 } 55 67 56 68 /**
