001 package org.openstreetmap.gui.jmapviewer; 002 003 //License: GPL. Copyright 2008 by Jan Peter Stotz 004 005 import java.awt.Color; 006 import java.awt.Dimension; 007 import java.awt.Font; 008 import java.awt.Graphics; 009 import java.awt.Image; 010 import java.awt.Insets; 011 import java.awt.Point; 012 import java.awt.Rectangle; 013 import java.awt.event.ActionEvent; 014 import java.awt.event.ActionListener; 015 import java.awt.event.MouseEvent; 016 import java.awt.font.TextAttribute; 017 import java.awt.geom.Rectangle2D; 018 import java.util.HashMap; 019 import java.util.LinkedList; 020 import java.util.List; 021 022 import javax.swing.ImageIcon; 023 import javax.swing.JButton; 024 import javax.swing.JPanel; 025 import javax.swing.JSlider; 026 import javax.swing.event.ChangeEvent; 027 import javax.swing.event.ChangeListener; 028 import javax.swing.event.EventListenerList; 029 030 import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent; 031 import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent.COMMAND; 032 import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener; 033 import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker; 034 import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon; 035 import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle; 036 import org.openstreetmap.gui.jmapviewer.interfaces.TileCache; 037 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 038 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 039 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 040 import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource; 041 042 /** 043 * 044 * Provides a simple panel that displays pre-rendered map tiles loaded from the 045 * OpenStreetMap project. 046 * 047 * @author Jan Peter Stotz 048 * 049 */ 050 public class JMapViewer extends JPanel implements TileLoaderListener { 051 052 private static final long serialVersionUID = 1L; 053 054 /** 055 * Vectors for clock-wise tile painting 056 */ 057 protected static final Point[] move = { new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(0, -1) }; 058 059 public static final int MAX_ZOOM = 22; 060 public static final int MIN_ZOOM = 0; 061 062 protected List<MapMarker> mapMarkerList; 063 protected List<MapRectangle> mapRectangleList; 064 protected List<MapPolygon> mapPolygonList; 065 066 protected boolean mapMarkersVisible; 067 protected boolean mapRectanglesVisible; 068 protected boolean mapPolygonsVisible; 069 070 protected boolean tileGridVisible; 071 072 protected TileController tileController; 073 074 /** 075 * x- and y-position of the center of this map-panel on the world map 076 * denoted in screen pixel regarding the current zoom level. 077 */ 078 protected Point center; 079 080 /** 081 * Current zoom level 082 */ 083 protected int zoom; 084 085 protected JSlider zoomSlider; 086 protected JButton zoomInButton; 087 protected JButton zoomOutButton; 088 089 private TileSource tileSource; 090 091 protected AttributionSupport attribution = new AttributionSupport(); 092 093 /** 094 * Creates a standard {@link JMapViewer} instance that can be controlled via 095 * mouse: hold right mouse button for moving, double click left mouse button 096 * or use mouse wheel for zooming. Loaded tiles are stored the 097 * {@link MemoryTileCache} and the tile loader uses 4 parallel threads for 098 * retrieving the tiles. 099 */ 100 public JMapViewer() { 101 this(new MemoryTileCache(), 4); 102 new DefaultMapController(this); 103 } 104 105 public JMapViewer(TileCache tileCache, int downloadThreadCount) { 106 super(); 107 tileSource = new OsmTileSource.Mapnik(); 108 tileController = new TileController(tileSource, tileCache, this); 109 mapMarkerList = new LinkedList<MapMarker>(); 110 mapPolygonList = new LinkedList<MapPolygon>(); 111 mapRectangleList = new LinkedList<MapRectangle>(); 112 mapMarkersVisible = true; 113 mapRectanglesVisible = true; 114 mapPolygonsVisible = true; 115 tileGridVisible = false; 116 setLayout(null); 117 initializeZoomSlider(); 118 setMinimumSize(new Dimension(tileSource.getTileSize(), tileSource.getTileSize())); 119 setPreferredSize(new Dimension(400, 400)); 120 setDisplayPositionByLatLon(50, 9, 3); 121 //setToolTipText(""); 122 } 123 124 @Override 125 public String getToolTipText(MouseEvent event) { 126 // Point screenPoint = event.getLocationOnScreen(); 127 // Coordinate c = getPosition(screenPoint); 128 return super.getToolTipText(event); 129 } 130 131 protected void initializeZoomSlider() { 132 zoomSlider = new JSlider(MIN_ZOOM, tileController.getTileSource().getMaxZoom()); 133 zoomSlider.setOrientation(JSlider.VERTICAL); 134 zoomSlider.setBounds(10, 10, 30, 150); 135 zoomSlider.setOpaque(false); 136 zoomSlider.addChangeListener(new ChangeListener() { 137 public void stateChanged(ChangeEvent e) { 138 setZoom(zoomSlider.getValue()); 139 } 140 }); 141 add(zoomSlider); 142 int size = 18; 143 try { 144 ImageIcon icon = new ImageIcon(getClass().getResource("images/plus.png")); 145 zoomInButton = new JButton(icon); 146 } catch (Exception e) { 147 zoomInButton = new JButton("+"); 148 zoomInButton.setFont(new Font("sansserif", Font.BOLD, 9)); 149 zoomInButton.setMargin(new Insets(0, 0, 0, 0)); 150 } 151 zoomInButton.setBounds(4, 155, size, size); 152 zoomInButton.addActionListener(new ActionListener() { 153 154 public void actionPerformed(ActionEvent e) { 155 zoomIn(); 156 } 157 }); 158 add(zoomInButton); 159 try { 160 ImageIcon icon = new ImageIcon(getClass().getResource("images/minus.png")); 161 zoomOutButton = new JButton(icon); 162 } catch (Exception e) { 163 zoomOutButton = new JButton("-"); 164 zoomOutButton.setFont(new Font("sansserif", Font.BOLD, 9)); 165 zoomOutButton.setMargin(new Insets(0, 0, 0, 0)); 166 } 167 zoomOutButton.setBounds(8 + size, 155, size, size); 168 zoomOutButton.addActionListener(new ActionListener() { 169 170 public void actionPerformed(ActionEvent e) { 171 zoomOut(); 172 } 173 }); 174 add(zoomOutButton); 175 } 176 177 /** 178 * Changes the map pane so that it is centered on the specified coordinate 179 * at the given zoom level. 180 * 181 * @param lat 182 * latitude of the specified coordinate 183 * @param lon 184 * longitude of the specified coordinate 185 * @param zoom 186 * {@link #MIN_ZOOM} <= zoom level <= {@link #MAX_ZOOM} 187 */ 188 public void setDisplayPositionByLatLon(double lat, double lon, int zoom) { 189 setDisplayPositionByLatLon(new Point(getWidth() / 2, getHeight() / 2), lat, lon, zoom); 190 } 191 192 /** 193 * Changes the map pane so that the specified coordinate at the given zoom 194 * level is displayed on the map at the screen coordinate 195 * <code>mapPoint</code>. 196 * 197 * @param mapPoint 198 * point on the map denoted in pixels where the coordinate should 199 * be set 200 * @param lat 201 * latitude of the specified coordinate 202 * @param lon 203 * longitude of the specified coordinate 204 * @param zoom 205 * {@link #MIN_ZOOM} <= zoom level <= 206 * {@link TileSource#getMaxZoom()} 207 */ 208 public void setDisplayPositionByLatLon(Point mapPoint, double lat, double lon, int zoom) { 209 int x = OsmMercator.LonToX(lon, zoom); 210 int y = OsmMercator.LatToY(lat, zoom); 211 setDisplayPosition(mapPoint, x, y, zoom); 212 } 213 214 public void setDisplayPosition(int x, int y, int zoom) { 215 setDisplayPosition(new Point(getWidth() / 2, getHeight() / 2), x, y, zoom); 216 } 217 218 public void setDisplayPosition(Point mapPoint, int x, int y, int zoom) { 219 if (zoom > tileController.getTileSource().getMaxZoom() || zoom < MIN_ZOOM) 220 return; 221 222 // Get the plain tile number 223 Point p = new Point(); 224 p.x = x - mapPoint.x + getWidth() / 2; 225 p.y = y - mapPoint.y + getHeight() / 2; 226 center = p; 227 setIgnoreRepaint(true); 228 try { 229 int oldZoom = this.zoom; 230 this.zoom = zoom; 231 if (oldZoom != zoom) { 232 zoomChanged(oldZoom); 233 } 234 if (zoomSlider.getValue() != zoom) { 235 zoomSlider.setValue(zoom); 236 } 237 } finally { 238 setIgnoreRepaint(false); 239 repaint(); 240 } 241 } 242 243 /** 244 * Sets the displayed map pane and zoom level so that all chosen map elements are 245 * visible. 246 */ 247 public void setDisplayToFitMapElements(boolean markers, boolean rectangles, boolean polygons) { 248 int nbElemToCheck = 0; 249 if (markers && mapMarkerList != null) 250 nbElemToCheck += mapMarkerList.size(); 251 if (rectangles && mapRectangleList != null) 252 nbElemToCheck += mapRectangleList.size(); 253 if (polygons && mapPolygonList != null) 254 nbElemToCheck += mapPolygonList.size(); 255 if (nbElemToCheck == 0) 256 return; 257 258 int x_min = Integer.MAX_VALUE; 259 int y_min = Integer.MAX_VALUE; 260 int x_max = Integer.MIN_VALUE; 261 int y_max = Integer.MIN_VALUE; 262 int mapZoomMax = tileController.getTileSource().getMaxZoom(); 263 264 if (markers) { 265 for (MapMarker marker : mapMarkerList) { 266 int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax); 267 int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax); 268 x_max = Math.max(x_max, x); 269 y_max = Math.max(y_max, y); 270 x_min = Math.min(x_min, x); 271 y_min = Math.min(y_min, y); 272 } 273 } 274 275 if (rectangles) { 276 for (MapRectangle rectangle : mapRectangleList) { 277 x_max = Math.max(x_max, OsmMercator.LonToX(rectangle.getBottomRight().getLon(), mapZoomMax)); 278 y_max = Math.max(y_max, OsmMercator.LatToY(rectangle.getTopLeft().getLat(), mapZoomMax)); 279 x_min = Math.min(x_min, OsmMercator.LonToX(rectangle.getTopLeft().getLon(), mapZoomMax)); 280 y_min = Math.min(y_min, OsmMercator.LatToY(rectangle.getBottomRight().getLat(), mapZoomMax)); 281 } 282 } 283 284 if (polygons) { 285 for (MapPolygon polygon : mapPolygonList) { 286 for (Coordinate c : polygon.getPoints()) { 287 int x = OsmMercator.LonToX(c.getLon(), mapZoomMax); 288 int y = OsmMercator.LatToY(c.getLat(), mapZoomMax); 289 x_max = Math.max(x_max, x); 290 y_max = Math.max(y_max, y); 291 x_min = Math.min(x_min, x); 292 y_min = Math.min(y_min, y); 293 } 294 } 295 } 296 297 int height = Math.max(0, getHeight()); 298 int width = Math.max(0, getWidth()); 299 int newZoom = mapZoomMax; 300 int x = x_max - x_min; 301 int y = y_max - y_min; 302 while (x > width || y > height) { 303 newZoom--; 304 x >>= 1; 305 y >>= 1; 306 } 307 x = x_min + (x_max - x_min) / 2; 308 y = y_min + (y_max - y_min) / 2; 309 int z = 1 << (mapZoomMax - newZoom); 310 x /= z; 311 y /= z; 312 setDisplayPosition(x, y, newZoom); 313 } 314 315 316 /** 317 * Sets the displayed map pane and zoom level so that all map markers are 318 * visible. 319 */ 320 public void setDisplayToFitMapMarkers() { 321 setDisplayToFitMapElements(true, false, false); 322 } 323 324 /** 325 * Sets the displayed map pane and zoom level so that all map rectangles are 326 * visible. 327 */ 328 public void setDisplayToFitMapRectangles() { 329 setDisplayToFitMapElements(false, true, false); 330 } 331 332 /** 333 * Sets the displayed map pane and zoom level so that all map polygons are 334 * visible. 335 */ 336 public void setDisplayToFitMapPolygons() { 337 setDisplayToFitMapElements(false, false, true); 338 } 339 340 /** 341 * @return the center 342 */ 343 public Point getCenter() { 344 return center; 345 } 346 347 /** 348 * @param center the center to set 349 */ 350 public void setCenter(Point center) { 351 this.center = center; 352 } 353 354 /** 355 * Calculates the latitude/longitude coordinate of the center of the 356 * currently displayed map area. 357 * 358 * @return latitude / longitude 359 */ 360 public Coordinate getPosition() { 361 double lon = OsmMercator.XToLon(center.x, zoom); 362 double lat = OsmMercator.YToLat(center.y, zoom); 363 return new Coordinate(lat, lon); 364 } 365 366 /** 367 * Converts the relative pixel coordinate (regarding the top left corner of 368 * the displayed map) into a latitude / longitude coordinate 369 * 370 * @param mapPoint 371 * relative pixel coordinate regarding the top left corner of the 372 * displayed map 373 * @return latitude / longitude 374 */ 375 public Coordinate getPosition(Point mapPoint) { 376 return getPosition(mapPoint.x, mapPoint.y); 377 } 378 379 /** 380 * Converts the relative pixel coordinate (regarding the top left corner of 381 * the displayed map) into a latitude / longitude coordinate 382 * 383 * @param mapPointX 384 * @param mapPointY 385 * @return latitude / longitude 386 */ 387 public Coordinate getPosition(int mapPointX, int mapPointY) { 388 int x = center.x + mapPointX - getWidth() / 2; 389 int y = center.y + mapPointY - getHeight() / 2; 390 double lon = OsmMercator.XToLon(x, zoom); 391 double lat = OsmMercator.YToLat(y, zoom); 392 return new Coordinate(lat, lon); 393 } 394 395 /** 396 * Calculates the position on the map of a given coordinate 397 * 398 * @param lat 399 * @param lon 400 * @param checkOutside 401 * @return point on the map or <code>null</code> if the point is not visible 402 * and checkOutside set to <code>true</code> 403 */ 404 public Point getMapPosition(double lat, double lon, boolean checkOutside) { 405 int x = OsmMercator.LonToX(lon, zoom); 406 int y = OsmMercator.LatToY(lat, zoom); 407 x -= center.x - getWidth() / 2; 408 y -= center.y - getHeight() / 2; 409 if (checkOutside) { 410 if (x < 0 || y < 0 || x > getWidth() || y > getHeight()) 411 return null; 412 } 413 return new Point(x, y); 414 } 415 416 /** 417 * Calculates the position on the map of a given coordinate 418 * 419 * @param lat 420 * @param lon 421 * @return point on the map or <code>null</code> if the point is not visible 422 */ 423 public Point getMapPosition(double lat, double lon) { 424 return getMapPosition(lat, lon, true); 425 } 426 427 /** 428 * Calculates the position on the map of a given coordinate 429 * 430 * @param coord 431 * @return point on the map or <code>null</code> if the point is not visible 432 */ 433 public Point getMapPosition(Coordinate coord) { 434 if (coord != null) 435 return getMapPosition(coord.getLat(), coord.getLon()); 436 else 437 return null; 438 } 439 440 /** 441 * Calculates the position on the map of a given coordinate 442 * 443 * @param coord 444 * @return point on the map or <code>null</code> if the point is not visible 445 * and checkOutside set to <code>true</code> 446 */ 447 public Point getMapPosition(Coordinate coord, boolean checkOutside) { 448 if (coord != null) 449 return getMapPosition(coord.getLat(), coord.getLon(), checkOutside); 450 else 451 return null; 452 } 453 454 /** 455 * Gets the meter per pixel. 456 * 457 * @return the meter per pixel 458 * @author Jason Huntley 459 */ 460 public double getMeterPerPixel() { 461 Point origin=new Point(5,5); 462 Point center=new Point(getWidth()/2, getHeight()/2); 463 464 double pDistance=center.distance(origin); 465 466 Coordinate originCoord=getPosition(origin); 467 Coordinate centerCoord=getPosition(center); 468 469 double mDistance=OsmMercator.getDistance(originCoord.getLat(), originCoord.getLon(), 470 centerCoord.getLat(), centerCoord.getLon()); 471 472 return mDistance/pDistance; 473 } 474 475 @Override 476 protected void paintComponent(Graphics g) { 477 super.paintComponent(g); 478 479 int iMove = 0; 480 481 int tilesize = tileSource.getTileSize(); 482 int tilex = center.x / tilesize; 483 int tiley = center.y / tilesize; 484 int off_x = (center.x % tilesize); 485 int off_y = (center.y % tilesize); 486 487 int w2 = getWidth() / 2; 488 int h2 = getHeight() / 2; 489 int posx = w2 - off_x; 490 int posy = h2 - off_y; 491 492 int diff_left = off_x; 493 int diff_right = tilesize - off_x; 494 int diff_top = off_y; 495 int diff_bottom = tilesize - off_y; 496 497 boolean start_left = diff_left < diff_right; 498 boolean start_top = diff_top < diff_bottom; 499 500 if (start_top) { 501 if (start_left) { 502 iMove = 2; 503 } else { 504 iMove = 3; 505 } 506 } else { 507 if (start_left) { 508 iMove = 1; 509 } else { 510 iMove = 0; 511 } 512 } // calculate the visibility borders 513 int x_min = -tilesize; 514 int y_min = -tilesize; 515 int x_max = getWidth(); 516 int y_max = getHeight(); 517 518 // paint the tiles in a spiral, starting from center of the map 519 boolean painted = true; 520 int x = 0; 521 while (painted) { 522 painted = false; 523 for (int i = 0; i < 4; i++) { 524 if (i % 2 == 0) { 525 x++; 526 } 527 for (int j = 0; j < x; j++) { 528 if (x_min <= posx && posx <= x_max && y_min <= posy && posy <= y_max) { 529 // tile is visible 530 Tile tile = tileController.getTile(tilex, tiley, zoom); 531 if (tile != null) { 532 painted = true; 533 tile.paint(g, posx, posy); 534 if (tileGridVisible) { 535 g.drawRect(posx, posy, tilesize, tilesize); 536 } 537 } 538 } 539 Point p = move[iMove]; 540 posx += p.x * tilesize; 541 posy += p.y * tilesize; 542 tilex += p.x; 543 tiley += p.y; 544 } 545 iMove = (iMove + 1) % move.length; 546 } 547 } 548 // outer border of the map 549 int mapSize = tilesize << zoom; 550 g.drawRect(w2 - center.x, h2 - center.y, mapSize, mapSize); 551 552 // g.drawString("Tiles in cache: " + tileCache.getTileCount(), 50, 20); 553 554 if (mapPolygonsVisible && mapPolygonList != null) { 555 for (MapPolygon polygon : mapPolygonList) { 556 paintPolygon(g, polygon); 557 } 558 } 559 560 if (mapRectanglesVisible && mapRectangleList != null) { 561 for (MapRectangle rectangle : mapRectangleList) { 562 paintRectangle(g, rectangle); 563 } 564 } 565 566 if (mapMarkersVisible && mapMarkerList != null) { 567 for (MapMarker marker : mapMarkerList) { 568 paintMarker(g, marker); 569 } 570 } 571 572 attribution.paintAttribution(g, getWidth(), getHeight(), getPosition(0, 0), getPosition(getWidth(), getHeight()), zoom, this); 573 } 574 575 /** 576 * Paint a single marker. 577 */ 578 protected void paintMarker(Graphics g, MapMarker marker) { 579 Point p = getMapPosition(marker.getLat(), marker.getLon()); 580 if (p != null) { 581 marker.paint(g, p); 582 } 583 } 584 585 /** 586 * Paint a single rectangle. 587 */ 588 protected void paintRectangle(Graphics g, MapRectangle rectangle) { 589 Coordinate topLeft = rectangle.getTopLeft(); 590 Coordinate bottomRight = rectangle.getBottomRight(); 591 if (topLeft != null && bottomRight != null) { 592 Point pTopLeft = getMapPosition(topLeft, false); 593 Point pBottomRight = getMapPosition(bottomRight, false); 594 if (pTopLeft != null && pBottomRight != null) { 595 rectangle.paint(g, pTopLeft, pBottomRight); 596 } 597 } 598 } 599 600 /** 601 * Paint a single polygon. 602 */ 603 protected void paintPolygon(Graphics g, MapPolygon polygon) { 604 List<Coordinate> coords = polygon.getPoints(); 605 if (coords != null && coords.size() >= 3) { 606 List<Point> points = new LinkedList<Point>(); 607 for (Coordinate c : coords) { 608 Point p = getMapPosition(c, false); 609 if (p == null) { 610 return; 611 } 612 points.add(p); 613 } 614 polygon.paint(g, points); 615 } 616 } 617 618 /** 619 * Moves the visible map pane. 620 * 621 * @param x 622 * horizontal movement in pixel. 623 * @param y 624 * vertical movement in pixel 625 */ 626 public void moveMap(int x, int y) { 627 center.x += x; 628 center.y += y; 629 repaint(); 630 this.fireJMVEvent(new JMVCommandEvent(COMMAND.MOVE, this)); 631 } 632 633 /** 634 * @return the current zoom level 635 */ 636 public int getZoom() { 637 return zoom; 638 } 639 640 /** 641 * Increases the current zoom level by one 642 */ 643 public void zoomIn() { 644 setZoom(zoom + 1); 645 } 646 647 /** 648 * Increases the current zoom level by one 649 */ 650 public void zoomIn(Point mapPoint) { 651 setZoom(zoom + 1, mapPoint); 652 } 653 654 /** 655 * Decreases the current zoom level by one 656 */ 657 public void zoomOut() { 658 setZoom(zoom - 1); 659 } 660 661 /** 662 * Decreases the current zoom level by one 663 * 664 * @param mapPoint point to choose as center for new zoom level 665 */ 666 public void zoomOut(Point mapPoint) { 667 setZoom(zoom - 1, mapPoint); 668 } 669 670 /** 671 * Set the zoom level and center point for display 672 * 673 * @param zoom new zoom level 674 * @param mapPoint point to choose as center for new zoom level 675 */ 676 public void setZoom(int zoom, Point mapPoint) { 677 if (zoom > tileController.getTileSource().getMaxZoom() || zoom < tileController.getTileSource().getMinZoom() 678 || zoom == this.zoom) 679 return; 680 Coordinate zoomPos = getPosition(mapPoint); 681 tileController.cancelOutstandingJobs(); // Clearing outstanding load 682 // requests 683 setDisplayPositionByLatLon(mapPoint, zoomPos.getLat(), zoomPos.getLon(), zoom); 684 685 this.fireJMVEvent(new JMVCommandEvent(COMMAND.ZOOM, this)); 686 } 687 688 /** 689 * Set the zoom level 690 * 691 * @param zoom new zoom level 692 */ 693 public void setZoom(int zoom) { 694 setZoom(zoom, new Point(getWidth() / 2, getHeight() / 2)); 695 } 696 697 /** 698 * Every time the zoom level changes this method is called. Override it in 699 * derived implementations for adapting zoom dependent values. The new zoom 700 * level can be obtained via {@link #getZoom()}. 701 * 702 * @param oldZoom 703 * the previous zoom level 704 */ 705 protected void zoomChanged(int oldZoom) { 706 zoomSlider.setToolTipText("Zoom level " + zoom); 707 zoomInButton.setToolTipText("Zoom to level " + (zoom + 1)); 708 zoomOutButton.setToolTipText("Zoom to level " + (zoom - 1)); 709 zoomOutButton.setEnabled(zoom > tileController.getTileSource().getMinZoom()); 710 zoomInButton.setEnabled(zoom < tileController.getTileSource().getMaxZoom()); 711 } 712 713 public boolean isTileGridVisible() { 714 return tileGridVisible; 715 } 716 717 public void setTileGridVisible(boolean tileGridVisible) { 718 this.tileGridVisible = tileGridVisible; 719 repaint(); 720 } 721 722 public boolean getMapMarkersVisible() { 723 return mapMarkersVisible; 724 } 725 726 /** 727 * Enables or disables painting of the {@link MapMarker} 728 * 729 * @param mapMarkersVisible 730 * @see #addMapMarker(MapMarker) 731 * @see #getMapMarkerList() 732 */ 733 public void setMapMarkerVisible(boolean mapMarkersVisible) { 734 this.mapMarkersVisible = mapMarkersVisible; 735 repaint(); 736 } 737 738 public void setMapMarkerList(List<MapMarker> mapMarkerList) { 739 this.mapMarkerList = mapMarkerList; 740 repaint(); 741 } 742 743 public List<MapMarker> getMapMarkerList() { 744 return mapMarkerList; 745 } 746 747 public void setMapRectangleList(List<MapRectangle> mapRectangleList) { 748 this.mapRectangleList = mapRectangleList; 749 repaint(); 750 } 751 752 public List<MapRectangle> getMapRectangleList() { 753 return mapRectangleList; 754 } 755 756 public void setMapPolygonList(List<MapPolygon> mapPolygonList) { 757 this.mapPolygonList = mapPolygonList; 758 repaint(); 759 } 760 761 public List<MapPolygon> getMapPolygonList() { 762 return mapPolygonList; 763 } 764 765 public void addMapMarker(MapMarker marker) { 766 mapMarkerList.add(marker); 767 repaint(); 768 } 769 770 public void removeMapMarker(MapMarker marker) { 771 mapMarkerList.remove(marker); 772 repaint(); 773 } 774 775 public void removeAllMapMarkers() { 776 mapMarkerList.clear(); 777 repaint(); 778 } 779 780 public void addMapRectangle(MapRectangle rectangle) { 781 mapRectangleList.add(rectangle); 782 repaint(); 783 } 784 785 public void removeMapRectangle(MapRectangle rectangle) { 786 mapRectangleList.remove(rectangle); 787 repaint(); 788 } 789 790 public void removeAllMapRectangles() { 791 mapRectangleList.clear(); 792 repaint(); 793 } 794 795 public void addMapPolygon(MapPolygon polygon) { 796 mapPolygonList.add(polygon); 797 repaint(); 798 } 799 800 public void removeMapPolygon(MapPolygon polygon) { 801 mapPolygonList.remove(polygon); 802 repaint(); 803 } 804 805 public void removeAllMapPolygons() { 806 mapPolygonList.clear(); 807 repaint(); 808 } 809 810 public void setZoomContolsVisible(boolean visible) { 811 zoomSlider.setVisible(visible); 812 zoomInButton.setVisible(visible); 813 zoomOutButton.setVisible(visible); 814 } 815 816 public boolean getZoomContolsVisible() { 817 return zoomSlider.isVisible(); 818 } 819 820 public void setTileSource(TileSource tileSource) { 821 if (tileSource.getMaxZoom() > MAX_ZOOM) 822 throw new RuntimeException("Maximum zoom level too high"); 823 if (tileSource.getMinZoom() < MIN_ZOOM) 824 throw new RuntimeException("Minumim zoom level too low"); 825 this.tileSource = tileSource; 826 tileController.setTileSource(tileSource); 827 zoomSlider.setMinimum(tileSource.getMinZoom()); 828 zoomSlider.setMaximum(tileSource.getMaxZoom()); 829 tileController.cancelOutstandingJobs(); 830 if (zoom > tileSource.getMaxZoom()) { 831 setZoom(tileSource.getMaxZoom()); 832 } 833 834 attribution.initialize(tileSource); 835 repaint(); 836 } 837 838 public void tileLoadingFinished(Tile tile, boolean success) { 839 repaint(); 840 } 841 842 public boolean isMapRectanglesVisible() { 843 return mapRectanglesVisible; 844 } 845 846 /** 847 * Enables or disables painting of the {@link MapRectangle} 848 * 849 * @param mapRectanglesVisible 850 * @see #addMapRectangle(MapRectangle) 851 * @see #getMapRectangleList() 852 */ 853 public void setMapRectanglesVisible(boolean mapRectanglesVisible) { 854 this.mapRectanglesVisible = mapRectanglesVisible; 855 repaint(); 856 } 857 858 public boolean isMapPolygonsVisible() { 859 return mapPolygonsVisible; 860 } 861 862 /** 863 * Enables or disables painting of the {@link MapPolygon} 864 * 865 * @param mapPolygonsVisible 866 * @see #addMapPolygon(MapPolygon) 867 * @see #getMapPolygonList() 868 */ 869 public void setMapPolygonsVisible(boolean mapPolygonsVisible) { 870 this.mapPolygonsVisible = mapPolygonsVisible; 871 repaint(); 872 } 873 874 /** 875 * Return tile information caching class 876 * @see TileLoaderListener#getTileCache() 877 */ 878 public TileCache getTileCache() { 879 return tileController.getTileCache(); 880 } 881 882 public void setTileLoader(TileLoader loader) { 883 tileController.setTileLoader(loader); 884 } 885 886 protected EventListenerList listenerList = new EventListenerList(); 887 888 /** 889 * @param listener listener to set 890 */ 891 public void addJMVListener(JMapViewerEventListener listener) { 892 listenerList.add(JMapViewerEventListener.class, listener); 893 } 894 895 /** 896 * @param listener listener to remove 897 */ 898 public void removeJMVListener(JMapViewerEventListener listener) { 899 listenerList.remove(JMapViewerEventListener.class, listener); 900 } 901 902 /** 903 * Send an update to all objects registered with viewer 904 * 905 * @param event to dispatch 906 */ 907 void fireJMVEvent(JMVCommandEvent evt) { 908 Object[] listeners = listenerList.getListenerList(); 909 for (int i=0; i<listeners.length; i+=2) { 910 if (listeners[i]==JMapViewerEventListener.class) { 911 ((JMapViewerEventListener)listeners[i+1]).processCommand(evt); 912 } 913 } 914 } 915 }