source: josm/trunk/test/unit/org/openstreetmap/josm/gui/dialogs/MinimapDialogTest.java@ 18690

Last change on this file since 18690 was 18690, checked in by taylor.smock, 14 months ago

See #16567: Convert all assertion calls to JUnit 5 (patch by gaben, modified)

The modifications are as follows:

  • Merge DomainValidatorTest.testIDN and DomainValidatorTest.testIDNJava6OrLater
  • Update some tests to use @ParameterizedTest (DomainValidatorTest)
  • Replace various exception blocks with assertThrows. These typically looked like
        try {
            // Something that should throw an exception here
            fail("An exception should have been thrown");
        } catch (Exception e) {
            // Verify the exception matches expectations here
        }
    
  • Replace assertTrue(val instanceof Clazz) with assertInstanceOf
  • Replace JUnit 4 @Suite with JUnit 5 @Suite

Both the original patch and the modified patch fix various lint issues.

  • Property svn:eol-style set to native
File size: 35.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static java.util.concurrent.TimeUnit.MILLISECONDS;
5import static org.junit.jupiter.api.Assertions.assertArrayEquals;
6import static org.junit.jupiter.api.Assertions.assertEquals;
7import static org.junit.jupiter.api.Assertions.assertFalse;
8import static org.junit.jupiter.api.Assertions.assertInstanceOf;
9import static org.junit.jupiter.api.Assertions.assertTrue;
10import static org.junit.jupiter.api.Assertions.fail;
11import static org.openstreetmap.josm.tools.I18n.tr;
12
13import java.awt.Color;
14import java.awt.Component;
15import java.awt.Graphics2D;
16import java.awt.event.ComponentEvent;
17import java.awt.image.BufferedImage;
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.HashMap;
21import java.util.Map;
22import java.util.Objects;
23import java.util.concurrent.Callable;
24import java.util.regex.Matcher;
25
26import javax.swing.JCheckBoxMenuItem;
27import javax.swing.JMenuItem;
28import javax.swing.JPopupMenu;
29
30import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
31import org.awaitility.Awaitility;
32import org.junit.Rule;
33import org.junit.Test;
34import org.openstreetmap.josm.TestUtils;
35import org.openstreetmap.josm.data.Bounds;
36import org.openstreetmap.josm.data.DataSource;
37import org.openstreetmap.josm.data.imagery.ImageryInfo;
38import org.openstreetmap.josm.data.imagery.ImageryLayerInfo;
39import org.openstreetmap.josm.data.osm.DataSet;
40import org.openstreetmap.josm.data.projection.ProjectionRegistry;
41import org.openstreetmap.josm.data.projection.Projections;
42import org.openstreetmap.josm.gui.MainApplication;
43import org.openstreetmap.josm.gui.MapView;
44import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
45import org.openstreetmap.josm.gui.bbox.SourceButton;
46import org.openstreetmap.josm.gui.layer.ImageryLayer;
47import org.openstreetmap.josm.gui.layer.LayerManagerTest.TestLayer;
48import org.openstreetmap.josm.gui.layer.OsmDataLayer;
49import org.openstreetmap.josm.gui.util.GuiHelper;
50import org.openstreetmap.josm.spi.preferences.Config;
51import org.openstreetmap.josm.testutils.ImagePatternMatching;
52import org.openstreetmap.josm.testutils.JOSMTestRules;
53
54/**
55 * Unit tests of {@link MinimapDialog} class.
56 */
57public class MinimapDialogTest {
58
59 /**
60 * Setup tests
61 */
62 @Rule
63 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
64 public JOSMTestRules josmTestRules = new JOSMTestRules().main().projection().fakeImagery();
65
66 /**
67 * Unit test of {@link MinimapDialog} class.
68 */
69 @Test
70 public void testMinimapDialog() {
71 MinimapDialog dlg = new MinimapDialog();
72 dlg.showDialog();
73 assertTrue(dlg.isVisible());
74 dlg.hideDialog();
75 assertFalse(dlg.isVisible());
76 }
77
78 @FunctionalInterface
79 protected interface ThrowingRunnable {
80 void run() throws Throwable;
81 }
82
83 protected static Runnable uncheckExceptions(final ThrowingRunnable tr) {
84 return (() -> {
85 try {
86 tr.run();
87 } catch (Throwable e) {
88 throw new RuntimeException(e);
89 }
90 });
91 }
92
93 protected void assertSingleSelectedSourceLabel(final String label) {
94 JPopupMenu menu = this.sourceButton.getPopupMenu();
95 boolean found = false;
96 for (Component c: menu.getComponents()) {
97 if (c instanceof JPopupMenu.Separator) {
98 break;
99 } else {
100 boolean equalText = ((JMenuItem) c).getText().equals(label);
101 boolean isSelected = ((JMenuItem) c).isSelected();
102 assertEquals(equalText, isSelected);
103 if (equalText) {
104 assertFalse(found, "Second selected source found");
105 found = true;
106 }
107 }
108 }
109 assertTrue(found, "Selected source not found in menu");
110 }
111
112 protected void clickSourceMenuItemByLabel(final String label) {
113 try {
114 GuiHelper.runInEDTAndWaitWithException(() -> {
115 JPopupMenu menu = this.sourceButton.getPopupMenu();
116 for (Component c: menu.getComponents()) {
117 if (c instanceof JPopupMenu.Separator) {
118 // sources should all come before any separators
119 break;
120 } else if (Objects.equals(((JMenuItem) c).getText(), label)) {
121 ((JMenuItem) c).doClick();
122 return;
123 }
124 // else continue...
125 }
126 fail("Expected JMenuItem with text " + label + " not found");
127 });
128 } catch (Throwable e) {
129 throw new RuntimeException(String.format("Failed to find menu item with label %s: %s", label, e), e);
130 }
131 }
132
133 protected void assertSourceLabelsVisible(final String... labels) {
134 GuiHelper.runInEDTAndWaitWithException(() -> {
135 final ArrayList<String> menuLabels = new ArrayList<>();
136 final JPopupMenu menu = this.sourceButton.getPopupMenu();
137 for (Component c: menu.getComponents()) {
138 if (c instanceof JPopupMenu.Separator) {
139 break;
140 }
141 menuLabels.add(((JMenuItem) c).getText());
142 }
143
144 assertArrayEquals(
145 labels,
146 menuLabels.toArray()
147 );
148 });
149 }
150
151 private MinimapDialog minimap;
152 private SlippyMapBBoxChooser slippyMap;
153 private SourceButton sourceButton;
154 private Callable<Boolean> slippyMapTasksFinished;
155
156 private static BufferedImage paintedSlippyMap;
157
158 protected void setUpMiniMap() {
159 GuiHelper.runInEDTAndWaitWithException(uncheckExceptions(() -> {
160 this.minimap = new MinimapDialog();
161 this.minimap.setSize(300, 200);
162 this.minimap.showDialog();
163 this.slippyMap = (SlippyMapBBoxChooser) TestUtils.getPrivateField(this.minimap, "slippyMap");
164 this.sourceButton = (SourceButton) TestUtils.getPrivateField(this.slippyMap, "iSourceButton");
165
166 // get minimap in a paintable state
167 this.minimap.addNotify();
168 this.minimap.doLayout();
169 }));
170
171 this.slippyMapTasksFinished = () -> !this.slippyMap.getTileController().getTileLoader().hasOutstandingTasks();
172 }
173
174 protected void paintSlippyMap() {
175 if (paintedSlippyMap == null ||
176 paintedSlippyMap.getWidth() != this.slippyMap.getSize().width ||
177 paintedSlippyMap.getHeight() != this.slippyMap.getSize().height) {
178 paintedSlippyMap = new BufferedImage(
179 this.slippyMap.getSize().width,
180 this.slippyMap.getSize().height,
181 BufferedImage.TYPE_INT_RGB
182 );
183 } // else reuse existing one - allocation is expensive
184
185 // clear background to a recognizably "wrong" color & dispose our Graphics2D so we don't risk carrying over
186 // any state
187 Graphics2D g = paintedSlippyMap.createGraphics();
188 g.setBackground(Color.BLUE);
189 g.clearRect(0, 0, paintedSlippyMap.getWidth(), paintedSlippyMap.getHeight());
190 g.dispose();
191
192 g = paintedSlippyMap.createGraphics();
193 this.slippyMap.paintAll(g);
194 }
195
196 /**
197 * Tests to switch imagery source.
198 */
199 @Test
200 public void testSourceSwitching() {
201 // relevant prefs starting out empty, should choose the first source and have shown download area enabled
202 // (not that there's a data layer for it to use)
203
204 this.setUpMiniMap();
205
206 // an initial paint operation is required to trigger the tile fetches
207 this.paintSlippyMap();
208
209 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
210
211 this.paintSlippyMap();
212
213 assertEquals(0xffffffff, paintedSlippyMap.getRGB(0, 0));
214
215 this.assertSingleSelectedSourceLabel("White Tiles");
216
217 this.clickSourceMenuItemByLabel("Magenta Tiles");
218 this.assertSingleSelectedSourceLabel("Magenta Tiles");
219 // call paint to trigger new tile fetch
220 this.paintSlippyMap();
221
222 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
223
224 this.paintSlippyMap();
225
226 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
227
228 this.clickSourceMenuItemByLabel("Green Tiles");
229 this.assertSingleSelectedSourceLabel("Green Tiles");
230 // call paint to trigger new tile fetch
231 this.paintSlippyMap();
232
233 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
234
235 this.paintSlippyMap();
236
237 assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0));
238
239 assertEquals("Green Tiles", Config.getPref().get("slippy_map_chooser.mapstyle", "Fail"));
240 }
241
242 /**
243 * Tests that the apparently-selected TileSource survives the tile sources being refreshed.
244 */
245 @Test
246 public void testRefreshSourcesRetainsSelection() {
247 // relevant prefs starting out empty, should choose the first source and have shown download area enabled
248 // (not that there's a data layer for it to use)
249
250 this.setUpMiniMap();
251
252 this.clickSourceMenuItemByLabel("Magenta Tiles");
253 this.assertSingleSelectedSourceLabel("Magenta Tiles");
254
255 // call paint to trigger new tile fetch
256 this.paintSlippyMap();
257
258 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
259
260 this.paintSlippyMap();
261
262 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
263
264 this.slippyMap.refreshTileSources();
265
266 this.assertSingleSelectedSourceLabel("Magenta Tiles");
267
268 // call paint to trigger new tile fetch
269 this.paintSlippyMap();
270
271 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
272
273 this.paintSlippyMap();
274
275 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
276 }
277
278 /**
279 * Tests that the currently selected source being removed from ImageryLayerInfo will remain present and
280 * selected in the source menu even after the tile sources have been refreshed.
281 */
282 @Test
283 public void testRemovedSourceStillSelected() {
284 // relevant prefs starting out empty, should choose the first source and have shown download area enabled
285 // (not that there's a data layer for it to use)
286
287 this.setUpMiniMap();
288
289 this.clickSourceMenuItemByLabel("Green Tiles");
290
291 ImageryLayerInfo.instance.remove(
292 ImageryLayerInfo.instance.getLayers().stream().filter(i -> i.getName().equals("Green Tiles")).findAny().get()
293 );
294
295 this.assertSingleSelectedSourceLabel("Green Tiles");
296
297 this.slippyMap.refreshTileSources();
298
299 this.assertSingleSelectedSourceLabel("Green Tiles");
300
301 // call paint to trigger new tile fetch
302 this.paintSlippyMap();
303
304 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
305
306 this.paintSlippyMap();
307
308 assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0));
309 }
310
311 /**
312 * Tests the tile source list includes sources only present in the LayerManager
313 */
314 @Test
315 public void testTileSourcesFromCurrentLayers() {
316 // relevant prefs starting out empty, should choose the first (ImageryLayerInfo) source and have shown download area enabled
317 // (not that there's a data layer for it to use)
318
319 final ImageryInfo magentaTilesInfo = ImageryLayerInfo.instance.getLayers().stream().filter(
320 i -> i.getName().equals("Magenta Tiles")
321 ).findAny().get();
322 final ImageryInfo blackTilesInfo = ImageryLayerInfo.instance.getLayers().stream().filter(
323 i -> i.getName().equals("Black Tiles")
324 ).findAny().get();
325
326 // first we will remove "Magenta Tiles" from ImageryLayerInfo
327 ImageryLayerInfo.instance.remove(magentaTilesInfo);
328
329 this.setUpMiniMap();
330
331 assertSourceLabelsVisible(
332 "White Tiles",
333 "Black Tiles",
334 "Green Tiles"
335 );
336
337 final ImageryLayer magentaTilesLayer = ImageryLayer.create(magentaTilesInfo);
338 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(magentaTilesLayer));
339
340 assertSourceLabelsVisible(
341 "White Tiles",
342 "Black Tiles",
343 "Green Tiles",
344 "Magenta Tiles"
345 );
346
347 this.clickSourceMenuItemByLabel("Magenta Tiles");
348 this.assertSingleSelectedSourceLabel("Magenta Tiles");
349
350 // call paint to trigger new tile fetch
351 this.paintSlippyMap();
352
353 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
354
355 this.paintSlippyMap();
356
357 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
358
359 final ImageryLayer blackTilesLayer = ImageryLayer.create(blackTilesInfo);
360 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(blackTilesLayer));
361
362 assertSourceLabelsVisible(
363 "White Tiles",
364 "Black Tiles",
365 "Green Tiles",
366 "Magenta Tiles"
367 );
368
369 this.clickSourceMenuItemByLabel("Black Tiles");
370 this.assertSingleSelectedSourceLabel("Black Tiles");
371
372 // call paint to trigger new tile fetch
373 this.paintSlippyMap();
374
375 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
376
377 this.paintSlippyMap();
378
379 assertEquals(0xff000000, paintedSlippyMap.getRGB(0, 0));
380
381 // removing magentaTilesLayer while it is *not* the selected TileSource should make it disappear
382 // immediately
383 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(magentaTilesLayer));
384
385 assertSourceLabelsVisible(
386 "White Tiles",
387 "Black Tiles",
388 "Green Tiles"
389 );
390 this.assertSingleSelectedSourceLabel("Black Tiles");
391
392 final ImageryLayer magentaTilesLayer2 = ImageryLayer.create(magentaTilesInfo);
393 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().addLayer(magentaTilesLayer2));
394
395 assertSourceLabelsVisible(
396 "White Tiles",
397 "Black Tiles",
398 "Green Tiles",
399 "Magenta Tiles"
400 );
401
402 this.clickSourceMenuItemByLabel("Magenta Tiles");
403 this.assertSingleSelectedSourceLabel("Magenta Tiles");
404
405 // call paint to trigger new tile fetch
406 this.paintSlippyMap();
407
408 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
409
410 this.paintSlippyMap();
411
412 assertEquals(0xffff00ff, paintedSlippyMap.getRGB(0, 0));
413
414 // removing magentaTilesLayer while it *is* the selected TileSource...
415 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(magentaTilesLayer2));
416
417 assertSourceLabelsVisible(
418 "White Tiles",
419 "Black Tiles",
420 "Green Tiles",
421 "Magenta Tiles"
422 );
423 this.assertSingleSelectedSourceLabel("Magenta Tiles");
424
425 this.clickSourceMenuItemByLabel("Green Tiles");
426 this.assertSingleSelectedSourceLabel("Green Tiles");
427 assertSourceLabelsVisible(
428 "White Tiles",
429 "Black Tiles",
430 "Green Tiles"
431 );
432
433 // removing blackTilesLayer shouldn't remove it from the menu as it is already in ImageryLayerInfo
434 GuiHelper.runInEDT(() -> MainApplication.getLayerManager().removeLayer(blackTilesLayer));
435
436 this.assertSingleSelectedSourceLabel("Green Tiles");
437 assertSourceLabelsVisible(
438 "White Tiles",
439 "Black Tiles",
440 "Green Tiles"
441 );
442 }
443
444 /**
445 * Tests minimap obeys a saved "mapstyle" preference on startup.
446 */
447 @Test
448 public void testSourcePrefObeyed() {
449 Config.getPref().put("slippy_map_chooser.mapstyle", "Green Tiles");
450
451 this.setUpMiniMap();
452
453 this.assertSingleSelectedSourceLabel("Green Tiles");
454
455 // an initial paint operation is required to trigger the tile fetches
456 this.paintSlippyMap();
457
458 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
459
460 this.paintSlippyMap();
461
462 assertEquals(0xff00ff00, paintedSlippyMap.getRGB(0, 0));
463
464 this.clickSourceMenuItemByLabel("Magenta Tiles");
465 this.assertSingleSelectedSourceLabel("Magenta Tiles");
466
467 assertEquals("Magenta Tiles", Config.getPref().get("slippy_map_chooser.mapstyle", "Fail"));
468 }
469
470 /**
471 * Tests minimap handles an unrecognized "mapstyle" preference on startup
472 */
473 @Test
474 public void testSourcePrefInvalid() {
475 Config.getPref().put("slippy_map_chooser.mapstyle", "Hooloovoo Tiles");
476
477 this.setUpMiniMap();
478
479 this.assertSingleSelectedSourceLabel("White Tiles");
480
481 // an initial paint operation is required to trigger the tile fetches
482 this.paintSlippyMap();
483
484 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
485
486 this.paintSlippyMap();
487
488 assertEquals(0xffffffff, paintedSlippyMap.getRGB(0, 0));
489 }
490
491 /**
492 * test viewport marker rectangle matches the mapView's aspect ratio
493 */
494 @Test
495 public void testViewportAspectRatio() {
496 // Add a test layer to the layer manager to get the MapFrame & MapView
497 MainApplication.getLayerManager().addLayer(new TestLayer());
498
499 Config.getPref().put("slippy_map_chooser.mapstyle", "White Tiles");
500 // ensure projection matches JMapViewer's
501 ProjectionRegistry.setProjection(Projections.getProjectionByCode("EPSG:3857"));
502
503 MapView mapView = MainApplication.getMap().mapView;
504 GuiHelper.runInEDTAndWaitWithException(() -> {
505 mapView.setVisible(true);
506 mapView.addNotify();
507 mapView.doLayout();
508 // ensure we have a square mapView viewport
509 mapView.setBounds(0, 0, 350, 350);
510 });
511
512 this.setUpMiniMap();
513
514 // attempt to set viewport to cover a non-square area
515 mapView.zoomTo(new Bounds(26.27, -18.23, 26.275, -18.229));
516
517 // an initial paint operation is required to trigger the tile fetches
518 this.paintSlippyMap();
519
520 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
521
522 this.paintSlippyMap();
523
524 Map<Integer, String> paletteMap = new HashMap<Integer, String>() {{
525 put(0xffffffff, "w"); // white
526 put(0xff000000, "b"); // black
527 put(0xfff0d1d1, "p"); // pink
528 }};
529
530 Matcher rowMatcher = ImagePatternMatching.rowMatch(
531 paintedSlippyMap,
532 paintedSlippyMap.getHeight()/2,
533 paletteMap,
534 "^(w+)b(p+)b(w+)$",
535 true
536 );
537
538 // (within a tolerance for numerical error) the number of pixels on the left of the viewport marker
539 // should equal the number on the right
540 assertTrue(
541 Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4,
542 "Viewport marker not horizontally centered"
543 );
544
545 Matcher colMatcher = ImagePatternMatching.columnMatch(
546 paintedSlippyMap,
547 paintedSlippyMap.getWidth()/2,
548 paletteMap,
549 "^(w+)b(p+)b(w+)$",
550 true
551 );
552
553 // (within a tolerance for numerical error) the number of pixels on the top of the viewport marker
554 // should equal the number on the bottom
555 assertTrue(
556 Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4,
557 "Viewport marker not vertically centered"
558 );
559
560 // (within a tolerance for numerical error) the viewport marker should be square
561 assertTrue(
562 Math.abs(colMatcher.group(2).length() - rowMatcher.group(2).length()) < 4,
563 "Viewport marker not square"
564 );
565
566 // now change the mapView size
567 GuiHelper.runInEDTAndWaitWithException(() -> {
568 mapView.setBounds(0, 0, 150, 300);
569 Arrays.stream(mapView.getComponentListeners()).forEach(
570 cl -> cl.componentResized(new ComponentEvent(mapView, ComponentEvent.COMPONENT_RESIZED))
571 );
572 });
573 // minimap doesn't (yet?) listen for component resize events to update its viewport marker, so
574 // trigger a zoom change
575 mapView.zoomTo(mapView.getCenter().add(1., 0.));
576 this.paintSlippyMap();
577
578 rowMatcher = ImagePatternMatching.rowMatch(
579 paintedSlippyMap,
580 paintedSlippyMap.getHeight()/2,
581 paletteMap,
582 "^(w+)b(p+)b(w+)$",
583 true
584 );
585 assertTrue(
586 Math.abs(rowMatcher.group(1).length() - rowMatcher.group(3).length()) < 4,
587 "Viewport marker not horizontally centered"
588 );
589
590 colMatcher = ImagePatternMatching.columnMatch(
591 paintedSlippyMap,
592 paintedSlippyMap.getWidth()/2,
593 paletteMap,
594 "^(w+)b(p+)b(w+)$",
595 true
596 );
597 assertTrue(
598 Math.abs(colMatcher.group(1).length() - colMatcher.group(3).length()) < 4,
599 "Viewport marker not vertically centered"
600 );
601
602 try {
603 javax.imageio.ImageIO.write(paintedSlippyMap, "png", new java.io.File("failed.png"));
604 } catch (java.io.IOException ioe) {
605 System.err.println("Failed writing image");
606 }
607
608 assertTrue(
609 Math.abs(colMatcher.group(2).length() - (rowMatcher.group(2).length()*2.0)) < 5,
610 "Viewport marker not 2:1 aspect ratio"
611 );
612 }
613
614 protected JCheckBoxMenuItem getShowDownloadedAreaMenuItem() {
615 JPopupMenu menu = this.sourceButton.getPopupMenu();
616 boolean afterSeparator = false;
617 for (Component c: menu.getComponents()) {
618 if (c instanceof JPopupMenu.Separator) {
619 assertFalse(afterSeparator, "More than one separator before target item");
620 afterSeparator = true;
621 } else if (((JMenuItem) c).getText().equals(tr("Show downloaded area"))) {
622 assertTrue(afterSeparator, "Separator not found before target item");
623 return assertInstanceOf(JCheckBoxMenuItem.class, c, "Target item doesn't appear to be a JCheckBoxMenuItem");
624 }
625 }
626 fail("'Show downloaded area' menu item not found");
627 return null;
628 }
629
630 /**
631 * test downloaded area is shown shaded
632 */
633 @Test
634 public void testShowDownloadedArea() {
635 Config.getPref().put("slippy_map_chooser.mapstyle", "Green Tiles");
636 Config.getPref().putBoolean("slippy_map_chooser.show_downloaded_area", false);
637
638 DataSet dataSet = new DataSet();
639 dataSet.addDataSource(new DataSource(new Bounds(51.725, -0.0209, 51.746, 0.0162), "Somewhere"));
640
641 OsmDataLayer dataLayer = new OsmDataLayer(
642 dataSet,
643 "Test Layer 123",
644 null
645 );
646 MainApplication.getLayerManager().addLayer(dataLayer);
647 MainApplication.getLayerManager().setActiveLayer(dataLayer);
648
649 MapView mapView = MainApplication.getMap().mapView;
650 GuiHelper.runInEDTAndWaitWithException(() -> {
651 mapView.setVisible(true);
652 mapView.addNotify();
653 mapView.doLayout();
654 mapView.setBounds(0, 0, 500, 500);
655 });
656
657 this.setUpMiniMap();
658
659 // assert "show downloaded areas" checkbox is unchecked
660 assertFalse(this.getShowDownloadedAreaMenuItem().isSelected());
661
662 // we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio
663 mapView.zoomTo(new Bounds(51.732, -0.0269, 51.753, 0.0102));
664
665 // an initial paint operation is required to trigger the tile fetches
666 this.paintSlippyMap();
667
668 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
669
670 this.paintSlippyMap();
671
672 Map<Integer, String> paletteMap = new HashMap<Integer, String>() {{
673 put(0xff00ff00, "g"); // green
674 put(0xff000000, "b"); // black
675 put(0xff8ad16b, "v"); // viewport marker inner (pink+green mix)
676 put(0xff00df00, "d"); // (shaded green)
677 put(0xff8ac46b, "q"); // (shaded pink+green mix)
678 }};
679
680 // assert downloaded areas are not drawn
681 ImagePatternMatching.rowMatch(
682 paintedSlippyMap,
683 paintedSlippyMap.getHeight()/2,
684 paletteMap,
685 "^g+bv+bg+$",
686 true
687 );
688 ImagePatternMatching.columnMatch(
689 paintedSlippyMap,
690 paintedSlippyMap.getWidth()/2,
691 paletteMap,
692 "^g+bv+bg+$",
693 true
694 );
695
696 // enable "show downloaded areas"
697 GuiHelper.runInEDTAndWaitWithException(() -> this.getShowDownloadedAreaMenuItem().doClick());
698 assertTrue(this.getShowDownloadedAreaMenuItem().isSelected());
699
700 // assert downloaded areas are drawn
701 this.paintSlippyMap();
702
703 ImagePatternMatching.rowMatch(
704 paintedSlippyMap,
705 paintedSlippyMap.getHeight()/2,
706 paletteMap,
707 "^d+bq+v+bg+d+$",
708 true
709 );
710 ImagePatternMatching.columnMatch(
711 paintedSlippyMap,
712 paintedSlippyMap.getWidth()/2,
713 paletteMap,
714 "^d+bq+v+bg+d+$",
715 true
716 );
717
718 // also assert the leftmost column doesn't (yet) have any downloaded area marks (i.e. fully shaded)
719 ImagePatternMatching.columnMatch(
720 paintedSlippyMap,
721 0,
722 paletteMap,
723 "^d+$",
724 true
725 );
726
727 // add another downloaded area, going off the left of the widget
728 dataSet.addDataSource(new DataSource(new Bounds(51.745, -1., 51.765, 0.0162), "Somewhere else"));
729 // and redraw
730 this.paintSlippyMap();
731
732 // the middle row should be as before
733 ImagePatternMatching.rowMatch(
734 paintedSlippyMap,
735 paintedSlippyMap.getHeight()/2,
736 paletteMap,
737 "^d+bq+v+bg+d+$",
738 true
739 );
740 // the middle column should have its unshaded region extended beyond the viewport marker
741 ImagePatternMatching.columnMatch(
742 paintedSlippyMap,
743 paintedSlippyMap.getWidth()/2,
744 paletteMap,
745 "^d+g+bv+bg+d+$",
746 true
747 );
748 // but the leftmost column should now have an unshaded mark
749 ImagePatternMatching.columnMatch(
750 paintedSlippyMap,
751 0,
752 paletteMap,
753 "^d+g+d+$",
754 true
755 );
756 // and the rightmost column should be untouched
757 ImagePatternMatching.columnMatch(
758 paintedSlippyMap,
759 paintedSlippyMap.getWidth()-1,
760 paletteMap,
761 "^d+$",
762 true
763 );
764
765 // and now if we pan to the left (in EastNorth units)
766 mapView.zoomTo(mapView.getCenter().add(-5000., 0.));
767 // and redraw
768 this.paintSlippyMap();
769
770 // the middle row should have its unshaded region outside the viewport marker
771 ImagePatternMatching.rowMatch(
772 paintedSlippyMap,
773 paintedSlippyMap.getHeight()/2,
774 paletteMap,
775 "^d+bq+bd+g+d*$",
776 true
777 );
778 // the middle column should have a shaded region inside the viewport marker
779 ImagePatternMatching.columnMatch(
780 paintedSlippyMap,
781 paintedSlippyMap.getWidth()/2,
782 paletteMap,
783 "^d+g+bv+q+bd+$",
784 true
785 );
786 }
787
788 /**
789 * test display of downloaded area follows active layer switching
790 */
791 @Test
792 public void testShowDownloadedAreaLayerSwitching() {
793 Config.getPref().put("slippy_map_chooser.mapstyle", "Green Tiles");
794 Config.getPref().putBoolean("slippy_map_chooser.show_downloaded_area", true);
795
796 DataSet dataSetA = new DataSet();
797 // dataSetA has a long thin horizontal downloaded area (extending off the left & right of the map)
798 dataSetA.addDataSource(new DataSource(new Bounds(-18., -61.02, -15., -60.98), "Elsewhere"));
799
800 OsmDataLayer dataLayerA = new OsmDataLayer(
801 dataSetA,
802 "Test Layer A",
803 null
804 );
805 MainApplication.getLayerManager().addLayer(dataLayerA);
806
807 DataSet dataSetB = new DataSet();
808 // dataSetB has a long thin vertical downloaded area (extending off the top & bottom of the map)
809 dataSetB.addDataSource(new DataSource(new Bounds(-16.38, -62., -16.34, -60.), "Nowhere"));
810
811 OsmDataLayer dataLayerB = new OsmDataLayer(
812 dataSetB,
813 "Test Layer B",
814 null
815 );
816 MainApplication.getLayerManager().addLayer(dataLayerB);
817
818 MainApplication.getLayerManager().setActiveLayer(dataLayerB);
819
820 MapView mapView = MainApplication.getMap().mapView;
821 GuiHelper.runInEDTAndWaitWithException(() -> {
822 mapView.setVisible(true);
823 mapView.addNotify();
824 mapView.doLayout();
825 mapView.setBounds(0, 0, 400, 400);
826 });
827
828 this.setUpMiniMap();
829
830 // assert "show downloaded areas" checkbox is checked
831 assertTrue(this.getShowDownloadedAreaMenuItem().isSelected());
832
833 // again, we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio
834 mapView.zoomTo(new Bounds(-16.423, -61.076, -16.299, -60.932));
835
836 // an initial paint operation is required to trigger the tile fetches
837 this.paintSlippyMap();
838
839 Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished);
840
841 this.paintSlippyMap();
842
843 Map<Integer, String> paletteMap = new HashMap<Integer, String>() {{
844 put(0xff00ff00, "g"); // green
845 put(0xff000000, "b"); // black
846 put(0xff8ad16b, "v"); // viewport marker inner (pink+green mix)
847 put(0xff00df00, "d"); // (shaded green)
848 put(0xff8ac46b, "q"); // (shaded pink+green mix)
849 }};
850
851 // the middle row should be entirely unshaded
852 ImagePatternMatching.rowMatch(
853 paintedSlippyMap,
854 paintedSlippyMap.getHeight()/2,
855 paletteMap,
856 "^g+bv+bg+$",
857 true
858 );
859 // the middle column should have an unshaded band within the viewport marker
860 Matcher centerMatcher = ImagePatternMatching.columnMatch(
861 paintedSlippyMap,
862 paintedSlippyMap.getWidth()/2,
863 paletteMap,
864 "^(d+bq+)(v+)(q+bd+)$",
865 true
866 );
867 // the leftmost and rightmost columns should have an unshaded band
868 Matcher leftMatcher = ImagePatternMatching.columnMatch(
869 paintedSlippyMap,
870 0,
871 paletteMap,
872 "^(d+)(g+)(d+)$",
873 true
874 );
875 Matcher rightMatcher = ImagePatternMatching.columnMatch(
876 paintedSlippyMap,
877 paintedSlippyMap.getWidth()-1,
878 paletteMap,
879 "^(d+)(g+)(d+)$",
880 true
881 );
882 // the three columns should have the unshaded band in the same place
883 assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length());
884 assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length());
885 assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length());
886 assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length());
887
888 // switch active layer
889 MainApplication.getLayerManager().setActiveLayer(dataLayerA);
890 this.paintSlippyMap();
891
892 // the middle column should be entirely unshaded
893 ImagePatternMatching.columnMatch(
894 paintedSlippyMap,
895 paintedSlippyMap.getWidth()/2,
896 paletteMap,
897 "^g+bv+bg+$",
898 true
899 );
900 // the middle row should have an unshaded band within the viewport marker
901 centerMatcher = ImagePatternMatching.rowMatch(
902 paintedSlippyMap,
903 paintedSlippyMap.getHeight()/2,
904 paletteMap,
905 "^(d+bq+)(v+)(q+bd+)$",
906 true
907 );
908 // the topmost and bottommost rows should have an unshaded band
909 Matcher topMatcher = ImagePatternMatching.rowMatch(
910 paintedSlippyMap,
911 0,
912 paletteMap,
913 "^(d+)(g+)(d+)$",
914 true
915 );
916 Matcher BottomMatcher = ImagePatternMatching.rowMatch(
917 paintedSlippyMap,
918 paintedSlippyMap.getHeight()-1,
919 paletteMap,
920 "^(d+)(g+)(d+)$",
921 true
922 );
923 // the three rows should have the unshaded band in the same place
924 assertEquals(centerMatcher.group(1).length(), topMatcher.group(1).length());
925 assertEquals(centerMatcher.group(1).length(), BottomMatcher.group(1).length());
926 assertEquals(centerMatcher.group(2).length(), topMatcher.group(2).length());
927 assertEquals(centerMatcher.group(2).length(), BottomMatcher.group(2).length());
928
929 // deleting dataLayerA should hopefully switch our active layer back to dataLayerB
930 MainApplication.getLayerManager().removeLayer(dataLayerA);
931 this.paintSlippyMap();
932
933 // now we're really just repeating the same assertions we made originally when dataLayerB was active
934 // the middle row should be entirely unshaded
935 ImagePatternMatching.rowMatch(
936 paintedSlippyMap,
937 paintedSlippyMap.getHeight()/2,
938 paletteMap,
939 "^g+bv+bg+$",
940 true
941 );
942 // the middle column should have an unshaded band within the viewport marker
943 centerMatcher = ImagePatternMatching.columnMatch(
944 paintedSlippyMap,
945 paintedSlippyMap.getWidth()/2,
946 paletteMap,
947 "^(d+bq+)(v+)(q+bd+)$",
948 true
949 );
950 // the leftmost and rightmost columns should have an unshaded band
951 leftMatcher = ImagePatternMatching.columnMatch(
952 paintedSlippyMap,
953 0,
954 paletteMap,
955 "^(d+)(g+)(d+)$",
956 true
957 );
958 rightMatcher = ImagePatternMatching.columnMatch(
959 paintedSlippyMap,
960 paintedSlippyMap.getWidth()-1,
961 paletteMap,
962 "^(d+)(g+)(d+)$",
963 true
964 );
965 // the three columns should have the unshaded band in the same place
966 assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length());
967 assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length());
968 assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length());
969 assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length());
970
971 // but now if we expand its downloaded area to cover most of the southern hemisphere...
972 dataSetB.addDataSource(new DataSource(new Bounds(-75., -100., 0., 100.), "Everywhere"));
973 this.paintSlippyMap();
974
975 // we should see it all as unshaded.
976 ImagePatternMatching.rowMatch(
977 paintedSlippyMap,
978 0,
979 paletteMap,
980 "^g+$",
981 true
982 );
983 ImagePatternMatching.rowMatch(
984 paintedSlippyMap,
985 paintedSlippyMap.getHeight()/2,
986 paletteMap,
987 "^g+bv+bg+$",
988 true
989 );
990 ImagePatternMatching.rowMatch(
991 paintedSlippyMap,
992 paintedSlippyMap.getHeight()-1,
993 paletteMap,
994 "^g+$",
995 true
996 );
997 ImagePatternMatching.columnMatch(
998 paintedSlippyMap,
999 0,
1000 paletteMap,
1001 "^g+$",
1002 true
1003 );
1004 ImagePatternMatching.columnMatch(
1005 paintedSlippyMap,
1006 paintedSlippyMap.getWidth()/2,
1007 paletteMap,
1008 "^g+bv+bg+$",
1009 true
1010 );
1011 ImagePatternMatching.columnMatch(
1012 paintedSlippyMap,
1013 paintedSlippyMap.getWidth()-1,
1014 paletteMap,
1015 "^g+$",
1016 true
1017 );
1018 }
1019}
Note: See TracBrowser for help on using the repository browser.