// ********************************************************************** // // <copyright> // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // </copyright> // ********************************************************************** package com.bbn.openmap.event; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.net.MalformedURLException; import java.net.URL; import java.util.Properties; import javax.swing.ImageIcon; import javax.swing.SwingUtilities; import com.bbn.openmap.BufferedMapBean; import com.bbn.openmap.MapBean; import com.bbn.openmap.image.ImageScaler; import com.bbn.openmap.omGraphics.DrawingAttributes; import com.bbn.openmap.proj.Cartesian; import com.bbn.openmap.proj.Cylindrical; import com.bbn.openmap.proj.Proj; import com.bbn.openmap.proj.Projection; import com.bbn.openmap.util.PropUtils; /** * OMMouseMode is a combination of the PanMouseMode, NavMouseMode and * SelectMouseMode. Press and drag to pan. Double click to re-center, CTRL * double click to re-center and zoom. Shift-CTRL-Double click to center and * zoom out. Double click to select OMGraphics. Right click for pop-up menu. */ public class OMMouseMode extends CoordMouseMode { /** * */ private static final long serialVersionUID = 1L; public final static String OPAQUENESS_PROPERTY = "opaqueness"; public final static String LEAVE_SHADOW_PROPERTY = "leaveShadow"; public final static String USE_CURSOR_PROPERTY = "useCursor"; public final static String AZ_PANNING_SHAPEFILE_PROPERTY = "azPanningShapefile"; public final static String AZ_PANNING_PROPERTY = "azPanning"; public final static float DEFAULT_OPAQUENESS = 1.0f; public final static transient String modeID = "Gestures"; private boolean isPanning = false; private int oX, oY; private float opaqueness = DEFAULT_OPAQUENESS; private boolean leaveShadow = false; private boolean useCursor; private AzimuthPanner azPanner = null; private String azPanningShapefile = null; private DrawingAttributes azDrawing = null; /** * rPoint1 is the anchor point of a line segment */ public Point2D rPoint1; /** * rPoint2 is the new (current) point of a line segment */ public Point2D rPoint2; protected BufferedMapBean theMap = null; protected String coordString = null; public OMMouseMode() { super(modeID, true); setUseCursor(false); setLeaveShadow(true); setOpaqueness(DEFAULT_OPAQUENESS); DrawingAttributes da = DrawingAttributes.getDefaultClone(); da.setMatted(true); da.setMattingPaint(Color.LIGHT_GRAY); setAzDrawing(da); } /** * @return Returns the useCursor. */ public boolean isUseCursor() { return useCursor; } /** * @param useCursor The useCursor to set. */ public void setUseCursor(boolean useCursor) { this.useCursor = useCursor; if (useCursor) { /* * For who like make his CustomCursor */ try { Toolkit tk = Toolkit.getDefaultToolkit(); ImageIcon pointer = new ImageIcon(getClass().getResource("Gestures.gif")); Dimension bestSize = tk.getBestCursorSize(pointer.getIconWidth(), pointer.getIconHeight()); Image pointerImage = ImageScaler.getOptimalScalingImage(pointer.getImage(), (int) bestSize.getWidth(), (int) bestSize.getHeight()); Cursor cursor = tk.createCustomCursor(pointerImage, new Point(0, 0), "PP"); setModeCursor(cursor); return; } catch (Exception e) { // Problem finding image probably, just move on. } } setModeCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } public void setProperties(String prefix, Properties props) { super.setProperties(prefix, props); prefix = PropUtils.getScopedPropertyPrefix(prefix); opaqueness = PropUtils.floatFromProperties(props, prefix + OPAQUENESS_PROPERTY, opaqueness); leaveShadow = PropUtils.booleanFromProperties(props, prefix + LEAVE_SHADOW_PROPERTY, leaveShadow); azPanningShapefile = props.getProperty(prefix + AZ_PANNING_SHAPEFILE_PROPERTY, azPanningShapefile); setUseCursor(PropUtils.booleanFromProperties(props, prefix + USE_CURSOR_PROPERTY, isUseCursor())); azDrawing.setProperties(prefix + AZ_PANNING_PROPERTY, props); } public Properties getProperties(Properties props) { props = super.getProperties(props); String prefix = PropUtils.getScopedPropertyPrefix(this); props.put(prefix + OPAQUENESS_PROPERTY, Float.toString(getOpaqueness())); props.put(prefix + LEAVE_SHADOW_PROPERTY, Boolean.toString(isLeaveShadow())); props.put(prefix + USE_CURSOR_PROPERTY, Boolean.toString(isUseCursor())); props.put(prefix + AZ_PANNING_SHAPEFILE_PROPERTY, PropUtils.unnull(azPanningShapefile)); azDrawing.getProperties(props); return props; } public Properties getPropertyInfo(Properties props) { props = super.getPropertyInfo(props); PropUtils.setI18NPropertyInfo(i18n, props, OMMouseMode.class, OPAQUENESS_PROPERTY, "Transparency", "Transparency level for moving map, between 0 (clear) and 1 (opaque).", null); PropUtils.setI18NPropertyInfo(i18n, props, OMMouseMode.class, LEAVE_SHADOW_PROPERTY, "Leave Shadow", "Display current map in background while panning.", "com.bbn.openmap.util.propertyEditor.YesNoPropertyEditor"); PropUtils.setI18NPropertyInfo(i18n, props, OMMouseMode.class, USE_CURSOR_PROPERTY, "Use Cursor", "Use hand cursor for mouse mode.", "com.bbn.openmap.util.propertyEditor.YesNoPropertyEditor"); PropUtils.setI18NPropertyInfo(i18n, props, OMMouseMode.class, AZ_PANNING_SHAPEFILE_PROPERTY, "Az Projection Panning Shapefile", "Use a shapefile for azimuthal projection panning.", "com.bbn.openmap.util.propertyEditor.FUPropertyEditor"); azDrawing.getPropertyInfo(props); return props; } /** * Checks the MouseEvent to see if a BufferedMapBean can be found. * * @param evt MouseEvent, or a MapMouseEvent * @return BufferedMapBean, or null if source is not a BufferedMapBean. */ protected BufferedMapBean getBufferedMapBean(MouseEvent evt) { if (evt instanceof MapMouseEvent) { MapBean mb = ((MapMouseEvent) evt).getMap(); if (mb instanceof BufferedMapBean) { return (BufferedMapBean) mb; } } else { Object src = evt.getSource(); if (src instanceof BufferedMapBean) { return (BufferedMapBean) src; } } return null; } /** * PaintListener method. * * @param source the source object, most likely the MapBean * @param g java.awt.Graphics */ public void listenerPaint(Object source, Graphics g) { MapBean mapBean = source instanceof MapBean ? (MapBean) source : null; if (azPanner != null) { azPanner.render(g); } else if (mapBean != null) { mapBean.removePaintListener(this); } } /** * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent) * The first click for drag, the image is generated. This image is * redrawing when the mouse is move, but, I need to repain the original * image. */ public void mouseDragged(MouseEvent arg0) { super.mouseDragged(arg0); if (mouseSupport.proxy == null) { BufferedMapBean mapBean = getBufferedMapBean(arg0); if (mapBean == null) { // OMMouseMode needs a BufferedMapBean return; } Projection proj = mapBean.getProjection(); // Left mouse click, pan if (SwingUtilities.isLeftMouseButton(arg0)) { int x = arg0.getX(); int y = arg0.getY(); if (!isPanning) { oX = x; oY = y; isPanning = true; } else if (proj instanceof Cylindrical || proj instanceof Cartesian) { // oX and oY set for this case. Not used for Azimuth // projections. mapBean.setPanningTransform(AffineTransform.getTranslateInstance(x - oX, y - oY)); mapBean.repaint(); } else { if (azPanner == null) { URL url = null; try { url = PropUtils.getResourceOrFileOrURL(azPanningShapefile); } catch (MalformedURLException murle) { } if (url != null) { azPanner = new AzimuthPanner.Shapefile(oX, oY, getAzDrawing(), url); } else { azPanner = new AzimuthPanner.Standard(oX, oY, getAzDrawing()); } mapBean.addPaintListener(this); } // Azimuth projection if (azPanner != null) { azPanner.handlePan(mapBean, arg0); } mapBean.repaint(); } } } } /** * Process a mouse pressed event. Add the mouse location to the segment * vector. Calculate the cumulative total distance. * * @param e mouse event. */ public void mousePressed(MouseEvent e) { mouseSupport.fireMapMousePressed(e); e.getComponent().requestFocus(); if (mouseSupport.proxy == null) { if (SwingUtilities.isRightMouseButton(e)) { // mouse has now been pressed // mousePressed = true; MapBean mb = theMap; if (mb == null && e.getSource() instanceof MapBean) { mb = (MapBean) e.getSource(); } if (mb != null) { // anchor the new first point of the line rPoint1 = mb.getCoordinates(e); // ensure the second point is not yet set. rPoint2 = null; } } } } public void mouseClicked(MouseEvent e) { Object obj = e.getSource(); boolean consumed = mouseSupport.fireMapMouseClicked(e); if (consumed || !(obj instanceof MapBean) || e.getClickCount() < 2) return; MapBean map = (MapBean) obj; Projection projection = map.getProjection(); Proj p = (Proj) projection; Point2D llp = map.getCoordinates(e); boolean shift = e.isShiftDown(); if (shift) { p.setScale(p.getScale() * 2.0f); } else { p.setScale(p.getScale() / 2.0f); } p.setCenter(llp); map.setProjection(p); } /** * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) * Make Pan event for the map. */ public void mouseReleased(MouseEvent arg0) { if (mouseSupport.proxy == null && isPanning) { BufferedMapBean mb = getBufferedMapBean(arg0); if (mb == null) { return; } Projection proj = mb.getProjection(); Point2D center = proj.forward(proj.getCenter()); int x = arg0.getX(); int y = arg0.getY(); center.setLocation(center.getX() - x + oX, center.getY() - y + oY); /* * OK, center now holds the pixel location of the new center pnt. To * figure out the lat/lon of it, we can do a straight inverse * projection operation. We will need to take rotation into account * if needed. */ mb.setCenter(mb.inverse(center.getX(), center.getY(), null)); mb.setPanningTransform(null); isPanning = false; if (azPanner != null) { azPanner.handleUnpan(arg0); azPanner = null; } } super.mouseReleased(arg0); } public boolean isLeaveShadow() { return leaveShadow; } public void setLeaveShadow(boolean leaveShadow) { this.leaveShadow = leaveShadow; } public float getOpaqueness() { return opaqueness; } public void setOpaqueness(float opaqueness) { this.opaqueness = opaqueness; } public boolean isPanning() { return isPanning; } /** * @return the starting x pixel location of a drag. */ public int getOX() { return oX; } /** * @return the starting y pixel location of a drag. */ public int getOY() { return oY; } /** * @return the azPanningShapefile */ public String getAzPanningShapefile() { return azPanningShapefile; } /** * @param azPanningShapefile the azPanningShapefile to set */ public void setAzPanningShapefile(String azPanningShapefile) { this.azPanningShapefile = azPanningShapefile; } /** * @return the azDrawing */ public DrawingAttributes getAzDrawing() { return azDrawing; } /** * @param azDrawing the azDrawing to set */ public void setAzDrawing(DrawingAttributes azDrawing) { this.azDrawing = azDrawing; } }