package swingxmap; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Frame; import java.awt.Graphics2D; import java.awt.Panel; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.measure.unit.NonSI; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.eclipse.swt.SWT; import org.eclipse.swt.awt.SWT_AWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.jdesktop.swingx.JXMapKit; import org.jdesktop.swingx.JXMapViewer; import org.jdesktop.swingx.JXMapKit.DefaultProviders; import org.jdesktop.swingx.mapviewer.GeoPosition; import org.jdesktop.swingx.painter.Painter; import org.jscience.geography.coordinates.LatLong; public class MapViewContent implements Iterable<IPositionProvider> { public final static GeoPosition torgetITrondheim = new GeoPosition(63.43057,10.39221); private Control focusTarget = null; private JXMapKit mapKit; public void createControls(Composite parent) { mapKit = new JXMapKit(); mapKit.setDefaultProvider(DefaultProviders.OpenStreetMaps); mapKit.getMainMap().setPanEnabled(false); DraggingPositionHandler mouseHandler = new DraggingPositionHandler(); mapKit.getMainMap().addMouseListener(mouseHandler); mapKit.getMainMap().addMouseMotionListener(mouseHandler); mapKit.setAddressLocation(torgetITrondheim); mapKit.setAddressLocationShown(true); mapKit.setZoom(3); mapKit.getZoomSlider().getModel().addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { invalidateOverlayPainter(); } }); Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND); // composite.addListener(SWT.MouseMove, genericListener); // composite.addListener(SWT.MouseDown, genericListener); // composite.addListener(SWT.MouseUp, genericListener); Frame frame = SWT_AWT.new_Frame(composite); frame.setLayout(new BorderLayout()); Container swingParent = new Panel(); frame.add(swingParent, BorderLayout.CENTER); // Container swingParent = frame; swingParent.setLayout(new BorderLayout()); swingParent.add(mapKit, BorderLayout.CENTER); focusTarget = composite; invalidateOverlayPainter(); } private class DraggingPositionHandler extends MouseAdapter implements IPositionProvider, MouseMotionListener { private IPositionProvider draggingProvider = null; private GeoPosition lastPosition = null; public void mouseMoved(MouseEvent e) { updateMousePosition((int)e.getX(), (int)e.getY()); } public void mousePressed(MouseEvent e) { draggingProvider = findTopMostPositionProvider(e.getX(), e.getY()); // System.out.println("findTopMostPositionProvider: " + draggingProvider); if (draggingProvider == null) { draggingProvider = findEmptyPositionProvider(); } // System.out.println("Dragging " + draggingProvider); setLastPosition(e); setSelectedPosition(draggingProvider != null ? this : null); } private void setLastPosition(MouseEvent e) { lastPosition = mapKit.getMainMap().convertPointToGeoPosition(new Point2D.Double(e.getX(), e.getY())); } public void mouseDragged(MouseEvent e) { updateMousePosition((int)e.getX(), (int)e.getY()); if (draggingProvider != null && (! draggingProvider.isReadOnly())) { setLastPosition(e); updatePositions(); } } public void mouseReleased(MouseEvent e) { setPosition(lastPosition.getLatitude(), lastPosition.getLongitude()); } public LatLong getPosition() { return LatLong.valueOf(lastPosition.getLatitude(), lastPosition.getLongitude(), NonSI.DEGREE_ANGLE); } public boolean isReadOnly() { return false; } public void setPosition(double latitude, double longitude) { if (draggingProvider != null && (! draggingProvider.isReadOnly())) { draggingProvider.setPosition(latitude, longitude); } } public String getToolTip() { return (draggingProvider != null ? draggingProvider.getToolTip() : null); } public org.eclipse.swt.graphics.Color getColor() { return (draggingProvider != null ? draggingProvider.getColor() : null); } } protected void updateMousePosition(int x, int y) { String status = getToolTipText(x, y, ", "); GeoPosition location = mapKit.getMainMap().convertPointToGeoPosition(new Point2D.Double(x, y)); String geoString = " (" + location.getLatitude() + ", " + location.getLongitude() + ")"; status = (status != null ? status + geoString : geoString); updateStatus(status); } protected void updateStatus(String status) { } private List<IPositionProvider> locations = new ArrayList<IPositionProvider>(); public void addPosition(double lat, double lng) { addPosition(new GeoPosition(lat, lng)); } public void addPosition(GeoPosition position) { locations.add(new GeoPositionProvider(position)); } public void addPosition(IPositionProvider position) { locations.add(position); } public void removePosition(IPositionProvider position) { locations.remove(position); } public void clearPositions() { locations.clear(); selectedPosition = null; } public Iterator<IPositionProvider> iterator() { return getProviders(); } public void updatePositions() { invalidateOverlayPainter(); } protected void paintLocation(Graphics2D g2d, GeoPosition location, Point2D position) { double size = 4.0; g2d.drawOval((int)(position.getX() - size / 2), (int)(position.getY() - size / 2), (int)size, (int)size); } private Color defaultPositionColor = Color.black; private Color defaultSelectedPositionColor = Color.red; private IPositionProvider selectedPosition = null; public void setSelectedPosition(IPositionProvider provider) { selectedPosition = provider; updatePositions(); } private boolean isSelected(IPositionProvider provider) { if (selectedPosition == provider) { return true; } if (selectedPosition instanceof DraggingPositionHandler && ((DraggingPositionHandler)selectedPosition).draggingProvider == provider) { return true; } return false; } private static GeoPosition createGeoPosition(IPositionProvider provider) { LatLong latLong = provider.getPosition(); return new GeoPosition(latLong.latitudeValue(NonSI.DEGREE_ANGLE), latLong.longitudeValue(NonSI.DEGREE_ANGLE)); } public class DefaultLocationsPainter implements Painter<JXMapViewer> { public void paint(Graphics2D g2d, JXMapViewer mapViewer, int width, int height) { g2d.setStroke(new BasicStroke(2.0f)); for (IPositionProvider provider: locations.toArray(new IPositionProvider[locations.size()])) { if ((! isSelected(provider)) && provider.getPosition() != null) { paintPosition(g2d, provider); } } if (selectedPosition != null && selectedPosition.getPosition() != null) { paintPosition(g2d, selectedPosition); } } private void paintPosition(Graphics2D g2d, IPositionProvider provider) { GeoPosition location = createGeoPosition(provider); Point2D position = mapKit.getMainMap().convertGeoPositionToPoint(location); org.eclipse.swt.graphics.Color c = provider.getColor(); g2d.setColor(c != null ? new Color(c.getRed(), c.getGreen(), c.getBlue()) : (provider == selectedPosition ? defaultSelectedPositionColor : defaultPositionColor)); paintLocation(g2d, location, position); } protected void paintLocation(Graphics2D g2d, GeoPosition location, Point2D position) { MapViewContent.this.paintLocation(g2d, location, position); } }; private Painter<JXMapViewer> locationsPainter = new DefaultLocationsPainter(); public Iterator<IPositionProvider> getProviders() { return new PositionProviderIterator(); } private class PositionProviderIterator implements Iterator<IPositionProvider> { private Point2D point; private Iterator<IPositionProvider> providers; private IPositionProvider currentProvider = null; public PositionProviderIterator() { providers = locations.iterator(); } public PositionProviderIterator(Point point) { this(); this.point = point; } public boolean hasNext() { if (currentProvider == null) { getNext(); } return currentProvider != null; } private void getNext() { currentProvider = null; while (providers.hasNext() && currentProvider == null) { IPositionProvider provider = providers.next(); if (point == null) { currentProvider = provider; } else if (provider.getPosition() != null) { GeoPosition location = createGeoPosition(provider); Point2D position = mapKit.getMainMap().convertGeoPositionToPoint(location); double dx = position.getX() - point.getX(), dy = position.getY() - point.getY(), distance = Math.sqrt(dx * dx + dy * dy); if (distance <= 4.0) { currentProvider = provider; } } } } public IPositionProvider next() { IPositionProvider provider = currentProvider; getNext(); return provider; } public void remove() { providers.remove(); } } public IPositionProvider findTopMostPositionProvider(int x, int y) { IPositionProvider currentProvider = null; for (Iterator<IPositionProvider> providers = new PositionProviderIterator(new Point(x, y)); providers.hasNext();) { currentProvider = providers.next(); } return currentProvider; } public IPositionProvider findEmptyPositionProvider() { for (Iterator<IPositionProvider> providers = new PositionProviderIterator(); providers.hasNext();) { IPositionProvider currentProvider = providers.next(); if (currentProvider.getPosition() == null) { // return currentProvider; } } return null; } public String getToolTipText(int x, int y, String separator) { String toolTip = null; Iterator<IPositionProvider> providers = new PositionProviderIterator(new Point(x, y)); while (providers.hasNext()) { IPositionProvider provider = providers.next(); String positionToolTip = provider.getToolTip(); if (positionToolTip == null); else if (toolTip == null) { toolTip = positionToolTip; } else { toolTip += separator + positionToolTip; } } return toolTip; } public void setLocationsPainter(Painter<JXMapViewer> painter) { this.locationsPainter = painter; } private void invalidateOverlayPainter() { mapKit.getMainMap().setOverlayPainter(locationsPainter); mapKit.getMainMap().repaint(); } public void setFocus() { focusTarget.setFocus(); // mapKit.getMainMap().requestFocus(); } }