001// License: GPL. For details, see Readme.txt file. 002package org.openstreetmap.gui.jmapviewer; 003 004import java.awt.Point; 005import java.awt.event.MouseEvent; 006import java.awt.event.MouseListener; 007import java.awt.event.MouseMotionListener; 008import java.awt.event.MouseWheelEvent; 009import java.awt.event.MouseWheelListener; 010 011/** 012 * Default map controller which implements map moving by pressing the right 013 * mouse button and zooming by double click or by mouse wheel. 014 * 015 * @author Jan Peter Stotz 016 * 017 */ 018public class DefaultMapController extends JMapController implements MouseListener, MouseMotionListener, 019MouseWheelListener { 020 021 private static final int MOUSE_BUTTONS_MASK = MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK 022 | MouseEvent.BUTTON2_DOWN_MASK; 023 024 private static final int MAC_MOUSE_BUTTON3_MASK = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK; 025 public DefaultMapController(JMapViewer map) { 026 super(map); 027 } 028 029 private Point lastDragPoint; 030 031 private boolean isMoving = false; 032 033 private boolean movementEnabled = true; 034 035 private int movementMouseButton = MouseEvent.BUTTON3; 036 private int movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; 037 038 private boolean wheelZoomEnabled = true; 039 private boolean doubleClickZoomEnabled = true; 040 041 public void mouseDragged(MouseEvent e) { 042 debugMouseEvent("DefaultMapController.mouseDragged", e); 043 if (!movementEnabled || !isMoving) 044 return; 045 // Is only the selected mouse button pressed? 046 if ((e.getModifiersEx() & MOUSE_BUTTONS_MASK) == movementMouseButtonMask || isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { 047 if (JMapViewer.debug) { 048 System.err.println("(#9897) moving"); 049 } 050 Point p = e.getPoint(); 051 if (lastDragPoint != null) { 052 int diffx = lastDragPoint.x - p.x; 053 int diffy = lastDragPoint.y - p.y; 054 map.moveMap(diffx, diffy); 055 } 056 lastDragPoint = p; 057 } 058 } 059 060 public void mouseClicked(MouseEvent e) { 061 debugMouseEvent("DefaultMapController.mouseClicked", e); 062 if (doubleClickZoomEnabled && e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { 063 map.zoomIn(e.getPoint()); 064 } 065 } 066 067 public void mousePressed(MouseEvent e) { 068 debugMouseEvent("DefaultMapController.mousePressed", e); 069 070 if (e.getButton() == movementMouseButton || isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { 071 if (JMapViewer.debug) { 072 System.err.println("(#9897) move start"); 073 } 074 lastDragPoint = null; 075 isMoving = true; 076 } 077 } 078 079 public void mouseReleased(MouseEvent e) { 080 debugMouseEvent("DefaultMapController.mouseReleased", e); 081 if (e.getButton() == movementMouseButton || isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1) { 082 if (JMapViewer.debug) { 083 System.err.println("(#9897) move stop"); 084 } 085 lastDragPoint = null; 086 isMoving = false; 087 } 088 } 089 090 public void debugMouseEvent(String s, MouseEvent e) { 091 if (JMapViewer.debug) { 092 System.err.println("(#9897) " + s + ": Button "+ e.getButton() + " Modifiers: " +Integer.toBinaryString(e.getModifiersEx())); 093 } 094 } 095 096 public void mouseWheelMoved(MouseWheelEvent e) { 097 if (wheelZoomEnabled) { 098 map.setZoom(map.getZoom() - e.getWheelRotation(), e.getPoint()); 099 } 100 } 101 102 public boolean isMovementEnabled() { 103 return movementEnabled; 104 } 105 106 /** 107 * Enables or disables that the map pane can be moved using the mouse. 108 * 109 * @param movementEnabled 110 */ 111 public void setMovementEnabled(boolean movementEnabled) { 112 this.movementEnabled = movementEnabled; 113 } 114 115 public int getMovementMouseButton() { 116 return movementMouseButton; 117 } 118 119 /** 120 * Sets the mouse button that is used for moving the map. Possible values 121 * are: 122 * <ul> 123 * <li>{@link MouseEvent#BUTTON1} (left mouse button)</li> 124 * <li>{@link MouseEvent#BUTTON2} (middle mouse button)</li> 125 * <li>{@link MouseEvent#BUTTON3} (right mouse button)</li> 126 * </ul> 127 * 128 * @param movementMouseButton 129 */ 130 public void setMovementMouseButton(int movementMouseButton) { 131 this.movementMouseButton = movementMouseButton; 132 switch (movementMouseButton) { 133 case MouseEvent.BUTTON1: 134 movementMouseButtonMask = MouseEvent.BUTTON1_DOWN_MASK; 135 break; 136 case MouseEvent.BUTTON2: 137 movementMouseButtonMask = MouseEvent.BUTTON2_DOWN_MASK; 138 break; 139 case MouseEvent.BUTTON3: 140 movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; 141 break; 142 default: 143 throw new RuntimeException("Unsupported button"); 144 } 145 } 146 147 public boolean isWheelZoomEnabled() { 148 return wheelZoomEnabled; 149 } 150 151 public void setWheelZoomEnabled(boolean wheelZoomEnabled) { 152 this.wheelZoomEnabled = wheelZoomEnabled; 153 } 154 155 public boolean isDoubleClickZoomEnabled() { 156 return doubleClickZoomEnabled; 157 } 158 159 public void setDoubleClickZoomEnabled(boolean doubleClickZoomEnabled) { 160 this.doubleClickZoomEnabled = doubleClickZoomEnabled; 161 } 162 163 public void mouseEntered(MouseEvent e) { 164 } 165 166 public void mouseExited(MouseEvent e) { 167 } 168 169 public void mouseMoved(MouseEvent e) { 170 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired. 171 // 172 if (isPlatformOsx()) { 173 if (!movementEnabled || !isMoving) 174 return; 175 // Is only the selected mouse button pressed? 176 if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) { 177 Point p = e.getPoint(); 178 if (lastDragPoint != null) { 179 int diffx = lastDragPoint.x - p.x; 180 int diffy = lastDragPoint.y - p.y; 181 map.moveMap(diffx, diffy); 182 } 183 lastDragPoint = p; 184 } 185 186 } 187 188 } 189 190 /** 191 * Replies true if we are currently running on OSX 192 * 193 * @return true if we are currently running on OSX 194 */ 195 public static boolean isPlatformOsx() { 196 String os = System.getProperty("os.name"); 197 return os != null && os.toLowerCase().startsWith("mac os x"); 198 } 199}