| 392 | |
| 393 | protected JCheckBoxMenuItem getShowDownloadedAreaMenuItem() { |
| 394 | JPopupMenu menu = this.sourceButton.getPopupMenu(); |
| 395 | boolean afterSeparator = false; |
| 396 | for (Component c: menu.getComponents()) { |
| 397 | if (JPopupMenu.Separator.class.isInstance(c)) { |
| 398 | assertFalse("More than one separator before target item", afterSeparator); |
| 399 | afterSeparator = true; |
| 400 | } else if (((JMenuItem) c).getText().equals(tr("Show downloaded area"))) { |
| 401 | assertTrue("Separator not found before target item", afterSeparator); |
| 402 | assertTrue("Target item doesn't appear to be a JCheckBoxMenuItem", JCheckBoxMenuItem.class.isInstance(c)); |
| 403 | return (JCheckBoxMenuItem) c; |
| 404 | } |
| 405 | } |
| 406 | fail("'Show downloaded area' menu item not found"); |
| 407 | return null; |
| 408 | } |
| 409 | |
| 410 | /** |
| 411 | * test downloaded area is shown shaded |
| 412 | * @throws Exception if any error occurs |
| 413 | */ |
| 414 | @Test |
| 415 | public void testShowDownloadedArea() throws Exception { |
| 416 | Main.pref.put("slippy_map_chooser.mapstyle", "Green Tiles"); |
| 417 | Main.pref.putBoolean("slippy_map_chooser.show_downloaded_area", false); |
| 418 | |
| 419 | DataSet dataSet = new DataSet(); |
| 420 | dataSet.addDataSource(new DataSource(new Bounds(51.725, -0.0209, 51.746, 0.0162), "Somewhere")); |
| 421 | |
| 422 | OsmDataLayer dataLayer = new OsmDataLayer( |
| 423 | dataSet, |
| 424 | "Test Layer 123", |
| 425 | null |
| 426 | ); |
| 427 | MainApplication.getLayerManager().addLayer(dataLayer); |
| 428 | MainApplication.getLayerManager().setActiveLayer(dataLayer); |
| 429 | |
| 430 | MapView mapView = MainApplication.getMap().mapView; |
| 431 | GuiHelper.runInEDTAndWaitWithException(() -> { |
| 432 | mapView.setVisible(true); |
| 433 | mapView.addNotify(); |
| 434 | mapView.doLayout(); |
| 435 | mapView.setBounds(0, 0, 500, 500); |
| 436 | }); |
| 437 | |
| 438 | this.setUpMiniMap(); |
| 439 | |
| 440 | // assert "show downloaded areas" checkbox is unchecked |
| 441 | assertFalse(this.getShowDownloadedAreaMenuItem().isSelected()); |
| 442 | |
| 443 | // we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio |
| 444 | mapView.zoomTo(new Bounds(51.732, -0.0269, 51.753, 0.0102)); |
| 445 | |
| 446 | // an initial paint operation is required to trigger the tile fetches |
| 447 | this.paintSlippyMap(); |
| 448 | |
| 449 | Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); |
| 450 | |
| 451 | this.paintSlippyMap(); |
| 452 | |
| 453 | Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder() |
| 454 | .put(0xff00ff00, "g") // green |
| 455 | .put(0xff000000, "b") // black |
| 456 | .put(0xff8ad16b, "v") // viewport marker inner (pink+green mix) |
| 457 | .put(0xff00df00, "d") // (shaded green) |
| 458 | .put(0xff8ac46b, "q") // (shaded pink+green mix) |
| 459 | .build(); |
| 460 | |
| 461 | // assert downloaded areas are not drawn |
| 462 | ImagePatternMatching.rowMatch( |
| 463 | paintedSlippyMap, |
| 464 | paintedSlippyMap.getHeight()/2, |
| 465 | paletteMap, |
| 466 | "^g+bv+bg+$", |
| 467 | true |
| 468 | ); |
| 469 | ImagePatternMatching.columnMatch( |
| 470 | paintedSlippyMap, |
| 471 | paintedSlippyMap.getWidth()/2, |
| 472 | paletteMap, |
| 473 | "^g+bv+bg+$", |
| 474 | true |
| 475 | ); |
| 476 | |
| 477 | // enable "show downloaded areas" |
| 478 | GuiHelper.runInEDTAndWaitWithException(() -> this.getShowDownloadedAreaMenuItem().doClick()); |
| 479 | assertTrue(this.getShowDownloadedAreaMenuItem().isSelected()); |
| 480 | |
| 481 | // assert downloaded areas are drawn |
| 482 | this.paintSlippyMap(); |
| 483 | |
| 484 | ImagePatternMatching.rowMatch( |
| 485 | paintedSlippyMap, |
| 486 | paintedSlippyMap.getHeight()/2, |
| 487 | paletteMap, |
| 488 | "^d+bq+v+bg+d+$", |
| 489 | true |
| 490 | ); |
| 491 | ImagePatternMatching.columnMatch( |
| 492 | paintedSlippyMap, |
| 493 | paintedSlippyMap.getWidth()/2, |
| 494 | paletteMap, |
| 495 | "^d+bq+v+bg+d+$", |
| 496 | true |
| 497 | ); |
| 498 | |
| 499 | // also assert the leftmost column doesn't (yet) have any downloaded area marks (i.e. fully shaded) |
| 500 | ImagePatternMatching.columnMatch( |
| 501 | paintedSlippyMap, |
| 502 | 0, |
| 503 | paletteMap, |
| 504 | "^d+$", |
| 505 | true |
| 506 | ); |
| 507 | |
| 508 | // add another downloaded area, going off the left of the widget |
| 509 | dataSet.addDataSource(new DataSource(new Bounds(51.745, -1., 51.765, 0.0162), "Somewhere else")); |
| 510 | // and redraw |
| 511 | this.paintSlippyMap(); |
| 512 | |
| 513 | // the middle row should be as before |
| 514 | ImagePatternMatching.rowMatch( |
| 515 | paintedSlippyMap, |
| 516 | paintedSlippyMap.getHeight()/2, |
| 517 | paletteMap, |
| 518 | "^d+bq+v+bg+d+$", |
| 519 | true |
| 520 | ); |
| 521 | // the middle column should have its unshaded region extended beyond the viewport marker |
| 522 | ImagePatternMatching.columnMatch( |
| 523 | paintedSlippyMap, |
| 524 | paintedSlippyMap.getWidth()/2, |
| 525 | paletteMap, |
| 526 | "^d+g+bv+bg+d+$", |
| 527 | true |
| 528 | ); |
| 529 | // but the leftmost column should now have an unshaded mark |
| 530 | ImagePatternMatching.columnMatch( |
| 531 | paintedSlippyMap, |
| 532 | 0, |
| 533 | paletteMap, |
| 534 | "^d+g+d+$", |
| 535 | true |
| 536 | ); |
| 537 | // and the rightmost column should be untouched |
| 538 | ImagePatternMatching.columnMatch( |
| 539 | paintedSlippyMap, |
| 540 | paintedSlippyMap.getWidth()-1, |
| 541 | paletteMap, |
| 542 | "^d+$", |
| 543 | true |
| 544 | ); |
| 545 | |
| 546 | // and now if we pan to the left (in EastNorth units) |
| 547 | mapView.zoomTo(mapView.getCenter().add(-5000., 0.)); |
| 548 | // and redraw |
| 549 | this.paintSlippyMap(); |
| 550 | |
| 551 | // the middle row should have its unshaded region outside the viewport marker |
| 552 | ImagePatternMatching.rowMatch( |
| 553 | paintedSlippyMap, |
| 554 | paintedSlippyMap.getHeight()/2, |
| 555 | paletteMap, |
| 556 | "^d+bq+bd+g+d*$", |
| 557 | true |
| 558 | ); |
| 559 | // the middle column should have a shaded region inside the viewport marker |
| 560 | ImagePatternMatching.columnMatch( |
| 561 | paintedSlippyMap, |
| 562 | paintedSlippyMap.getWidth()/2, |
| 563 | paletteMap, |
| 564 | "^d+g+bv+q+bd+$", |
| 565 | true |
| 566 | ); |
| 567 | } |
| 568 | |
| 569 | /** |
| 570 | * test display of downloaded area follows active layer switching |
| 571 | * @throws Exception if any error occurs |
| 572 | */ |
| 573 | @Test |
| 574 | public void testShowDownloadedAreaLayerSwitching() throws Exception { |
| 575 | Main.pref.put("slippy_map_chooser.mapstyle", "Green Tiles"); |
| 576 | Main.pref.putBoolean("slippy_map_chooser.show_downloaded_area", true); |
| 577 | |
| 578 | DataSet dataSetA = new DataSet(); |
| 579 | // dataSetA has a long thin horizontal downloaded area (extending off the left & right of the map) |
| 580 | dataSetA.addDataSource(new DataSource(new Bounds(-18., -61.02, -15., -60.98), "Elsewhere")); |
| 581 | |
| 582 | OsmDataLayer dataLayerA = new OsmDataLayer( |
| 583 | dataSetA, |
| 584 | "Test Layer A", |
| 585 | null |
| 586 | ); |
| 587 | MainApplication.getLayerManager().addLayer(dataLayerA); |
| 588 | |
| 589 | DataSet dataSetB = new DataSet(); |
| 590 | // dataSetB has a long thin vertical downloaded area (extending off the top & bottom of the map) |
| 591 | dataSetB.addDataSource(new DataSource(new Bounds(-16.38, -62., -16.34, -60.), "Nowhere")); |
| 592 | |
| 593 | OsmDataLayer dataLayerB = new OsmDataLayer( |
| 594 | dataSetB, |
| 595 | "Test Layer B", |
| 596 | null |
| 597 | ); |
| 598 | MainApplication.getLayerManager().addLayer(dataLayerB); |
| 599 | |
| 600 | MainApplication.getLayerManager().setActiveLayer(dataLayerB); |
| 601 | |
| 602 | MapView mapView = MainApplication.getMap().mapView; |
| 603 | GuiHelper.runInEDTAndWaitWithException(() -> { |
| 604 | mapView.setVisible(true); |
| 605 | mapView.addNotify(); |
| 606 | mapView.doLayout(); |
| 607 | mapView.setBounds(0, 0, 400, 400); |
| 608 | }); |
| 609 | |
| 610 | this.setUpMiniMap(); |
| 611 | |
| 612 | // assert "show downloaded areas" checkbox is checked |
| 613 | assertTrue(this.getShowDownloadedAreaMenuItem().isSelected()); |
| 614 | |
| 615 | // again, we won't end up with exactly this viewport as it doesn't *precisely* match the aspect ratio |
| 616 | mapView.zoomTo(new Bounds(-16.423, -61.076, -16.299, -60.932)); |
| 617 | |
| 618 | // an initial paint operation is required to trigger the tile fetches |
| 619 | this.paintSlippyMap(); |
| 620 | |
| 621 | Awaitility.await().atMost(1000, MILLISECONDS).until(this.slippyMapTasksFinished); |
| 622 | |
| 623 | this.paintSlippyMap(); |
| 624 | |
| 625 | Map<Integer, String> paletteMap = ImmutableMap.<Integer, String>builder() |
| 626 | .put(0xff00ff00, "g") // green |
| 627 | .put(0xff000000, "b") // black |
| 628 | .put(0xff8ad16b, "v") // viewport marker inner (pink+green mix) |
| 629 | .put(0xff00df00, "d") // (shaded green) |
| 630 | .put(0xff8ac46b, "q") // (shaded pink+green mix) |
| 631 | .build(); |
| 632 | |
| 633 | // the middle row should be entirely unshaded |
| 634 | ImagePatternMatching.rowMatch( |
| 635 | paintedSlippyMap, |
| 636 | paintedSlippyMap.getHeight()/2, |
| 637 | paletteMap, |
| 638 | "^g+bv+bg+$", |
| 639 | true |
| 640 | ); |
| 641 | // the middle column should have an unshaded band within the viewport marker |
| 642 | Matcher centerMatcher = ImagePatternMatching.columnMatch( |
| 643 | paintedSlippyMap, |
| 644 | paintedSlippyMap.getWidth()/2, |
| 645 | paletteMap, |
| 646 | "^(d+bq+)(v+)(q+bd+)$", |
| 647 | true |
| 648 | ); |
| 649 | // the leftmost and rightmost columns should have an unshaded band |
| 650 | Matcher leftMatcher = ImagePatternMatching.columnMatch( |
| 651 | paintedSlippyMap, |
| 652 | 0, |
| 653 | paletteMap, |
| 654 | "^(d+)(g+)(d+)$", |
| 655 | true |
| 656 | ); |
| 657 | Matcher rightMatcher = ImagePatternMatching.columnMatch( |
| 658 | paintedSlippyMap, |
| 659 | paintedSlippyMap.getWidth()-1, |
| 660 | paletteMap, |
| 661 | "^(d+)(g+)(d+)$", |
| 662 | true |
| 663 | ); |
| 664 | // the three columns should have the unshaded band in the same place |
| 665 | assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length()); |
| 666 | assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length()); |
| 667 | assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length()); |
| 668 | assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length()); |
| 669 | |
| 670 | // switch active layer |
| 671 | MainApplication.getLayerManager().setActiveLayer(dataLayerA); |
| 672 | this.paintSlippyMap(); |
| 673 | |
| 674 | // the middle column should be entirely unshaded |
| 675 | ImagePatternMatching.columnMatch( |
| 676 | paintedSlippyMap, |
| 677 | paintedSlippyMap.getWidth()/2, |
| 678 | paletteMap, |
| 679 | "^g+bv+bg+$", |
| 680 | true |
| 681 | ); |
| 682 | // the middle row should have an unshaded band within the viewport marker |
| 683 | centerMatcher = ImagePatternMatching.rowMatch( |
| 684 | paintedSlippyMap, |
| 685 | paintedSlippyMap.getHeight()/2, |
| 686 | paletteMap, |
| 687 | "^(d+bq+)(v+)(q+bd+)$", |
| 688 | true |
| 689 | ); |
| 690 | // the topmost and bottommost rows should have an unshaded band |
| 691 | Matcher topMatcher = ImagePatternMatching.rowMatch( |
| 692 | paintedSlippyMap, |
| 693 | 0, |
| 694 | paletteMap, |
| 695 | "^(d+)(g+)(d+)$", |
| 696 | true |
| 697 | ); |
| 698 | Matcher BottomMatcher = ImagePatternMatching.rowMatch( |
| 699 | paintedSlippyMap, |
| 700 | paintedSlippyMap.getHeight()-1, |
| 701 | paletteMap, |
| 702 | "^(d+)(g+)(d+)$", |
| 703 | true |
| 704 | ); |
| 705 | // the three rows should have the unshaded band in the same place |
| 706 | assertEquals(centerMatcher.group(1).length(), topMatcher.group(1).length()); |
| 707 | assertEquals(centerMatcher.group(1).length(), BottomMatcher.group(1).length()); |
| 708 | assertEquals(centerMatcher.group(2).length(), topMatcher.group(2).length()); |
| 709 | assertEquals(centerMatcher.group(2).length(), BottomMatcher.group(2).length()); |
| 710 | |
| 711 | // deleting dataLayerA should hopefully switch our active layer back to dataLayerB |
| 712 | MainApplication.getLayerManager().removeLayer(dataLayerA); |
| 713 | this.paintSlippyMap(); |
| 714 | |
| 715 | // now we're really just repeating the same assertions we made originally when dataLayerB was active |
| 716 | // the middle row should be entirely unshaded |
| 717 | ImagePatternMatching.rowMatch( |
| 718 | paintedSlippyMap, |
| 719 | paintedSlippyMap.getHeight()/2, |
| 720 | paletteMap, |
| 721 | "^g+bv+bg+$", |
| 722 | true |
| 723 | ); |
| 724 | // the middle column should have an unshaded band within the viewport marker |
| 725 | centerMatcher = ImagePatternMatching.columnMatch( |
| 726 | paintedSlippyMap, |
| 727 | paintedSlippyMap.getWidth()/2, |
| 728 | paletteMap, |
| 729 | "^(d+bq+)(v+)(q+bd+)$", |
| 730 | true |
| 731 | ); |
| 732 | // the leftmost and rightmost columns should have an unshaded band |
| 733 | leftMatcher = ImagePatternMatching.columnMatch( |
| 734 | paintedSlippyMap, |
| 735 | 0, |
| 736 | paletteMap, |
| 737 | "^(d+)(g+)(d+)$", |
| 738 | true |
| 739 | ); |
| 740 | rightMatcher = ImagePatternMatching.columnMatch( |
| 741 | paintedSlippyMap, |
| 742 | paintedSlippyMap.getWidth()-1, |
| 743 | paletteMap, |
| 744 | "^(d+)(g+)(d+)$", |
| 745 | true |
| 746 | ); |
| 747 | // the three columns should have the unshaded band in the same place |
| 748 | assertEquals(centerMatcher.group(1).length(), leftMatcher.group(1).length()); |
| 749 | assertEquals(centerMatcher.group(1).length(), rightMatcher.group(1).length()); |
| 750 | assertEquals(centerMatcher.group(2).length(), leftMatcher.group(2).length()); |
| 751 | assertEquals(centerMatcher.group(2).length(), rightMatcher.group(2).length()); |
| 752 | |
| 753 | // but now if we expand its downloaded area to cover most of the southern hemisphere... |
| 754 | dataSetB.addDataSource(new DataSource(new Bounds(-75., -100., 0., 100.), "Everywhere")); |
| 755 | this.paintSlippyMap(); |
| 756 | |
| 757 | // we should see it all as unshaded. |
| 758 | ImagePatternMatching.rowMatch( |
| 759 | paintedSlippyMap, |
| 760 | 0, |
| 761 | paletteMap, |
| 762 | "^g+$", |
| 763 | true |
| 764 | ); |
| 765 | ImagePatternMatching.rowMatch( |
| 766 | paintedSlippyMap, |
| 767 | paintedSlippyMap.getHeight()/2, |
| 768 | paletteMap, |
| 769 | "^g+bv+bg+$", |
| 770 | true |
| 771 | ); |
| 772 | ImagePatternMatching.rowMatch( |
| 773 | paintedSlippyMap, |
| 774 | paintedSlippyMap.getHeight()-1, |
| 775 | paletteMap, |
| 776 | "^g+$", |
| 777 | true |
| 778 | ); |
| 779 | ImagePatternMatching.columnMatch( |
| 780 | paintedSlippyMap, |
| 781 | 0, |
| 782 | paletteMap, |
| 783 | "^g+$", |
| 784 | true |
| 785 | ); |
| 786 | ImagePatternMatching.columnMatch( |
| 787 | paintedSlippyMap, |
| 788 | paintedSlippyMap.getWidth()/2, |
| 789 | paletteMap, |
| 790 | "^g+bv+bg+$", |
| 791 | true |
| 792 | ); |
| 793 | ImagePatternMatching.columnMatch( |
| 794 | paintedSlippyMap, |
| 795 | paintedSlippyMap.getWidth()-1, |
| 796 | paletteMap, |
| 797 | "^g+$", |
| 798 | true |
| 799 | ); |
| 800 | } |