Changeset 13181 in josm


Ignore:
Timestamp:
2017-12-02T15:13:32+01:00 (13 days ago)
Author:
Don-vip
Message:

fix #15599 - Improvements for testing painting (last patches by ris)

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapViewState.java

    r13175 r13181  
    33
    44import java.awt.Container;
     5import java.awt.GraphicsEnvironment;
    56import java.awt.Point;
    67import java.awt.geom.AffineTransform;
     
    145146
    146147    private static Point findTopLeftOnScreen(JComponent position) {
    147         try {
    148             return position.getLocationOnScreen();
    149         } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
    150             throw BugReport.intercept(e).put("position", position).put("parent", position::getParent);
     148        if (GraphicsEnvironment.isHeadless()) {
     149            // in our imaginary universe the window is always (10, 10) from the top left of the screen
     150            Point topLeftInWindow = findTopLeftInWindow(position);
     151            return new Point(topLeftInWindow.x + 10, topLeftInWindow.y + 10);
     152        } else {
     153            try {
     154                return position.getLocationOnScreen();
     155            } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
     156                throw BugReport.intercept(e).put("position", position).put("parent", position::getParent);
     157            }
    151158        }
    152159    }
  • trunk/src/org/openstreetmap/josm/gui/NavigatableComponent.java

    r13154 r13181  
    33
    44import java.awt.Cursor;
     5import java.awt.GraphicsEnvironment;
    56import java.awt.Point;
    67import java.awt.Rectangle;
     
    320321
    321322    protected boolean isVisibleOnScreen() {
    322         return SwingUtilities.getWindowAncestor(this) != null && isShowing();
     323        return GraphicsEnvironment.isHeadless() || (
     324            SwingUtilities.getWindowAncestor(this) != null && isShowing()
     325        );
    323326    }
    324327
  • trunk/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java

    r13172 r13181  
    22package org.openstreetmap.josm.gui.dialogs;
    33
     4import static java.util.concurrent.TimeUnit.MILLISECONDS;
    45import static org.junit.Assert.assertEquals;
    56import static org.junit.Assert.assertFalse;
     
    78import static org.junit.Assert.fail;
    89
    9 import static java.util.concurrent.TimeUnit.MILLISECONDS;
    10 
    1110import java.awt.Color;
    1211import java.awt.Component;
    1312import java.awt.Graphics2D;
     13import java.awt.event.ComponentEvent;
    1414import java.awt.image.BufferedImage;
     15import java.util.Arrays;
     16import java.util.Map;
     17import java.util.concurrent.Callable;
     18import java.util.regex.Matcher;
    1519
    1620import javax.swing.JMenuItem;
    1721import javax.swing.JPopupMenu;
    1822
    19 import java.util.concurrent.Callable;
    20 
     23import org.awaitility.Awaitility;
    2124import org.junit.Rule;
    2225import org.junit.Test;
    2326import org.openstreetmap.josm.Main;
    2427import org.openstreetmap.josm.TestUtils;
     28import org.openstreetmap.josm.data.Bounds;
     29import org.openstreetmap.josm.data.projection.Projections;
     30import org.openstreetmap.josm.gui.MainApplication;
     31import org.openstreetmap.josm.gui.MapView;
    2532import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
    2633import org.openstreetmap.josm.gui.bbox.SourceButton;
     34import org.openstreetmap.josm.gui.layer.LayerManagerTest.TestLayer;
     35import org.openstreetmap.josm.gui.util.GuiHelper;
     36import org.openstreetmap.josm.testutils.ImagePatternMatching;
    2737import org.openstreetmap.josm.testutils.JOSMTestRules;
    2838
     39import com.google.common.collect.ImmutableMap;
     40
    2941import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    30 
    31 import org.awaitility.Awaitility;
    3242
    3343/**
     
    5565    }
    5666
    57     protected void assertSingleSelectedSourceLabel(String label) {
     67    @FunctionalInterface
     68    protected interface ThrowingRunnable {
     69        void run() throws Throwable;
     70    }
     71
     72    protected static Runnable uncheckExceptions(final ThrowingRunnable tr) {
     73        return (() -> {
     74            try {
     75                tr.run();
     76            } catch (Throwable e) {
     77                throw new RuntimeException(e);
     78            }
     79        });
     80    }
     81
     82    protected void assertSingleSelectedSourceLabel(final String label) {
    5883        JPopupMenu menu = this.sourceButton.getPopupMenu();
    5984        boolean found = false;
     
    7499    }
    75100
    76     protected JMenuItem getSourceMenuItemByLabel(String label) {
    77         JPopupMenu menu = this.sourceButton.getPopupMenu();
    78         for (Component c: menu.getComponents()) {
    79             if (JPopupMenu.Separator.class.isInstance(c)) {
    80                 break;
    81             } else if (((JMenuItem) c).getText() == label) {
    82                 return (JMenuItem) c;
    83             }
    84             // else continue...
     101    protected void clickSourceMenuItemByLabel(final String label) {
     102        try {
     103            GuiHelper.runInEDTAndWaitWithException(() -> {
     104                JPopupMenu menu = this.sourceButton.getPopupMenu();
     105                for (Component c: menu.getComponents()) {
     106                    if (JPopupMenu.Separator.class.isInstance(c)) {
     107                        // sources should all come before any separators
     108                        break;
     109                    } else if (((JMenuItem) c).getText() == label) {
     110                        ((JMenuItem) c).doClick();
     111                        return;
     112                    }
     113                    // else continue...
     114                }
     115                fail();
     116            });
     117        } catch (Throwable e) {
     118            // need to turn this *back* into an AssertionFailedError
     119            fail(String.format("Failed to find menu item with label %s: %s", label, e));
    85120        }
    86         fail("Failed to find menu item with label " + label);
    87         return null;
    88121    }
    89122
     
    95128    protected static BufferedImage paintedSlippyMap;
    96129
    97     protected void setUpMiniMap() throws Exception {
    98         this.minimap = new MinimapDialog();
    99         this.minimap.setSize(300, 200);
    100         this.minimap.showDialog();
    101         this.slippyMap = (SlippyMapBBoxChooser) TestUtils.getPrivateField(this.minimap, "slippyMap");
    102         this.sourceButton = (SourceButton) TestUtils.getPrivateField(this.slippyMap, "iSourceButton");
     130    protected void setUpMiniMap() {
     131        GuiHelper.runInEDTAndWaitWithException(uncheckExceptions(() -> {
     132            this.minimap = new MinimapDialog();
     133            this.minimap.setSize(300, 200);
     134            this.minimap.showDialog();
     135            this.slippyMap = (SlippyMapBBoxChooser) TestUtils.getPrivateField(this.minimap, "slippyMap");
     136            this.sourceButton = (SourceButton) TestUtils.getPrivateField(this.slippyMap, "iSourceButton");
     137
     138            // get minimap in a paintable state
     139            this.minimap.addNotify();
     140            this.minimap.doLayout();
     141        }));
    103142
    104143        this.slippyMapTasksFinished = () -> !this.slippyMap.getTileController().getTileLoader().hasOutstandingTasks();
    105 
    106         // get minimap in a paintable state
    107         this.minimap.addNotify();
    108         this.minimap.doLayout();
    109144    }
    110145
     
    153188        this.assertSingleSelectedSourceLabel("White Tiles");
    154189
    155         this.getSourceMenuItemByLabel("Magenta Tiles").doClick();
     190        this.clickSourceMenuItemByLabel("Magenta Tiles");
    156191        this.assertSingleSelectedSourceLabel("Magenta Tiles");
    157192        // call paint to trigger new tile fetch
     
    164199        assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
    165200
    166         this.getSourceMenuItemByLabel("Green Tiles").doClick();
     201        this.clickSourceMenuItemByLabel("Green Tiles");
    167202        this.assertSingleSelectedSourceLabel("Green Tiles");
    168203        // call paint to trigger new tile fetch
     
    199234        assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0));
    200235
    201         this.getSourceMenuItemByLabel("Magenta Tiles").doClick();
     236        this.clickSourceMenuItemByLabel("Magenta Tiles");
    202237        this.assertSingleSelectedSourceLabel("Magenta Tiles");
    203238
     
    226261        assertEquals(0xffffffff, paintedSlippyMap.getRGB(0, 0));
    227262    }
     263
     264    /**
     265     * test viewport marker rectangle matches the mapView's aspect ratio
     266     * @throws Exception if any error occurs
     267     */
     268    @Test
     269    public void testViewportAspectRatio() throws Exception {
     270        // Add a test layer to the layer manager to get the MapFrame & MapView
     271        MainApplication.getLayerManager().addLayer(new TestLayer());
     272
     273        Main.pref.put("slippy_map_chooser.mapstyle", "White Tiles");
     274        // ensure projection matches JMapViewer's
     275        Main.setProjection(Projections.getProjectionByCode("EPSG:3857"));
     276
     277        MapView mapView = MainApplication.getMap().mapView;
     278        GuiHelper.runInEDTAndWaitWithException(() -> {
     279            mapView.setVisible(true);
     280            mapView.addNotify();
     281            mapView.doLayout();
     282            // ensure we have a square mapView viewport
     283            mapView.setBounds(0, 0, 350, 350);
     284        });
     285
     286        this.setUpMiniMap();
     287
     288        // attempt to set viewport to cover a non-square area
     289        mapView.zoomTo(new Bounds(26.27, -18.23, 26.275, -18.229));
     290
     291        // an initial paint operation is required to trigger the tile fetches
     292        this.paintSlippyMap();
     293
     294        Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
     295
     296        this.paintSlippyMap();
     297
     298        Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder()
     299            .put(0xffffffff, "w")
     300            .put(0xff000000, "b")
     301            .put(0xfff0d1d1, "p")
     302            .build();
     303
     304        Matcher rowMatcher = ImagePatternMatching.rowMatch(
     305            paintedSlippyMap,
     306            paintedSlippyMap.getHeight()/2,
     307            paletteMap,
     308            "^(w+)b(p+)b(w+)$",
     309            true
     310        );
     311
     312        // (within a tolerance for numerical error) the number of pixels on the left of the viewport marker
     313        // should equal the number on the right
     314        assertTrue(
     315            "Viewport marker not horizontally centered",
     316            Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4
     317        );
     318
     319        Matcher colMatcher = ImagePatternMatching.columnMatch(
     320            paintedSlippyMap,
     321            paintedSlippyMap.getWidth()/2,
     322            paletteMap,
     323            "^(w+)b(p+)b(w+)$",
     324            true
     325        );
     326
     327        // (within a tolerance for numerical error) the number of pixels on the top of the viewport marker
     328        // should equal the number on the bottom
     329        assertTrue(
     330            "Viewport marker not vertically centered",
     331            Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4
     332        );
     333
     334        // (within a tolerance for numerical error) the viewport marker should be square
     335        assertTrue(
     336            "Viewport marker not square",
     337            Math.abs(colMatcher.group(2).length() - rowMatcher.group(2).length()) < 4
     338        );
     339
     340        // now change the mapView size
     341        GuiHelper.runInEDTAndWaitWithException(() -> {
     342            mapView.setBounds(0, 0, 150, 300);
     343            Arrays.stream(mapView.getComponentListeners()).forEach(
     344                cl -> cl.componentResized(new ComponentEvent(mapView, ComponentEvent.COMPONENT_RESIZED))
     345            );
     346        });
     347        // minimap doesn't (yet?) listen for component resize events to update its viewport marker, so
     348        // trigger a zoom change
     349        mapView.zoomTo(mapView.getCenter().add(1., 0.));
     350        this.paintSlippyMap();
     351
     352        rowMatcher = ImagePatternMatching.rowMatch(
     353            paintedSlippyMap,
     354            paintedSlippyMap.getHeight()/2,
     355            paletteMap,
     356            "^(w+)b(p+)b(w+)$",
     357            true
     358        );
     359        assertTrue(
     360            "Viewport marker not horizontally centered",
     361            Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4
     362        );
     363
     364        colMatcher = ImagePatternMatching.columnMatch(
     365            paintedSlippyMap,
     366            paintedSlippyMap.getWidth()/2,
     367            paletteMap,
     368            "^(w+)b(p+)b(w+)$",
     369            true
     370        );
     371        assertTrue(
     372            "Viewport marker not vertically centered",
     373            Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4
     374        );
     375
     376        try {
     377            javax.imageio.ImageIO.write(paintedSlippyMap, "png", new java.io.File("failed.png"));
     378        } catch (java.io.IOException ioe) {
     379            System.err.println("Failed writing image");
     380        }
     381
     382        assertTrue(
     383            "Viewport marker not 2:1 aspect ratio",
     384            Math.abs(colMatcher.group(2).length() - (rowMatcher.group(2).length()*2.0)) < 5
     385        );
     386    }
    228387}
Note: See TracChangeset for help on using the changeset viewer.