| 1 | package org.openstreetmap.gui.jmapviewer;
|
|---|
| 2 |
|
|---|
| 3 | //License: GPL. Copyright 2008 by Jan Peter Stotz
|
|---|
| 4 |
|
|---|
| 5 | import java.awt.Color;
|
|---|
| 6 | import java.awt.Dimension;
|
|---|
| 7 | import java.awt.Font;
|
|---|
| 8 | import java.awt.Graphics;
|
|---|
| 9 | import java.awt.Image;
|
|---|
| 10 | import java.awt.Insets;
|
|---|
| 11 | import java.awt.Point;
|
|---|
| 12 | import java.awt.Rectangle;
|
|---|
| 13 | import java.awt.event.ActionEvent;
|
|---|
| 14 | import java.awt.event.ActionListener;
|
|---|
| 15 | import java.awt.event.MouseEvent;
|
|---|
| 16 | import java.awt.font.TextAttribute;
|
|---|
| 17 | import java.awt.geom.Rectangle2D;
|
|---|
| 18 | import java.util.HashMap;
|
|---|
| 19 | import java.util.LinkedList;
|
|---|
| 20 | import java.util.List;
|
|---|
| 21 |
|
|---|
| 22 | import javax.swing.ImageIcon;
|
|---|
| 23 | import javax.swing.JButton;
|
|---|
| 24 | import javax.swing.JPanel;
|
|---|
| 25 | import javax.swing.JSlider;
|
|---|
| 26 | import javax.swing.event.ChangeEvent;
|
|---|
| 27 | import javax.swing.event.ChangeListener;
|
|---|
| 28 | import javax.swing.event.EventListenerList;
|
|---|
| 29 |
|
|---|
| 30 | import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent;
|
|---|
| 31 | import org.openstreetmap.gui.jmapviewer.events.JMVCommandEvent.COMMAND;
|
|---|
| 32 | import org.openstreetmap.gui.jmapviewer.interfaces.JMapViewerEventListener;
|
|---|
| 33 | import org.openstreetmap.gui.jmapviewer.interfaces.MapMarker;
|
|---|
| 34 | import org.openstreetmap.gui.jmapviewer.interfaces.MapPolygon;
|
|---|
| 35 | import org.openstreetmap.gui.jmapviewer.interfaces.MapObject;
|
|---|
| 36 | import org.openstreetmap.gui.jmapviewer.interfaces.MapRectangle;
|
|---|
| 37 | import org.openstreetmap.gui.jmapviewer.interfaces.TileCache;
|
|---|
| 38 | import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
|
|---|
| 39 | import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
|
|---|
| 40 | import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
|
|---|
| 41 | import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource;
|
|---|
| 42 |
|
|---|
| 43 | import com.houghtonassociates.nexus.core.math.ACPMMathUtil;
|
|---|
| 44 |
|
|---|
| 45 | /**
|
|---|
| 46 | *
|
|---|
| 47 | * Provides a simple panel that displays pre-rendered map tiles loaded from the
|
|---|
| 48 | * OpenStreetMap project.
|
|---|
| 49 | *
|
|---|
| 50 | * @author Jan Peter Stotz
|
|---|
| 51 | *
|
|---|
| 52 | */
|
|---|
| 53 | public class JMapViewer extends JPanel implements TileLoaderListener {
|
|---|
| 54 |
|
|---|
| 55 | private static final long serialVersionUID = 1L;
|
|---|
| 56 |
|
|---|
| 57 | /**
|
|---|
| 58 | * Vectors for clock-wise tile painting
|
|---|
| 59 | */
|
|---|
| 60 | protected static final Point[] move = { new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(0, -1) };
|
|---|
| 61 |
|
|---|
| 62 | public static final int MAX_ZOOM = 22;
|
|---|
| 63 | public static final int MIN_ZOOM = 0;
|
|---|
| 64 |
|
|---|
| 65 | protected List<MapMarker> mapMarkerList;
|
|---|
| 66 | protected List<MapRectangle> mapRectangleList;
|
|---|
| 67 |
|
|---|
| 68 | protected List<MapPolygon> mapPolygonList;
|
|---|
| 69 | protected List<MapObject> mapObjectList;
|
|---|
| 70 |
|
|---|
| 71 | protected boolean mapMarkersVisible;
|
|---|
| 72 | protected boolean mapRectanglesVisible;
|
|---|
| 73 | protected boolean mapPolygonsVisible;
|
|---|
| 74 |
|
|---|
| 75 | protected boolean tileGridVisible;
|
|---|
| 76 |
|
|---|
| 77 | protected TileController tileController;
|
|---|
| 78 |
|
|---|
| 79 | /**
|
|---|
| 80 | * x- and y-position of the center of this map-panel on the world map
|
|---|
| 81 | * denoted in screen pixel regarding the current zoom level.
|
|---|
| 82 | */
|
|---|
| 83 | protected Point center;
|
|---|
| 84 |
|
|---|
| 85 | /**
|
|---|
| 86 | * Current zoom level
|
|---|
| 87 | */
|
|---|
| 88 | protected int zoom;
|
|---|
| 89 |
|
|---|
| 90 | protected JSlider zoomSlider;
|
|---|
| 91 | protected JButton zoomInButton;
|
|---|
| 92 | protected JButton zoomOutButton;
|
|---|
| 93 |
|
|---|
| 94 | private TileSource tileSource;
|
|---|
| 95 |
|
|---|
| 96 | // Attribution
|
|---|
| 97 | private Image attrImage;
|
|---|
| 98 | private String attrTermsUrl;
|
|---|
| 99 | public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
|
|---|
| 100 | public static final Font ATTR_LINK_FONT;
|
|---|
| 101 |
|
|---|
| 102 | protected Rectangle attrTextBounds = null;
|
|---|
| 103 | protected Rectangle attrToUBounds = null;
|
|---|
| 104 | protected Rectangle attrImageBounds = null;
|
|---|
| 105 |
|
|---|
| 106 | static {
|
|---|
| 107 | HashMap<TextAttribute, Integer> aUnderline = new HashMap<TextAttribute, Integer>();
|
|---|
| 108 | aUnderline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
|
|---|
| 109 | ATTR_LINK_FONT = ATTR_FONT.deriveFont(aUnderline);
|
|---|
| 110 | }
|
|---|
| 111 |
|
|---|
| 112 | /**
|
|---|
| 113 | * Creates a standard {@link JMapViewer} instance that can be controlled via
|
|---|
| 114 | * mouse: hold right mouse button for moving, double click left mouse button
|
|---|
| 115 | * or use mouse wheel for zooming. Loaded tiles are stored the
|
|---|
| 116 | * {@link MemoryTileCache} and the tile loader uses 4 parallel threads for
|
|---|
| 117 | * retrieving the tiles.
|
|---|
| 118 | */
|
|---|
| 119 | public JMapViewer() {
|
|---|
| 120 | this(new MemoryTileCache(), 4);
|
|---|
| 121 | new DefaultMapController(this);
|
|---|
| 122 | }
|
|---|
| 123 |
|
|---|
| 124 | public JMapViewer(TileCache tileCache, int downloadThreadCount) {
|
|---|
| 125 | super();
|
|---|
| 126 | tileSource = new OsmTileSource.Mapnik();
|
|---|
| 127 | tileController = new TileController(tileSource, tileCache, this);
|
|---|
| 128 | mapMarkerList = new LinkedList<MapMarker>();
|
|---|
| 129 | mapPolygonList = new LinkedList<MapPolygon>();
|
|---|
| 130 | mapObjectList = new LinkedList<MapObject>();
|
|---|
| 131 | mapRectangleList = new LinkedList<MapRectangle>();
|
|---|
| 132 | mapMarkersVisible = true;
|
|---|
| 133 | mapRectanglesVisible = true;
|
|---|
| 134 | mapPolygonsVisible = true;
|
|---|
| 135 | tileGridVisible = false;
|
|---|
| 136 | setLayout(null);
|
|---|
| 137 | initializeZoomSlider();
|
|---|
| 138 | setMinimumSize(new Dimension(tileSource.getTileSize(), tileSource.getTileSize()));
|
|---|
| 139 | setPreferredSize(new Dimension(400, 400));
|
|---|
| 140 | setDisplayPositionByLatLon(50, 9, 3);
|
|---|
| 141 | //setToolTipText("");
|
|---|
| 142 | }
|
|---|
| 143 |
|
|---|
| 144 | @Override
|
|---|
| 145 | public String getToolTipText(MouseEvent event) {
|
|---|
| 146 | // Point screenPoint = event.getLocationOnScreen();
|
|---|
| 147 | // Coordinate c = getPosition(screenPoint);
|
|---|
| 148 | return super.getToolTipText(event);
|
|---|
| 149 | }
|
|---|
| 150 |
|
|---|
| 151 | protected void initializeZoomSlider() {
|
|---|
| 152 | zoomSlider = new JSlider(MIN_ZOOM, tileController.getTileSource().getMaxZoom());
|
|---|
| 153 | zoomSlider.setOrientation(JSlider.VERTICAL);
|
|---|
| 154 | zoomSlider.setBounds(10, 10, 30, 150);
|
|---|
| 155 | zoomSlider.setOpaque(false);
|
|---|
| 156 | zoomSlider.addChangeListener(new ChangeListener() {
|
|---|
| 157 | public void stateChanged(ChangeEvent e) {
|
|---|
| 158 | setZoom(zoomSlider.getValue());
|
|---|
| 159 | }
|
|---|
| 160 | });
|
|---|
| 161 | add(zoomSlider);
|
|---|
| 162 | int size = 18;
|
|---|
| 163 | try {
|
|---|
| 164 | ImageIcon icon = new ImageIcon(getClass().getResource("images/plus.png"));
|
|---|
| 165 | zoomInButton = new JButton(icon);
|
|---|
| 166 | } catch (Exception e) {
|
|---|
| 167 | zoomInButton = new JButton("+");
|
|---|
| 168 | zoomInButton.setFont(new Font("sansserif", Font.BOLD, 9));
|
|---|
| 169 | zoomInButton.setMargin(new Insets(0, 0, 0, 0));
|
|---|
| 170 | }
|
|---|
| 171 | zoomInButton.setBounds(4, 155, size, size);
|
|---|
| 172 | zoomInButton.addActionListener(new ActionListener() {
|
|---|
| 173 |
|
|---|
| 174 | public void actionPerformed(ActionEvent e) {
|
|---|
| 175 | zoomIn();
|
|---|
| 176 | }
|
|---|
| 177 | });
|
|---|
| 178 | add(zoomInButton);
|
|---|
| 179 | try {
|
|---|
| 180 | ImageIcon icon = new ImageIcon(getClass().getResource("images/minus.png"));
|
|---|
| 181 | zoomOutButton = new JButton(icon);
|
|---|
| 182 | } catch (Exception e) {
|
|---|
| 183 | zoomOutButton = new JButton("-");
|
|---|
| 184 | zoomOutButton.setFont(new Font("sansserif", Font.BOLD, 9));
|
|---|
| 185 | zoomOutButton.setMargin(new Insets(0, 0, 0, 0));
|
|---|
| 186 | }
|
|---|
| 187 | zoomOutButton.setBounds(8 + size, 155, size, size);
|
|---|
| 188 | zoomOutButton.addActionListener(new ActionListener() {
|
|---|
| 189 |
|
|---|
| 190 | public void actionPerformed(ActionEvent e) {
|
|---|
| 191 | zoomOut();
|
|---|
| 192 | }
|
|---|
| 193 | });
|
|---|
| 194 | add(zoomOutButton);
|
|---|
| 195 | }
|
|---|
| 196 |
|
|---|
| 197 | /**
|
|---|
| 198 | * Changes the map pane so that it is centered on the specified coordinate
|
|---|
| 199 | * at the given zoom level.
|
|---|
| 200 | *
|
|---|
| 201 | * @param lat
|
|---|
| 202 | * latitude of the specified coordinate
|
|---|
| 203 | * @param lon
|
|---|
| 204 | * longitude of the specified coordinate
|
|---|
| 205 | * @param zoom
|
|---|
| 206 | * {@link #MIN_ZOOM} <= zoom level <= {@link #MAX_ZOOM}
|
|---|
| 207 | */
|
|---|
| 208 | public void setDisplayPositionByLatLon(double lat, double lon, int zoom) {
|
|---|
| 209 | setDisplayPositionByLatLon(new Point(getWidth() / 2, getHeight() / 2), lat, lon, zoom);
|
|---|
| 210 | }
|
|---|
| 211 |
|
|---|
| 212 | /**
|
|---|
| 213 | * Changes the map pane so that the specified coordinate at the given zoom
|
|---|
| 214 | * level is displayed on the map at the screen coordinate
|
|---|
| 215 | * <code>mapPoint</code>.
|
|---|
| 216 | *
|
|---|
| 217 | * @param mapPoint
|
|---|
| 218 | * point on the map denoted in pixels where the coordinate should
|
|---|
| 219 | * be set
|
|---|
| 220 | * @param lat
|
|---|
| 221 | * latitude of the specified coordinate
|
|---|
| 222 | * @param lon
|
|---|
| 223 | * longitude of the specified coordinate
|
|---|
| 224 | * @param zoom
|
|---|
| 225 | * {@link #MIN_ZOOM} <= zoom level <=
|
|---|
| 226 | * {@link TileSource#getMaxZoom()}
|
|---|
| 227 | */
|
|---|
| 228 | public void setDisplayPositionByLatLon(Point mapPoint, double lat, double lon, int zoom) {
|
|---|
| 229 | int x = OsmMercator.LonToX(lon, zoom);
|
|---|
| 230 | int y = OsmMercator.LatToY(lat, zoom);
|
|---|
| 231 | setDisplayPosition(mapPoint, x, y, zoom);
|
|---|
| 232 | }
|
|---|
| 233 |
|
|---|
| 234 | public void setDisplayPosition(int x, int y, int zoom) {
|
|---|
| 235 | setDisplayPosition(new Point(getWidth() / 2, getHeight() / 2), x, y, zoom);
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | public void setDisplayPosition(Point mapPoint, int x, int y, int zoom) {
|
|---|
| 239 | if (zoom > tileController.getTileSource().getMaxZoom() || zoom < MIN_ZOOM)
|
|---|
| 240 | return;
|
|---|
| 241 |
|
|---|
| 242 | // Get the plain tile number
|
|---|
| 243 | Point p = new Point();
|
|---|
| 244 | p.x = x - mapPoint.x + getWidth() / 2;
|
|---|
| 245 | p.y = y - mapPoint.y + getHeight() / 2;
|
|---|
| 246 | center = p;
|
|---|
| 247 | setIgnoreRepaint(true);
|
|---|
| 248 | try {
|
|---|
| 249 | int oldZoom = this.zoom;
|
|---|
| 250 | this.zoom = zoom;
|
|---|
| 251 | if (oldZoom != zoom) {
|
|---|
| 252 | zoomChanged(oldZoom);
|
|---|
| 253 | }
|
|---|
| 254 | if (zoomSlider.getValue() != zoom) {
|
|---|
| 255 | zoomSlider.setValue(zoom);
|
|---|
| 256 | }
|
|---|
| 257 | } finally {
|
|---|
| 258 | setIgnoreRepaint(false);
|
|---|
| 259 | repaint();
|
|---|
| 260 | }
|
|---|
| 261 | }
|
|---|
| 262 |
|
|---|
| 263 | /**
|
|---|
| 264 | * Sets the displayed map pane and zoom level so that all map markers are
|
|---|
| 265 | * visible.
|
|---|
| 266 | */
|
|---|
| 267 | public void setDisplayToFitMapElements(boolean markers, boolean rectangles, boolean polygons) {
|
|---|
| 268 | int nbElemToCheck = 0;
|
|---|
| 269 | if (markers && mapMarkerList != null)
|
|---|
| 270 | nbElemToCheck += mapMarkerList.size();
|
|---|
| 271 | if (rectangles && mapRectangleList != null)
|
|---|
| 272 | nbElemToCheck += mapRectangleList.size();
|
|---|
| 273 | if (polygons && mapPolygonList != null)
|
|---|
| 274 | nbElemToCheck += mapPolygonList.size();
|
|---|
| 275 | if (nbElemToCheck == 0)
|
|---|
| 276 | return;
|
|---|
| 277 |
|
|---|
| 278 | int x_min = Integer.MAX_VALUE;
|
|---|
| 279 | int y_min = Integer.MAX_VALUE;
|
|---|
| 280 | int x_max = Integer.MIN_VALUE;
|
|---|
| 281 | int y_max = Integer.MIN_VALUE;
|
|---|
| 282 | int mapZoomMax = tileController.getTileSource().getMaxZoom();
|
|---|
| 283 |
|
|---|
| 284 | if (markers) {
|
|---|
| 285 | for (MapMarker marker : mapMarkerList) {
|
|---|
| 286 | int x = OsmMercator.LonToX(marker.getLon(), mapZoomMax);
|
|---|
| 287 | int y = OsmMercator.LatToY(marker.getLat(), mapZoomMax);
|
|---|
| 288 | x_max = Math.max(x_max, x);
|
|---|
| 289 | y_max = Math.max(y_max, y);
|
|---|
| 290 | x_min = Math.min(x_min, x);
|
|---|
| 291 | y_min = Math.min(y_min, y);
|
|---|
| 292 | }
|
|---|
| 293 | }
|
|---|
| 294 |
|
|---|
| 295 | if (polygons) {
|
|---|
| 296 | for (MapPolygon polygon : mapPolygonList) {
|
|---|
| 297 | for (Coordinate c : polygon.getPoints()) {
|
|---|
| 298 | int x = OsmMercator.LonToX(c.getLon(), mapZoomMax);
|
|---|
| 299 | int y = OsmMercator.LatToY(c.getLat(), mapZoomMax);
|
|---|
| 300 | x_max = Math.max(x_max, x);
|
|---|
| 301 | y_max = Math.max(y_max, y);
|
|---|
| 302 | x_min = Math.min(x_min, x);
|
|---|
| 303 | y_min = Math.min(y_min, y);
|
|---|
| 304 | }
|
|---|
| 305 | }
|
|---|
| 306 | }
|
|---|
| 307 |
|
|---|
| 308 | int height = Math.max(0, getHeight());
|
|---|
| 309 | int width = Math.max(0, getWidth());
|
|---|
| 310 | int newZoom = mapZoomMax;
|
|---|
| 311 | int x = x_max - x_min;
|
|---|
| 312 | int y = y_max - y_min;
|
|---|
| 313 | while (x > width || y > height) {
|
|---|
| 314 | newZoom--;
|
|---|
| 315 | x >>= 1;
|
|---|
| 316 | y >>= 1;
|
|---|
| 317 | }
|
|---|
| 318 | x = x_min + (x_max - x_min) / 2;
|
|---|
| 319 | y = y_min + (y_max - y_min) / 2;
|
|---|
| 320 | int z = 1 << (mapZoomMax - newZoom);
|
|---|
| 321 | x /= z;
|
|---|
| 322 | y /= z;
|
|---|
| 323 | setDisplayPosition(x, y, newZoom);
|
|---|
| 324 | }
|
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 | /**
|
|---|
| 328 | * Sets the displayed map pane and zoom level so that all map markers are
|
|---|
| 329 | * visible.
|
|---|
| 330 | */
|
|---|
| 331 | public void setDisplayToFitMapMarkers() {
|
|---|
| 332 | setDisplayToFitMapElements(true, false, false);
|
|---|
| 333 | }
|
|---|
| 334 |
|
|---|
| 335 | /**
|
|---|
| 336 | * Sets the displayed map pane and zoom level so that all map rectangles are
|
|---|
| 337 | * visible.
|
|---|
| 338 | */
|
|---|
| 339 | public void setDisplayToFitMapRectangles() {
|
|---|
| 340 | setDisplayToFitMapElements(false, true, false);
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | /**
|
|---|
| 344 | * Sets the displayed map pane and zoom level so that all map polygons are
|
|---|
| 345 | * visible.
|
|---|
| 346 | */
|
|---|
| 347 | public void setDisplayToFitMapPolygons() {
|
|---|
| 348 | setDisplayToFitMapElements(false, false, true);
|
|---|
| 349 | }
|
|---|
| 350 |
|
|---|
| 351 | /**
|
|---|
| 352 | * @return the center
|
|---|
| 353 | */
|
|---|
| 354 | public Point getCenter() {
|
|---|
| 355 | return center;
|
|---|
| 356 | }
|
|---|
| 357 |
|
|---|
| 358 | /**
|
|---|
| 359 | * @param center the center to set
|
|---|
| 360 | */
|
|---|
| 361 | public void setCenter(Point center) {
|
|---|
| 362 | this.center = center;
|
|---|
| 363 | }
|
|---|
| 364 |
|
|---|
| 365 | /**
|
|---|
| 366 | * Calculates the latitude/longitude coordinate of the center of the
|
|---|
| 367 | * currently displayed map area.
|
|---|
| 368 | *
|
|---|
| 369 | * @return latitude / longitude
|
|---|
| 370 | */
|
|---|
| 371 | public Coordinate getPosition() {
|
|---|
| 372 | double lon = OsmMercator.XToLon(center.x, zoom);
|
|---|
| 373 | double lat = OsmMercator.YToLat(center.y, zoom);
|
|---|
| 374 | return new Coordinate(lat, lon);
|
|---|
| 375 | }
|
|---|
| 376 |
|
|---|
| 377 | /**
|
|---|
| 378 | * Converts the relative pixel coordinate (regarding the top left corner of
|
|---|
| 379 | * the displayed map) into a latitude / longitude coordinate
|
|---|
| 380 | *
|
|---|
| 381 | * @param mapPoint
|
|---|
| 382 | * relative pixel coordinate regarding the top left corner of the
|
|---|
| 383 | * displayed map
|
|---|
| 384 | * @return latitude / longitude
|
|---|
| 385 | */
|
|---|
| 386 | public Coordinate getPosition(Point mapPoint) {
|
|---|
| 387 | return getPosition(mapPoint.x, mapPoint.y);
|
|---|
| 388 | }
|
|---|
| 389 |
|
|---|
| 390 | /**
|
|---|
| 391 | * Converts the relative pixel coordinate (regarding the top left corner of
|
|---|
| 392 | * the displayed map) into a latitude / longitude coordinate
|
|---|
| 393 | *
|
|---|
| 394 | * @param mapPointX
|
|---|
| 395 | * @param mapPointY
|
|---|
| 396 | * @return
|
|---|
| 397 | */
|
|---|
| 398 | public Coordinate getPosition(int mapPointX, int mapPointY) {
|
|---|
| 399 | int x = center.x + mapPointX - getWidth() / 2;
|
|---|
| 400 | int y = center.y + mapPointY - getHeight() / 2;
|
|---|
| 401 | double lon = OsmMercator.XToLon(x, zoom);
|
|---|
| 402 | double lat = OsmMercator.YToLat(y, zoom);
|
|---|
| 403 | return new Coordinate(lat, lon);
|
|---|
| 404 | }
|
|---|
| 405 |
|
|---|
| 406 | /**
|
|---|
| 407 | * Calculates the position on the map of a given coordinate
|
|---|
| 408 | *
|
|---|
| 409 | * @param lat
|
|---|
| 410 | * @param lon
|
|---|
| 411 | * @param checkOutside
|
|---|
| 412 | * @return point on the map or <code>null</code> if the point is not visible
|
|---|
| 413 | * and checkOutside set to <code>true</code>
|
|---|
| 414 | */
|
|---|
| 415 | public Point getMapPosition(double lat, double lon, boolean checkOutside) {
|
|---|
| 416 | int x = OsmMercator.LonToX(lon, zoom);
|
|---|
| 417 | int y = OsmMercator.LatToY(lat, zoom);
|
|---|
| 418 | x -= center.x - getWidth() / 2;
|
|---|
| 419 | y -= center.y - getHeight() / 2;
|
|---|
| 420 | if (checkOutside) {
|
|---|
| 421 | if (x < 0 || y < 0 || x > getWidth() || y > getHeight())
|
|---|
| 422 | return null;
|
|---|
| 423 | }
|
|---|
| 424 | return new Point(x, y);
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | /**
|
|---|
| 428 | * Calculates the position on the map of a given coordinate
|
|---|
| 429 | *
|
|---|
| 430 | * @param lat
|
|---|
| 431 | * @param lon
|
|---|
| 432 | * @return point on the map or <code>null</code> if the point is not visible
|
|---|
| 433 | */
|
|---|
| 434 | public Point getMapPosition(double lat, double lon) {
|
|---|
| 435 | return getMapPosition(lat, lon, true);
|
|---|
| 436 | }
|
|---|
| 437 |
|
|---|
| 438 | /**
|
|---|
| 439 | * Calculates the position on the map of a given coordinate
|
|---|
| 440 | *
|
|---|
| 441 | * @param coord
|
|---|
| 442 | * @return point on the map or <code>null</code> if the point is not visible
|
|---|
| 443 | */
|
|---|
| 444 | public Point getMapPosition(Coordinate coord) {
|
|---|
| 445 | if (coord != null)
|
|---|
| 446 | return getMapPosition(coord.getLat(), coord.getLon());
|
|---|
| 447 | else
|
|---|
| 448 | return null;
|
|---|
| 449 | }
|
|---|
| 450 |
|
|---|
| 451 | /**
|
|---|
| 452 | * Calculates the position on the map of a given coordinate
|
|---|
| 453 | *
|
|---|
| 454 | * @param coord
|
|---|
| 455 | * @return point on the map or <code>null</code> if the point is not visible
|
|---|
| 456 | * and checkOutside set to <code>true</code>
|
|---|
| 457 | */
|
|---|
| 458 | public Point getMapPosition(Coordinate coord, boolean checkOutside) {
|
|---|
| 459 | if (coord != null)
|
|---|
| 460 | return getMapPosition(coord.getLat(), coord.getLon(), checkOutside);
|
|---|
| 461 | else
|
|---|
| 462 | return null;
|
|---|
| 463 | }
|
|---|
| 464 |
|
|---|
| 465 | /**
|
|---|
| 466 | * Gets the meter per pixel.
|
|---|
| 467 | *
|
|---|
| 468 | * @return the meter per pixel
|
|---|
| 469 | * @author Jason Huntley
|
|---|
| 470 | */
|
|---|
| 471 | public double getMeterPerPixel() {
|
|---|
| 472 | Point origin=new Point(5,5);
|
|---|
| 473 | Point center=new Point(getWidth()/2, getHeight()/2);
|
|---|
| 474 |
|
|---|
| 475 | double pDistance=center.distance(origin);
|
|---|
| 476 |
|
|---|
| 477 | Coordinate originCoord=getPosition(origin);
|
|---|
| 478 | Coordinate centerCoord=getPosition(center);
|
|---|
| 479 |
|
|---|
| 480 | double kmDistance=OsmMercator.getDistance(originCoord.getLat(), originCoord.getLon(),
|
|---|
| 481 | centerCoord.getLat(), centerCoord.getLon());
|
|---|
| 482 |
|
|---|
| 483 | double mDistance=OsmMercator.kmToMeters(kmDistance);
|
|---|
| 484 |
|
|---|
| 485 | return mDistance/pDistance;
|
|---|
| 486 | }
|
|---|
| 487 |
|
|---|
| 488 | @Override
|
|---|
| 489 | protected void paintComponent(Graphics g) {
|
|---|
| 490 | super.paintComponent(g);
|
|---|
| 491 |
|
|---|
| 492 | int iMove = 0;
|
|---|
| 493 |
|
|---|
| 494 | int tilesize = tileSource.getTileSize();
|
|---|
| 495 | int tilex = center.x / tilesize;
|
|---|
| 496 | int tiley = center.y / tilesize;
|
|---|
| 497 | int off_x = (center.x % tilesize);
|
|---|
| 498 | int off_y = (center.y % tilesize);
|
|---|
| 499 |
|
|---|
| 500 | int w2 = getWidth() / 2;
|
|---|
| 501 | int h2 = getHeight() / 2;
|
|---|
| 502 | int posx = w2 - off_x;
|
|---|
| 503 | int posy = h2 - off_y;
|
|---|
| 504 |
|
|---|
| 505 | int diff_left = off_x;
|
|---|
| 506 | int diff_right = tilesize - off_x;
|
|---|
| 507 | int diff_top = off_y;
|
|---|
| 508 | int diff_bottom = tilesize - off_y;
|
|---|
| 509 |
|
|---|
| 510 | boolean start_left = diff_left < diff_right;
|
|---|
| 511 | boolean start_top = diff_top < diff_bottom;
|
|---|
| 512 |
|
|---|
| 513 | if (start_top) {
|
|---|
| 514 | if (start_left) {
|
|---|
| 515 | iMove = 2;
|
|---|
| 516 | } else {
|
|---|
| 517 | iMove = 3;
|
|---|
| 518 | }
|
|---|
| 519 | } else {
|
|---|
| 520 | if (start_left) {
|
|---|
| 521 | iMove = 1;
|
|---|
| 522 | } else {
|
|---|
| 523 | iMove = 0;
|
|---|
| 524 | }
|
|---|
| 525 | } // calculate the visibility borders
|
|---|
| 526 | int x_min = -tilesize;
|
|---|
| 527 | int y_min = -tilesize;
|
|---|
| 528 | int x_max = getWidth();
|
|---|
| 529 | int y_max = getHeight();
|
|---|
| 530 |
|
|---|
| 531 | // paint the tiles in a spiral, starting from center of the map
|
|---|
| 532 | boolean painted = true;
|
|---|
| 533 | int x = 0;
|
|---|
| 534 | while (painted) {
|
|---|
| 535 | painted = false;
|
|---|
| 536 | for (int i = 0; i < 4; i++) {
|
|---|
| 537 | if (i % 2 == 0) {
|
|---|
| 538 | x++;
|
|---|
| 539 | }
|
|---|
| 540 | for (int j = 0; j < x; j++) {
|
|---|
| 541 | if (x_min <= posx && posx <= x_max && y_min <= posy && posy <= y_max) {
|
|---|
| 542 | // tile is visible
|
|---|
| 543 | Tile tile = tileController.getTile(tilex, tiley, zoom);
|
|---|
| 544 | if (tile != null) {
|
|---|
| 545 | painted = true;
|
|---|
| 546 | tile.paint(g, posx, posy);
|
|---|
| 547 | if (tileGridVisible) {
|
|---|
| 548 | g.drawRect(posx, posy, tilesize, tilesize);
|
|---|
| 549 | }
|
|---|
| 550 | }
|
|---|
| 551 | }
|
|---|
| 552 | Point p = move[iMove];
|
|---|
| 553 | posx += p.x * tilesize;
|
|---|
| 554 | posy += p.y * tilesize;
|
|---|
| 555 | tilex += p.x;
|
|---|
| 556 | tiley += p.y;
|
|---|
| 557 | }
|
|---|
| 558 | iMove = (iMove + 1) % move.length;
|
|---|
| 559 | }
|
|---|
| 560 | }
|
|---|
| 561 | // outer border of the map
|
|---|
| 562 | int mapSize = tilesize << zoom;
|
|---|
| 563 | g.drawRect(w2 - center.x, h2 - center.y, mapSize, mapSize);
|
|---|
| 564 |
|
|---|
| 565 | // g.drawString("Tiles in cache: " + tileCache.getTileCount(), 50, 20);
|
|---|
| 566 |
|
|---|
| 567 | if (mapPolygonsVisible && mapPolygonList != null) {
|
|---|
| 568 | for (MapPolygon polygon : mapPolygonList) {
|
|---|
| 569 | paintPolygon(g, polygon);
|
|---|
| 570 | }
|
|---|
| 571 | }
|
|---|
| 572 |
|
|---|
| 573 | if (mapRectanglesVisible && mapRectangleList != null) {
|
|---|
| 574 | for (MapRectangle rectangle : mapRectangleList) {
|
|---|
| 575 | paintRectangle(g, rectangle);
|
|---|
| 576 | }
|
|---|
| 577 | }
|
|---|
| 578 |
|
|---|
| 579 | if (mapObjectList != null) {
|
|---|
| 580 | for (MapObject obj : mapObjectList) {
|
|---|
| 581 | paintObject(g, obj);
|
|---|
| 582 | }
|
|---|
| 583 | }
|
|---|
| 584 |
|
|---|
| 585 | if (mapMarkersVisible && mapMarkerList != null) {
|
|---|
| 586 | for (MapMarker marker : mapMarkerList) {
|
|---|
| 587 | paintMarker(g, marker);
|
|---|
| 588 | }
|
|---|
| 589 | }
|
|---|
| 590 |
|
|---|
| 591 | paintAttribution(g);
|
|---|
| 592 | }
|
|---|
| 593 |
|
|---|
| 594 | /**
|
|---|
| 595 | * Paint a single object.
|
|---|
| 596 | */
|
|---|
| 597 | protected void paintObject(Graphics g, MapObject obj) {
|
|---|
| 598 | Point p = getMapPosition(obj.getLat(), obj.getLon(),false);
|
|---|
| 599 | if (p != null) {
|
|---|
| 600 | obj.paint(g, p, this);
|
|---|
| 601 | }
|
|---|
| 602 | }
|
|---|
| 603 |
|
|---|
| 604 | /**
|
|---|
| 605 | * Paint a single marker.
|
|---|
| 606 | */
|
|---|
| 607 | protected void paintMarker(Graphics g, MapMarker marker) {
|
|---|
| 608 | Point p = getMapPosition(marker.getLat(), marker.getLon());
|
|---|
| 609 | if (p != null) {
|
|---|
| 610 | marker.paint(g, p);
|
|---|
| 611 | }
|
|---|
| 612 | }
|
|---|
| 613 |
|
|---|
| 614 | /**
|
|---|
| 615 | * Paint a single rectangle.
|
|---|
| 616 | */
|
|---|
| 617 | protected void paintRectangle(Graphics g, MapRectangle rectangle) {
|
|---|
| 618 | Coordinate topLeft = rectangle.getTopLeft();
|
|---|
| 619 | Coordinate bottomRight = rectangle.getBottomRight();
|
|---|
| 620 | if (topLeft != null && bottomRight != null) {
|
|---|
| 621 | Point pTopLeft = getMapPosition(topLeft, false);
|
|---|
| 622 | Point pBottomRight = getMapPosition(bottomRight, false);
|
|---|
| 623 | if (pTopLeft != null && pBottomRight != null) {
|
|---|
| 624 | rectangle.paint(g, pTopLeft, pBottomRight);
|
|---|
| 625 | }
|
|---|
| 626 | }
|
|---|
| 627 | }
|
|---|
| 628 |
|
|---|
| 629 | /**
|
|---|
| 630 | * Paint a single polygon.
|
|---|
| 631 | */
|
|---|
| 632 | protected void paintPolygon(Graphics g, MapPolygon polygon) {
|
|---|
| 633 | List<Coordinate> coords = polygon.getPoints();
|
|---|
| 634 | if (coords != null && coords.size() >= 3) {
|
|---|
| 635 | List<Point> points = new LinkedList<Point>();
|
|---|
| 636 | for (Coordinate c : coords) {
|
|---|
| 637 | Point p = getMapPosition(c, false);
|
|---|
| 638 | if (p == null) {
|
|---|
| 639 | return;
|
|---|
| 640 | }
|
|---|
| 641 | points.add(p);
|
|---|
| 642 | }
|
|---|
| 643 | polygon.paint(g, points);
|
|---|
| 644 | }
|
|---|
| 645 | }
|
|---|
| 646 |
|
|---|
| 647 | /**
|
|---|
| 648 | * Moves the visible map pane.
|
|---|
| 649 | *
|
|---|
| 650 | * @param x
|
|---|
| 651 | * horizontal movement in pixel.
|
|---|
| 652 | * @param y
|
|---|
| 653 | * vertical movement in pixel
|
|---|
| 654 | */
|
|---|
| 655 | public void moveMap(int x, int y) {
|
|---|
| 656 | center.x += x;
|
|---|
| 657 | center.y += y;
|
|---|
| 658 | repaint();
|
|---|
| 659 | }
|
|---|
| 660 |
|
|---|
| 661 | /**
|
|---|
| 662 | * @return the current zoom level
|
|---|
| 663 | */
|
|---|
| 664 | public int getZoom() {
|
|---|
| 665 | return zoom;
|
|---|
| 666 | }
|
|---|
| 667 |
|
|---|
| 668 | /**
|
|---|
| 669 | * Increases the current zoom level by one
|
|---|
| 670 | */
|
|---|
| 671 | public void zoomIn() {
|
|---|
| 672 | setZoom(zoom + 1);
|
|---|
| 673 | }
|
|---|
| 674 |
|
|---|
| 675 | /**
|
|---|
| 676 | * Increases the current zoom level by one
|
|---|
| 677 | */
|
|---|
| 678 | public void zoomIn(Point mapPoint) {
|
|---|
| 679 | setZoom(zoom + 1, mapPoint);
|
|---|
| 680 | }
|
|---|
| 681 |
|
|---|
| 682 | /**
|
|---|
| 683 | * Decreases the current zoom level by one
|
|---|
| 684 | */
|
|---|
| 685 | public void zoomOut() {
|
|---|
| 686 | setZoom(zoom - 1);
|
|---|
| 687 | }
|
|---|
| 688 |
|
|---|
| 689 | /**
|
|---|
| 690 | * Decreases the current zoom level by one
|
|---|
| 691 | */
|
|---|
| 692 | public void zoomOut(Point mapPoint) {
|
|---|
| 693 | setZoom(zoom - 1, mapPoint);
|
|---|
| 694 | }
|
|---|
| 695 |
|
|---|
| 696 | public void setZoom(int zoom, Point mapPoint) {
|
|---|
| 697 | if (zoom > tileController.getTileSource().getMaxZoom() || zoom < tileController.getTileSource().getMinZoom()
|
|---|
| 698 | || zoom == this.zoom)
|
|---|
| 699 | return;
|
|---|
| 700 | Coordinate zoomPos = getPosition(mapPoint);
|
|---|
| 701 | tileController.cancelOutstandingJobs(); // Clearing outstanding load
|
|---|
| 702 | // requests
|
|---|
| 703 | setDisplayPositionByLatLon(mapPoint, zoomPos.getLat(), zoomPos.getLon(), zoom);
|
|---|
| 704 |
|
|---|
| 705 | this.fireJMVEvent(new JMVCommandEvent(COMMAND.ZOOM, this));
|
|---|
| 706 | }
|
|---|
| 707 |
|
|---|
| 708 | public void setZoom(int zoom) {
|
|---|
| 709 | setZoom(zoom, new Point(getWidth() / 2, getHeight() / 2));
|
|---|
| 710 | }
|
|---|
| 711 |
|
|---|
| 712 | /**
|
|---|
| 713 | * Every time the zoom level changes this method is called. Override it in
|
|---|
| 714 | * derived implementations for adapting zoom dependent values. The new zoom
|
|---|
| 715 | * level can be obtained via {@link #getZoom()}.
|
|---|
| 716 | *
|
|---|
| 717 | * @param oldZoom
|
|---|
| 718 | * the previous zoom level
|
|---|
| 719 | */
|
|---|
| 720 | protected void zoomChanged(int oldZoom) {
|
|---|
| 721 | zoomSlider.setToolTipText("Zoom level " + zoom);
|
|---|
| 722 | zoomInButton.setToolTipText("Zoom to level " + (zoom + 1));
|
|---|
| 723 | zoomOutButton.setToolTipText("Zoom to level " + (zoom - 1));
|
|---|
| 724 | zoomOutButton.setEnabled(zoom > tileController.getTileSource().getMinZoom());
|
|---|
| 725 | zoomInButton.setEnabled(zoom < tileController.getTileSource().getMaxZoom());
|
|---|
| 726 | }
|
|---|
| 727 |
|
|---|
| 728 | public boolean isTileGridVisible() {
|
|---|
| 729 | return tileGridVisible;
|
|---|
| 730 | }
|
|---|
| 731 |
|
|---|
| 732 | public void setTileGridVisible(boolean tileGridVisible) {
|
|---|
| 733 | this.tileGridVisible = tileGridVisible;
|
|---|
| 734 | repaint();
|
|---|
| 735 | }
|
|---|
| 736 |
|
|---|
| 737 | public boolean getMapMarkersVisible() {
|
|---|
| 738 | return mapMarkersVisible;
|
|---|
| 739 | }
|
|---|
| 740 |
|
|---|
| 741 | /**
|
|---|
| 742 | * Enables or disables painting of the {@link MapMarker}
|
|---|
| 743 | *
|
|---|
| 744 | * @param mapMarkersVisible
|
|---|
| 745 | * @see #addMapMarker(MapMarker)
|
|---|
| 746 | * @see #getMapMarkerList()
|
|---|
| 747 | */
|
|---|
| 748 | public void setMapMarkerVisible(boolean mapMarkersVisible) {
|
|---|
| 749 | this.mapMarkersVisible = mapMarkersVisible;
|
|---|
| 750 | repaint();
|
|---|
| 751 | }
|
|---|
| 752 |
|
|---|
| 753 | public void setMapMarkerList(List<MapMarker> mapMarkerList) {
|
|---|
| 754 | this.mapMarkerList = mapMarkerList;
|
|---|
| 755 | repaint();
|
|---|
| 756 | }
|
|---|
| 757 |
|
|---|
| 758 | public List<MapMarker> getMapMarkerList() {
|
|---|
| 759 | return mapMarkerList;
|
|---|
| 760 | }
|
|---|
| 761 |
|
|---|
| 762 | public void setMapRectangleList(List<MapRectangle> mapRectangleList) {
|
|---|
| 763 | this.mapRectangleList = mapRectangleList;
|
|---|
| 764 | repaint();
|
|---|
| 765 | }
|
|---|
| 766 |
|
|---|
| 767 | public List<MapRectangle> getMapRectangleList() {
|
|---|
| 768 | return mapRectangleList;
|
|---|
| 769 | }
|
|---|
| 770 |
|
|---|
| 771 | public void setMapPolygonList(List<MapPolygon> mapPolygonList) {
|
|---|
| 772 | this.mapPolygonList = mapPolygonList;
|
|---|
| 773 | repaint();
|
|---|
| 774 | }
|
|---|
| 775 |
|
|---|
| 776 | public List<MapPolygon> getMapPolygonList() {
|
|---|
| 777 | return mapPolygonList;
|
|---|
| 778 | }
|
|---|
| 779 |
|
|---|
| 780 |
|
|---|
| 781 | public void addMapObject(MapObject obj) {
|
|---|
| 782 | mapObjectList.add(obj);
|
|---|
| 783 | repaint();
|
|---|
| 784 | }
|
|---|
| 785 |
|
|---|
| 786 | public void removeMapObject(MapObject obj) {
|
|---|
| 787 | mapMarkerList.remove(obj);
|
|---|
| 788 | repaint();
|
|---|
| 789 | }
|
|---|
| 790 |
|
|---|
| 791 | public void addMapMarker(MapMarker marker) {
|
|---|
| 792 | mapMarkerList.add(marker);
|
|---|
| 793 | repaint();
|
|---|
| 794 | }
|
|---|
| 795 |
|
|---|
| 796 | public void removeMapMarker(MapMarker marker) {
|
|---|
| 797 | mapMarkerList.remove(marker);
|
|---|
| 798 | repaint();
|
|---|
| 799 | }
|
|---|
| 800 |
|
|---|
| 801 | public void removeAllMapMarkers() {
|
|---|
| 802 | mapMarkerList.clear();
|
|---|
| 803 | repaint();
|
|---|
| 804 | }
|
|---|
| 805 |
|
|---|
| 806 | public void addMapRectangle(MapRectangle rectangle) {
|
|---|
| 807 | mapRectangleList.add(rectangle);
|
|---|
| 808 | repaint();
|
|---|
| 809 | }
|
|---|
| 810 |
|
|---|
| 811 | public void removeMapRectangle(MapRectangle rectangle) {
|
|---|
| 812 | mapRectangleList.remove(rectangle);
|
|---|
| 813 | repaint();
|
|---|
| 814 | }
|
|---|
| 815 |
|
|---|
| 816 | public void removeAllMapRectangles() {
|
|---|
| 817 | mapRectangleList.clear();
|
|---|
| 818 | repaint();
|
|---|
| 819 | }
|
|---|
| 820 |
|
|---|
| 821 | public void addMapPolygon(MapPolygon polygon) {
|
|---|
| 822 | mapPolygonList.add(polygon);
|
|---|
| 823 | repaint();
|
|---|
| 824 | }
|
|---|
| 825 |
|
|---|
| 826 | public void removeMapPolygon(MapPolygon polygon) {
|
|---|
| 827 | mapPolygonList.remove(polygon);
|
|---|
| 828 | repaint();
|
|---|
| 829 | }
|
|---|
| 830 |
|
|---|
| 831 | public void removeAllMapPolygons() {
|
|---|
| 832 | mapPolygonList.clear();
|
|---|
| 833 | repaint();
|
|---|
| 834 | }
|
|---|
| 835 |
|
|---|
| 836 | public void setZoomContolsVisible(boolean visible) {
|
|---|
| 837 | zoomSlider.setVisible(visible);
|
|---|
| 838 | zoomInButton.setVisible(visible);
|
|---|
| 839 | zoomOutButton.setVisible(visible);
|
|---|
| 840 | }
|
|---|
| 841 |
|
|---|
| 842 | public boolean getZoomContolsVisible() {
|
|---|
| 843 | return zoomSlider.isVisible();
|
|---|
| 844 | }
|
|---|
| 845 |
|
|---|
| 846 | public TileSource getTileSource() {
|
|---|
| 847 | return tileSource;
|
|---|
| 848 | }
|
|---|
| 849 |
|
|---|
| 850 | public void setTileSource(TileSource tileSource) {
|
|---|
| 851 | if (tileSource.getMaxZoom() > MAX_ZOOM)
|
|---|
| 852 | throw new RuntimeException("Maximum zoom level too high");
|
|---|
| 853 | if (tileSource.getMinZoom() < MIN_ZOOM)
|
|---|
| 854 | throw new RuntimeException("Minumim zoom level too low");
|
|---|
| 855 | this.tileSource = tileSource;
|
|---|
| 856 | tileController.setTileSource(tileSource);
|
|---|
| 857 | zoomSlider.setMinimum(tileSource.getMinZoom());
|
|---|
| 858 | zoomSlider.setMaximum(tileSource.getMaxZoom());
|
|---|
| 859 | tileController.cancelOutstandingJobs();
|
|---|
| 860 | if (zoom > tileSource.getMaxZoom()) {
|
|---|
| 861 | setZoom(tileSource.getMaxZoom());
|
|---|
| 862 | }
|
|---|
| 863 | boolean requireAttr = tileSource.requiresAttribution();
|
|---|
| 864 | if (requireAttr) {
|
|---|
| 865 | attrImage = tileSource.getAttributionImage();
|
|---|
| 866 | attrTermsUrl = tileSource.getTermsOfUseURL();
|
|---|
| 867 | } else {
|
|---|
| 868 | attrImage = null;
|
|---|
| 869 | attrTermsUrl = null;
|
|---|
| 870 | }
|
|---|
| 871 | repaint();
|
|---|
| 872 | }
|
|---|
| 873 |
|
|---|
| 874 | public void tileLoadingFinished(Tile tile, boolean success) {
|
|---|
| 875 | repaint();
|
|---|
| 876 | }
|
|---|
| 877 |
|
|---|
| 878 | public boolean isMapRectanglesVisible() {
|
|---|
| 879 | return mapRectanglesVisible;
|
|---|
| 880 | }
|
|---|
| 881 |
|
|---|
| 882 | /**
|
|---|
| 883 | * Enables or disables painting of the {@link MapRectangle}
|
|---|
| 884 | *
|
|---|
| 885 | * @param mapRectanglesVisible
|
|---|
| 886 | * @see #addMapRectangle(MapRectangle)
|
|---|
| 887 | * @see #getMapRectangleList()
|
|---|
| 888 | */
|
|---|
| 889 | public void setMapRectanglesVisible(boolean mapRectanglesVisible) {
|
|---|
| 890 | this.mapRectanglesVisible = mapRectanglesVisible;
|
|---|
| 891 | repaint();
|
|---|
| 892 | }
|
|---|
| 893 |
|
|---|
| 894 | public boolean isMapPolygonsVisible() {
|
|---|
| 895 | return mapPolygonsVisible;
|
|---|
| 896 | }
|
|---|
| 897 |
|
|---|
| 898 | /**
|
|---|
| 899 | * Enables or disables painting of the {@link MapPolygon}
|
|---|
| 900 | *
|
|---|
| 901 | * @param mapPolygonsVisible
|
|---|
| 902 | * @see #addMapPolygon(MapPolygon)
|
|---|
| 903 | * @see #getMapPolygonList()
|
|---|
| 904 | */
|
|---|
| 905 | public void setMapPolygonsVisible(boolean mapPolygonsVisible) {
|
|---|
| 906 | this.mapPolygonsVisible = mapPolygonsVisible;
|
|---|
| 907 | repaint();
|
|---|
| 908 | }
|
|---|
| 909 |
|
|---|
| 910 | /*
|
|---|
| 911 | * (non-Javadoc)
|
|---|
| 912 | *
|
|---|
| 913 | * @see
|
|---|
| 914 | * org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener#getTileCache
|
|---|
| 915 | * ()
|
|---|
| 916 | */
|
|---|
| 917 | public TileCache getTileCache() {
|
|---|
| 918 | return tileController.getTileCache();
|
|---|
| 919 | }
|
|---|
| 920 |
|
|---|
| 921 | public void setTileLoader(TileLoader loader) {
|
|---|
| 922 | tileController.setTileLoader(loader);
|
|---|
| 923 | }
|
|---|
| 924 |
|
|---|
| 925 | private void paintAttribution(Graphics g) {
|
|---|
| 926 | if (!tileSource.requiresAttribution())
|
|---|
| 927 | return;
|
|---|
| 928 | // Draw attribution
|
|---|
| 929 | Font font = g.getFont();
|
|---|
| 930 | g.setFont(ATTR_LINK_FONT);
|
|---|
| 931 |
|
|---|
| 932 | Rectangle2D termsStringBounds = g.getFontMetrics().getStringBounds("Background Terms of Use", g);
|
|---|
| 933 | int textRealHeight = (int) termsStringBounds.getHeight();
|
|---|
| 934 | int textHeight = textRealHeight - 5;
|
|---|
| 935 | int textWidth = (int) termsStringBounds.getWidth();
|
|---|
| 936 | int termsTextY = getHeight() - textHeight;
|
|---|
| 937 | if (attrTermsUrl != null) {
|
|---|
| 938 | int x = 2;
|
|---|
| 939 | int y = getHeight() - textHeight;
|
|---|
| 940 | attrToUBounds = new Rectangle(x, y-textHeight, textWidth, textRealHeight);
|
|---|
| 941 | g.setColor(Color.black);
|
|---|
| 942 | g.drawString("Background Terms of Use", x + 1, y + 1);
|
|---|
| 943 | g.setColor(Color.white);
|
|---|
| 944 | g.drawString("Background Terms of Use", x, y);
|
|---|
| 945 | }
|
|---|
| 946 |
|
|---|
| 947 | // Draw attribution logo
|
|---|
| 948 | if (attrImage != null) {
|
|---|
| 949 | int x = 2;
|
|---|
| 950 | int imgWidth = attrImage.getWidth(this);
|
|---|
| 951 | int height = attrImage.getHeight(null);
|
|---|
| 952 | int y = termsTextY - height - textHeight - 5;
|
|---|
| 953 | attrImageBounds = new Rectangle(x, y, imgWidth, height);
|
|---|
| 954 | g.drawImage(attrImage, x, y, null);
|
|---|
| 955 | }
|
|---|
| 956 |
|
|---|
| 957 | g.setFont(ATTR_FONT);
|
|---|
| 958 | Coordinate topLeft = getPosition(0, 0);
|
|---|
| 959 | Coordinate bottomRight = getPosition(getWidth(), getHeight());
|
|---|
| 960 | String attributionText = tileSource.getAttributionText(zoom, topLeft, bottomRight);
|
|---|
| 961 | if (attributionText != null) {
|
|---|
| 962 | Rectangle2D stringBounds = g.getFontMetrics().getStringBounds(attributionText, g);
|
|---|
| 963 | int x = getWidth() - (int) stringBounds.getWidth();
|
|---|
| 964 | int y = getHeight() - textHeight;
|
|---|
| 965 | g.setColor(Color.black);
|
|---|
| 966 | g.drawString(attributionText, x + 1, y + 1);
|
|---|
| 967 | g.setColor(Color.white);
|
|---|
| 968 | g.drawString(attributionText, x, y);
|
|---|
| 969 | attrTextBounds = new Rectangle(x, y-textHeight, textWidth, textRealHeight);
|
|---|
| 970 | }
|
|---|
| 971 |
|
|---|
| 972 | g.setFont(font);
|
|---|
| 973 | }
|
|---|
| 974 |
|
|---|
| 975 | protected EventListenerList listenerList = new EventListenerList();
|
|---|
| 976 |
|
|---|
| 977 | /**
|
|---|
| 978 | * @param listener to set
|
|---|
| 979 | */
|
|---|
| 980 | public void addJMVListener(JMapViewerEventListener listener) {
|
|---|
| 981 | listenerList.add(JMapViewerEventListener.class, listener);
|
|---|
| 982 | }
|
|---|
| 983 |
|
|---|
| 984 | public void removeJMVListener(JMapViewerEventListener listener) {
|
|---|
| 985 | listenerList.remove(JMapViewerEventListener.class, listener);
|
|---|
| 986 | }
|
|---|
| 987 |
|
|---|
| 988 | void fireJMVEvent(JMVCommandEvent evt) {
|
|---|
| 989 | Object[] listeners = listenerList.getListenerList();
|
|---|
| 990 | for (int i=0; i<listeners.length; i+=2) {
|
|---|
| 991 | if (listeners[i]==JMapViewerEventListener.class) {
|
|---|
| 992 | ((JMapViewerEventListener)listeners[i+1]).processCommand(evt);
|
|---|
| 993 | }
|
|---|
| 994 | }
|
|---|
| 995 | }
|
|---|
| 996 | }
|
|---|