19 package org.sleuthkit.autopsy.geolocation;
21 import java.awt.AlphaComposite;
22 import java.awt.BasicStroke;
23 import java.awt.Color;
24 import java.awt.Dimension;
25 import java.awt.Graphics2D;
26 import java.awt.Paint;
27 import java.awt.Point;
28 import java.awt.Rectangle;
29 import java.awt.RenderingHints;
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.awt.event.ComponentAdapter;
33 import java.awt.event.ComponentEvent;
34 import java.awt.geom.GeneralPath;
35 import java.awt.geom.Point2D;
36 import java.awt.image.BufferedImage;
37 import java.beans.PropertyChangeEvent;
38 import java.beans.PropertyChangeListener;
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.List;
49 import java.util.logging.Level;
50 import java.util.prefs.PreferenceChangeEvent;
51 import java.util.prefs.PreferenceChangeListener;
52 import javax.swing.JMenuItem;
53 import javax.swing.JOptionPane;
54 import javax.swing.JPopupMenu;
55 import javax.swing.JSeparator;
56 import javax.swing.Popup;
57 import javax.swing.PopupFactory;
58 import javax.swing.Timer;
59 import javax.swing.event.MouseInputListener;
60 import org.jxmapviewer.JXMapViewer;
61 import org.jxmapviewer.OSMTileFactoryInfo;
62 import org.jxmapviewer.VirtualEarthTileFactoryInfo;
63 import org.jxmapviewer.input.CenterMapListener;
64 import org.jxmapviewer.input.ZoomMouseWheelListenerCursor;
65 import org.jxmapviewer.viewer.DefaultTileFactory;
66 import org.jxmapviewer.viewer.GeoPosition;
67 import org.jxmapviewer.viewer.TileFactory;
68 import org.jxmapviewer.viewer.TileFactoryInfo;
69 import org.jxmapviewer.viewer.WaypointPainter;
70 import org.jxmapviewer.viewer.WaypointRenderer;
71 import org.openide.util.NbBundle.Messages;
77 import javax.imageio.ImageIO;
78 import javax.swing.SwingUtilities;
79 import org.jxmapviewer.painter.CompoundPainter;
80 import org.jxmapviewer.painter.Painter;
81 import org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
86 @SuppressWarnings(
"deprecation")
87 final public class
MapPanel extends javax.swing.JPanel {
89 static final String CURRENT_MOUSE_GEOPOSITION =
"CURRENT_MOUSE_GEOPOSITION";
93 private static final long serialVersionUID = 1L;
94 private static final Set<Integer> DOT_WAYPOINT_TYPES =
new HashSet<>();
95 private static final int DOT_SIZE = 12;
96 private static final Set<Integer> VERY_SMALL_DOT_WAYPOINT_TYPES =
new HashSet<>();
97 private static final int VERY_SMALL_DOT_SIZE = 6;
102 private List<Set<MapWaypoint>> tracks =
new ArrayList<>();
103 private List<Set<MapWaypoint>> areas =
new ArrayList<>();
108 private static final int POPUP_WIDTH = 300;
109 private static final int POPUP_HEIGHT = 200;
110 private static final int POPUP_MARGIN = 10;
119 DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID());
120 DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID());
121 DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID());
122 VERY_SMALL_DOT_WAYPOINT_TYPES.add(ARTIFACT_TYPE.TSK_GPS_AREA.getTypeID());
129 "MapPanel_connection_failure_message=Failed to connect to new geolocation map tile source.",
130 "MapPanel_connection_failure_message_title=Connection Failure"
135 zoomChanging =
false;
137 popupFactory =
new PopupFactory();
140 whiteWaypointImage = ImageIO.read(getClass().getResource(
"/org/sleuthkit/autopsy/images/waypoint_white.png"));
141 transparentWaypointImage = ImageIO.read(getClass().getResource(
"/org/sleuthkit/autopsy/images/waypoint_transparent.png"));
142 }
catch (IOException ex) {
143 logger.log(Level.WARNING,
"Unable to load geolocation waypoint images", ex);
152 public void resizeTimedOut() {
159 public void preferenceChange(PreferenceChangeEvent evt) {
162 mapViewer.getTileFactory().dispose();
164 mapViewer.setTileFactory(getTileFactory());
165 initializeZoomSlider();
167 logger.log(Level.SEVERE,
"Failed to connect to new geolocation tile server.", ex);
168 JOptionPane.showMessageDialog(
MapPanel.this,
169 Bundle.MapPanel_connection_failure_message(),
170 Bundle.MapPanel_connection_failure_message_title(),
171 JOptionPane.ERROR_MESSAGE);
173 Bundle.MapPanel_connection_failure_message_title(),
174 Bundle.MapPanel_connection_failure_message());
185 List<MapWaypoint> getVisibleWaypoints() {
187 Rectangle viewport = mapViewer.getViewportBounds();
188 List<MapWaypoint> waypoints =
new ArrayList<>();
190 Iterator<MapWaypoint> iterator = waypointTree.
iterator();
191 while (iterator.hasNext()) {
193 if (viewport.contains(mapViewer.getTileFactory().geoToPixel(waypoint.
getPosition(), mapViewer.getZoom()))) {
194 waypoints.add(waypoint);
204 void initMap() throws GeoLocationDataException {
206 TileFactory tileFactory = getTileFactory();
207 mapViewer.setTileFactory(tileFactory);
210 MouseInputListener mia =
new MapPanMouseInputListener(mapViewer);
211 mapViewer.addMouseListener(mia);
212 mapViewer.addMouseMotionListener(mia);
214 mapViewer.addMouseListener(
new CenterMapListener(mapViewer));
215 mapViewer.addMouseWheelListener(
new ZoomMouseWheelListenerCursor(mapViewer));
218 mapViewer.addPropertyChangeListener(
"zoom",
new PropertyChangeListener() {
220 public void propertyChange(PropertyChangeEvent evt) {
221 zoomSlider.setValue(mapViewer.getZoom());
225 zoomSlider.setMinimum(tileFactory.getInfo().getMinimumZoomLevel());
226 zoomSlider.setMaximum(tileFactory.getInfo().getMaximumZoomLevel());
228 setZoom(tileFactory.getInfo().getMaximumZoomLevel() - 1);
230 mapViewer.setCenterPosition(
new GeoPosition(0, 0));
235 void initializePainter() {
237 WaypointPainter<MapWaypoint> waypointPainter =
new WaypointPainter<MapWaypoint>() {
239 public Set<MapWaypoint> getWaypoints() {
240 if (currentlySelectedWaypoint != null) {
241 waypointSet.remove(currentlySelectedWaypoint);
242 waypointSet.add(currentlySelectedWaypoint);
247 waypointPainter.setRenderer(
new MapWaypointRenderer());
249 ArrayList<Painter<JXMapViewer>> painters =
new ArrayList<>();
250 painters.add(
new MapAreaRenderer(areas));
251 painters.add(
new MapTrackRenderer(tracks));
252 painters.add(waypointPainter);
254 CompoundPainter<JXMapViewer> compoundPainter =
new CompoundPainter<>(painters);
255 mapViewer.setOverlayPainter(compoundPainter);
261 void initializeZoomSlider() {
262 TileFactory tileFactory = mapViewer.getTileFactory();
263 zoomSlider.setMinimum(tileFactory.getInfo().getMinimumZoomLevel());
264 zoomSlider.setMaximum(tileFactory.getInfo().getMaximumZoomLevel());
266 zoomSlider.repaint();
267 zoomSlider.revalidate();
277 case ONLINE_USER_DEFINED_OSM_SERVER:
279 case OFFLINE_OSM_ZIP:
281 case OFFILE_MBTILES_FILE:
284 return new DefaultTileFactory(
new VirtualEarthTileFactoryInfo(VirtualEarthTileFactoryInfo.MAP));
298 if (address.isEmpty()) {
299 throw new GeoLocationDataException(
"Invalid user preference for OSM user define tile server. Address is an empty string.");
301 TileFactoryInfo info =
new OSMTileFactoryInfo(
"User Defined Server", address);
316 if (path.isEmpty()) {
317 throw new GeoLocationDataException(
"Invalid OSM tile Zip file. User preference value is empty string.");
319 File file =
new File(path);
320 if (!file.exists() || !file.canRead()) {
321 throw new GeoLocationDataException(
"Invalid OSM tile zip file. Unable to read file: " + path);
324 String zipPath = path.replaceAll(
"\\\\",
"/");
326 return new OSMTileFactoryInfo(
"ZIP archive",
"jar:file:/" + zipPath +
"!");
335 void setWaypoints(Set<MapWaypoint> waypoints) {
337 this.waypointSet = waypoints;
339 waypointTree.
add(waypoint);
349 void setTracks(List<Set<MapWaypoint>> tracks) {
350 this.tracks = tracks;
358 void setAreas(List<Set<MapWaypoint>> areas) {
367 void setZoom(
int zoom) {
369 mapViewer.setZoom(zoom);
370 zoomSlider.setValue(zoom);
371 zoomChanging =
false;
377 void clearWaypoints() {
379 currentlySelectedWaypoint = null;
380 currentlySelectedSet = null;
381 if (currentPopup != null) {
395 List<MapWaypoint> waypoints = findClosestWaypoint(point);
397 if (waypoints.size() > 0) {
398 waypoint = waypoints.get(0);
400 showPopupMenu(waypoint, point);
403 if (waypoint != null && !waypoint.
equals(currentlySelectedWaypoint)) {
404 currentlySelectedWaypoint = waypoint;
405 if (currentPopup != null) {
410 }
catch (TskCoreException ex) {
411 logger.log(Level.WARNING,
"Failed to show popup for waypoint", ex);
422 if (waypoint == null) {
426 JMenuItem[] items = waypoint.getMenuItems();
427 JPopupMenu popupMenu =
new JPopupMenu();
428 for (JMenuItem menu : items) {
433 popupMenu.add(
new JSeparator());
436 popupMenu.show(mapViewer, point.x, point.y);
443 if (currentlySelectedWaypoint != null) {
444 if (currentPopup != null) {
448 WaypointDetailPanel detailPane =
new WaypointDetailPanel();
449 detailPane.setWaypoint(currentlySelectedWaypoint);
450 detailPane.setPreferredSize(
new Dimension(POPUP_WIDTH, POPUP_HEIGHT));
451 detailPane.addActionListener(
new ActionListener() {
453 public void actionPerformed(ActionEvent e) {
454 if (currentPopup != null) {
462 Point popupLocation = getLocationForDetailsPopup();
464 currentPopup = popupFactory.getPopup(
this, detailPane, popupLocation.x, popupLocation.y);
468 if (currentPopup != null) {
473 mapViewer.revalidate();
483 Point panelCorner = this.getLocationOnScreen();
484 int width = this.getWidth();
486 int popupX = panelCorner.x + width - POPUP_WIDTH - POPUP_MARGIN;
487 int popupY = panelCorner.y + POPUP_MARGIN;
489 return new Point(popupX, popupY);
501 if (waypointTree == null) {
502 return new ArrayList<>();
506 GeoPosition geopos = mapViewer.convertPointToGeoPosition(clickPoint);
511 if (waypoints == null || waypoints.isEmpty()) {
515 Iterator<MapWaypoint> iterator = waypoints.iterator();
519 List<MapWaypoint> closestPoints =
new ArrayList<>();
520 while (iterator.hasNext()) {
522 Point2D point = mapViewer.convertGeoPositionToPoint(nextWaypoint.
getPosition());
523 int pointX = (int) point.
getX();
524 int pointY = (int) point.getY();
526 if (DOT_WAYPOINT_TYPES.contains(nextWaypoint.getArtifactTypeID())) {
527 rect =
new Rectangle(
528 pointX - (DOT_SIZE / 2),
529 pointY - (DOT_SIZE / 2),
533 }
else if (VERY_SMALL_DOT_WAYPOINT_TYPES.contains(nextWaypoint.getArtifactTypeID())) {
534 rect =
new Rectangle(
535 pointX - (VERY_SMALL_DOT_SIZE / 2),
536 pointY - (VERY_SMALL_DOT_SIZE / 2),
541 rect =
new Rectangle(
542 pointX - (whiteWaypointImage.getWidth() / 2),
543 pointY - whiteWaypointImage.getHeight(),
544 whiteWaypointImage.getWidth(),
545 whiteWaypointImage.getHeight()
549 if (rect.contains(clickPoint)) {
550 closestPoints.add(nextWaypoint);
554 return closestPoints;
567 extends ComponentAdapter
568 implements ActionListener {
571 private static final int DEFAULT_TIMEOUT = 200;
578 this(DEFAULT_TIMEOUT);
587 timer =
new Timer(delayMS,
this);
588 timer.setRepeats(
false);
589 timer.setCoalesce(
false);
605 public abstract void resizeTimedOut();
613 @SuppressWarnings(
"unchecked")
615 private
void initComponents() {
616 java.awt.GridBagConstraints gridBagConstraints;
618 mapViewer =
new org.jxmapviewer.JXMapViewer();
619 zoomPanel =
new javax.swing.JPanel();
620 zoomSlider =
new javax.swing.JSlider();
621 javax.swing.JButton zoomInBtn =
new javax.swing.JButton();
622 javax.swing.JButton zoomOutBtn =
new javax.swing.JButton();
625 setLayout(
new java.awt.BorderLayout());
627 mapViewer.addMouseMotionListener(
new java.awt.event.MouseMotionAdapter() {
628 public void mouseMoved(java.awt.event.MouseEvent evt) {
629 mapViewerMouseMoved(evt);
632 mapViewer.addMouseListener(
new java.awt.event.MouseAdapter() {
633 public void mouseClicked(java.awt.event.MouseEvent evt) {
634 mapViewerMouseClicked(evt);
636 public void mousePressed(java.awt.event.MouseEvent evt) {
637 mapViewerMousePressed(evt);
639 public void mouseReleased(java.awt.event.MouseEvent evt) {
640 mapViewerMouseReleased(evt);
643 mapViewer.setLayout(
new java.awt.GridBagLayout());
645 zoomPanel.setFocusable(
false);
646 zoomPanel.setOpaque(
false);
647 zoomPanel.setRequestFocusEnabled(
false);
648 zoomPanel.setLayout(
new java.awt.GridBagLayout());
650 zoomSlider.setMaximum(15);
651 zoomSlider.setMinimum(10);
652 zoomSlider.setMinorTickSpacing(1);
653 zoomSlider.setOrientation(javax.swing.JSlider.VERTICAL);
654 zoomSlider.setPaintTicks(
true);
655 zoomSlider.setSnapToTicks(
true);
656 zoomSlider.setInverted(
true);
657 zoomSlider.setMinimumSize(
new java.awt.Dimension(35, 100));
658 zoomSlider.setOpaque(
false);
659 zoomSlider.setPreferredSize(
new java.awt.Dimension(35, 190));
660 zoomSlider.addChangeListener(
new javax.swing.event.ChangeListener() {
661 public void stateChanged(javax.swing.event.ChangeEvent evt) {
662 zoomSliderStateChanged(evt);
665 gridBagConstraints =
new java.awt.GridBagConstraints();
666 gridBagConstraints.gridx = 0;
667 gridBagConstraints.gridy = 1;
668 zoomPanel.add(zoomSlider, gridBagConstraints);
670 zoomInBtn.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/plus-grey.png")));
671 org.openide.awt.Mnemonics.setLocalizedText(zoomInBtn,
org.openide.util.NbBundle.getMessage(
MapPanel.class,
"MapPanel.zoomInBtn.text"));
672 zoomInBtn.setBorder(null);
673 zoomInBtn.setBorderPainted(
false);
674 zoomInBtn.setFocusPainted(
false);
675 zoomInBtn.setRequestFocusEnabled(
false);
676 zoomInBtn.setRolloverEnabled(
false);
677 zoomInBtn.addActionListener(
new java.awt.event.ActionListener() {
678 public void actionPerformed(java.awt.event.ActionEvent evt) {
679 zoomInBtnActionPerformed(evt);
682 gridBagConstraints =
new java.awt.GridBagConstraints();
683 gridBagConstraints.gridx = 0;
684 gridBagConstraints.gridy = 0;
685 zoomPanel.add(zoomInBtn, gridBagConstraints);
687 zoomOutBtn.setIcon(
new javax.swing.ImageIcon(getClass().getResource(
"/org/sleuthkit/autopsy/images/minus-grey.png")));
688 org.openide.awt.Mnemonics.setLocalizedText(zoomOutBtn,
org.openide.util.NbBundle.getMessage(
MapPanel.class,
"MapPanel.zoomOutBtn.text"));
689 zoomOutBtn.setBorder(null);
690 zoomOutBtn.setBorderPainted(
false);
691 zoomOutBtn.setFocusPainted(
false);
692 zoomOutBtn.setRequestFocusEnabled(
false);
693 zoomOutBtn.setRolloverEnabled(
false);
694 zoomOutBtn.addActionListener(
new java.awt.event.ActionListener() {
695 public void actionPerformed(java.awt.event.ActionEvent evt) {
696 zoomOutBtnActionPerformed(evt);
699 gridBagConstraints =
new java.awt.GridBagConstraints();
700 gridBagConstraints.gridx = 0;
701 gridBagConstraints.gridy = 2;
702 zoomPanel.add(zoomOutBtn, gridBagConstraints);
704 gridBagConstraints =
new java.awt.GridBagConstraints();
705 gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
706 gridBagConstraints.weightx = 1.0;
707 gridBagConstraints.weighty = 1.0;
708 gridBagConstraints.insets =
new java.awt.Insets(4, 4, 4, 4);
709 mapViewer.add(zoomPanel, gridBagConstraints);
711 add(mapViewer, java.awt.BorderLayout.CENTER);
716 setZoom(zoomSlider.getValue());
721 if (evt.isPopupTrigger()) {
722 showPopupMenu(evt.getPoint());
727 if (evt.isPopupTrigger()) {
728 showPopupMenu(evt.getPoint());
733 GeoPosition geopos = mapViewer.convertPointToGeoPosition(evt.getPoint());
734 firePropertyChange(CURRENT_MOUSE_GEOPOSITION, null, geopos);
738 if (!evt.isPopupTrigger() && SwingUtilities.isLeftMouseButton(evt)) {
739 List<MapWaypoint> waypoints = findClosestWaypoint(evt.getPoint());
740 if (waypoints.size() > 0) {
742 currentlySelectedWaypoint = selection;
743 currentlySelectedSet = null;
744 for (Set<MapWaypoint> track : tracks) {
745 if (track.contains(selection)) {
746 currentlySelectedSet = track;
750 if (currentlySelectedSet == null) {
751 for (Set<MapWaypoint> area : areas) {
752 if (area.contains(selection)) {
753 currentlySelectedSet = area;
759 currentlySelectedWaypoint = null;
760 currentlySelectedSet = null;
767 int currentValue = mapViewer.getZoom();
768 setZoom(currentValue - 1);
772 int currentValue = mapViewer.getZoom();
773 setZoom(currentValue + 1);
788 private final Map<Color, BufferedImage> dotImageCache =
new HashMap<>();
789 private final Map<Color, BufferedImage> verySmallDotImageCache =
new HashMap<>();
790 private final Map<Color, BufferedImage> waypointImageCache =
new HashMap<>();
799 Color baseColor = waypoint.getColor();
800 if (waypoint.
equals(currentlySelectedWaypoint)
801 || (currentlySelectedSet != null && currentlySelectedSet.contains(waypoint))) {
819 BufferedImage ret =
new BufferedImage(s, s, BufferedImage.TYPE_INT_ARGB);
820 Graphics2D g = ret.createGraphics();
821 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
823 g.fillOval(1, 1, s - 2, s - 2);
824 g.setColor(Color.BLACK);
825 g.setStroke(
new BasicStroke(1));
826 g.drawOval(1, 1, s - 2, s - 2);
839 int w = whiteWaypointImage.getWidth();
840 int h = whiteWaypointImage.getHeight();
842 BufferedImage ret =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
844 Graphics2D g = ret.createGraphics();
845 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
846 g.drawImage(whiteWaypointImage, 0, 0, null);
847 g.setComposite(AlphaComposite.SrcIn);
849 g.fillRect(0, 0, w, h);
850 g.setComposite(AlphaComposite.SrcAtop);
851 g.drawImage(transparentWaypointImage, 0, 0, null);
858 Color color = getColor(waypoint);
860 Point2D point = map.getTileFactory().geoToPixel(waypoint.
getPosition(), map.getZoom());
861 int x = (int) point.getX();
862 int y = (int) point.getY();
864 if (DOT_WAYPOINT_TYPES.contains(waypoint.getArtifactTypeID())) {
865 image = dotImageCache.computeIfAbsent(color, k -> {
866 return createTrackDotImage(color, DOT_SIZE);
869 y -= image.getHeight() / 2;
870 }
else if (VERY_SMALL_DOT_WAYPOINT_TYPES.contains(waypoint.getArtifactTypeID())) {
871 image = verySmallDotImageCache.computeIfAbsent(color, k -> {
872 return createTrackDotImage(color, VERY_SMALL_DOT_SIZE);
875 y -= image.getHeight() / 2;
877 image = waypointImageCache.computeIfAbsent(color, k -> {
878 return createWaypointImage(color);
881 y -= image.getHeight();
884 x -= image.getWidth() / 2;
886 Graphics2D g2d = (Graphics2D) g.create();
887 g2d.drawImage(image, x, y, null);
897 private final List<Set<MapWaypoint>>
tracks;
900 this.tracks = tracks;
903 private void drawRoute(Set<MapWaypoint> track, Graphics2D g, JXMapViewer map) {
907 boolean first =
true;
910 Point2D p = map.getTileFactory().geoToPixel(wp.getPosition(), map.getZoom());
911 int thisX = (int) p.getX();
912 int thisY = (int) p.getY();
917 g.drawLine(lastX, lastY, thisX, thisY);
926 public void paint(Graphics2D g, JXMapViewer map,
int w,
int h) {
927 Graphics2D g2d = (Graphics2D) g.create();
929 Rectangle bounds = map.getViewportBounds();
930 g2d.translate(-bounds.x, -bounds.y);
932 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
934 g2d.setColor(Color.BLACK);
935 g2d.setStroke(
new BasicStroke(2));
937 for (Set<MapWaypoint> track : tracks) {
938 drawRoute(track, g2d, map);
950 private final List<Set<MapWaypoint>>
areas;
963 private void drawArea(Set<MapWaypoint> area, Graphics2D g, JXMapViewer map) {
964 if (area.isEmpty()) {
967 boolean first =
true;
969 GeneralPath polygon =
new GeneralPath(GeneralPath.WIND_EVEN_ODD, area.size());
972 Point2D p = map.getTileFactory().geoToPixel(wp.getPosition(), map.getZoom());
973 int thisX = (int) p.getX();
974 int thisY = (int) p.getY();
977 polygon.moveTo(thisX, thisY);
980 polygon.lineTo(thisX, thisY);
985 Color areaColor = area.iterator().next().getColor();
986 final double maxColorValue = 255.0;
987 g.setPaint(
new Color((
float)(areaColor.getRed() / maxColorValue),
988 (
float)(areaColor.getGreen() / maxColorValue),
989 (
float)(areaColor.getBlue() / maxColorValue),
996 public void paint(Graphics2D g, JXMapViewer map,
int w,
int h) {
997 Graphics2D g2d = (Graphics2D) g.create();
999 Rectangle bounds = map.getViewportBounds();
1000 g2d.translate(-bounds.x, -bounds.y);
1002 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
1004 g2d.setColor(Color.BLACK);
1005 g2d.setStroke(
new BasicStroke(2));
1007 for (Set<MapWaypoint> area : areas) {
1008 drawArea(area, g2d, map);
void paint(Graphics2D g, JXMapViewer map, int w, int h)
final List< Set< MapWaypoint > > tracks
void zoomInBtnActionPerformed(java.awt.event.ActionEvent evt)
static String getGeolocationOsmZipPath()
final PopupFactory popupFactory
void showPopupMenu(MapWaypoint waypoint, Point point)
boolean equals(Object obj)
BufferedImage createWaypointImage(Color color)
void zoomSliderStateChanged(javax.swing.event.ChangeEvent evt)
void componentResized(ComponentEvent e)
void mapViewerMouseReleased(java.awt.event.MouseEvent evt)
Collection< T > nearestNeighbourSearch(int numNeighbors, T value)
ComponentResizeEndListener()
javax.swing.JPanel zoomPanel
KdTree< MapWaypoint > waypointTree
static String getGeolocationMBTilesFilePath()
TileFactoryInfo createOnlineOSMFactory(String address)
BufferedImage whiteWaypointImage
javax.swing.JSlider zoomSlider
void mapViewerMouseClicked(java.awt.event.MouseEvent evt)
void mapViewerMousePressed(java.awt.event.MouseEvent evt)
void mapViewerMouseMoved(java.awt.event.MouseEvent evt)
void drawRoute(Set< MapWaypoint > track, Graphics2D g, JXMapViewer map)
Set< MapWaypoint > currentlySelectedSet
Color getColor(MapWaypoint waypoint)
List< MapWaypoint > findClosestWaypoint(Point clickPoint)
void drawArea(Set< MapWaypoint > area, Graphics2D g, JXMapViewer map)
static int getGeolocationtTileOption()
Point getLocationForDetailsPopup()
void actionPerformed(ActionEvent e)
final List< Set< MapWaypoint > > areas
TileFactoryInfo createOSMZipFactory(String path)
BufferedImage createTrackDotImage(Color color, int s)
static String getGeolocationOsmServerAddress()
void paintWaypoint(Graphics2D g, JXMapViewer map, MapWaypoint waypoint)
static void error(String title, String message)
TileFactory getTileFactory()
synchronized static Logger getLogger(String name)
void zoomOutBtnActionPerformed(java.awt.event.ActionEvent evt)
static void addChangeListener(PreferenceChangeListener listener)
ComponentResizeEndListener(int delayMS)
void paint(Graphics2D g, JXMapViewer map, int w, int h)
BufferedImage transparentWaypointImage
GeoPosition getPosition()
Set< MapWaypoint > waypointSet
org.jxmapviewer.JXMapViewer mapViewer
void showPopupMenu(Point point)
MapWaypoint currentlySelectedWaypoint