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 026 private Point lastDragPoint; 027 028 private boolean isMoving; 029 030 private boolean movementEnabled = true; 031 032 private int movementMouseButton = MouseEvent.BUTTON3; 033 private int movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; 034 035 private boolean wheelZoomEnabled = true; 036 private boolean doubleClickZoomEnabled = true; 037 038 public DefaultMapController(JMapViewer map) { 039 super(map); 040 } 041 042 @Override 043 public void mouseDragged(MouseEvent e) { 044 if (!movementEnabled || !isMoving) 045 return; 046 // Is only the selected mouse button pressed? 047 if ((e.getModifiersEx() & MOUSE_BUTTONS_MASK) == movementMouseButtonMask 048 || isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { 049 Point p = e.getPoint(); 050 if (lastDragPoint != null) { 051 int diffx = lastDragPoint.x - p.x; 052 int diffy = lastDragPoint.y - p.y; 053 map.moveMap(diffx, diffy); 054 } 055 lastDragPoint = p; 056 } 057 } 058 059 @Override 060 public void mouseClicked(MouseEvent e) { 061 if (doubleClickZoomEnabled && e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { 062 map.zoomIn(e.getPoint()); 063 } 064 } 065 066 @Override 067 public void mousePressed(MouseEvent e) { 068 if (e.getButton() == movementMouseButton || isPlatformOsx() && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { 069 lastDragPoint = null; 070 isMoving = true; 071 } 072 } 073 074 @Override 075 public void mouseReleased(MouseEvent e) { 076 if (e.getButton() == movementMouseButton || isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1) { 077 lastDragPoint = null; 078 isMoving = false; 079 } 080 } 081 082 @Override 083 public void mouseWheelMoved(MouseWheelEvent e) { 084 if (wheelZoomEnabled) { 085 int rotation = JMapViewer.zoomReverseWheel ? -e.getWheelRotation() : e.getWheelRotation(); 086 map.setZoom(map.getZoom() - rotation, e.getPoint()); 087 } 088 } 089 090 public boolean isMovementEnabled() { 091 return movementEnabled; 092 } 093 094 /** 095 * Enables or disables that the map pane can be moved using the mouse. 096 * 097 * @param movementEnabled {@code true} to allow the map pane to be moved using the mouse 098 */ 099 public void setMovementEnabled(boolean movementEnabled) { 100 this.movementEnabled = movementEnabled; 101 } 102 103 public int getMovementMouseButton() { 104 return movementMouseButton; 105 } 106 107 /** 108 * Sets the mouse button that is used for moving the map. Possible values are: 109 * <ul> 110 * <li>{@link MouseEvent#BUTTON1} (left mouse button)</li> 111 * <li>{@link MouseEvent#BUTTON2} (middle mouse button)</li> 112 * <li>{@link MouseEvent#BUTTON3} (right mouse button)</li> 113 * </ul> 114 * 115 * @param movementMouseButton the mouse button that is used for moving the map 116 */ 117 public void setMovementMouseButton(int movementMouseButton) { 118 this.movementMouseButton = movementMouseButton; 119 switch (movementMouseButton) { 120 case MouseEvent.BUTTON1: 121 movementMouseButtonMask = MouseEvent.BUTTON1_DOWN_MASK; 122 break; 123 case MouseEvent.BUTTON2: 124 movementMouseButtonMask = MouseEvent.BUTTON2_DOWN_MASK; 125 break; 126 case MouseEvent.BUTTON3: 127 movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; 128 break; 129 default: 130 throw new RuntimeException("Unsupported button"); 131 } 132 } 133 134 public boolean isWheelZoomEnabled() { 135 return wheelZoomEnabled; 136 } 137 138 public void setWheelZoomEnabled(boolean wheelZoomEnabled) { 139 this.wheelZoomEnabled = wheelZoomEnabled; 140 } 141 142 public boolean isDoubleClickZoomEnabled() { 143 return doubleClickZoomEnabled; 144 } 145 146 public void setDoubleClickZoomEnabled(boolean doubleClickZoomEnabled) { 147 this.doubleClickZoomEnabled = doubleClickZoomEnabled; 148 } 149 150 @Override 151 public void mouseEntered(MouseEvent e) { 152 } 153 154 @Override 155 public void mouseExited(MouseEvent e) { 156 } 157 158 @Override 159 public void mouseMoved(MouseEvent e) { 160 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired. 161 // 162 if (isPlatformOsx()) { 163 if (!movementEnabled || !isMoving) 164 return; 165 // Is only the selected mouse button pressed? 166 if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) { 167 Point p = e.getPoint(); 168 if (lastDragPoint != null) { 169 int diffx = lastDragPoint.x - p.x; 170 int diffy = lastDragPoint.y - p.y; 171 map.moveMap(diffx, diffy); 172 } 173 lastDragPoint = p; 174 } 175 176 } 177 178 } 179 180 /** 181 * Replies true if we are currently running on OSX 182 * 183 * @return true if we are currently running on OSX 184 */ 185 public static boolean isPlatformOsx() { 186 String os = System.getProperty("os.name"); 187 return os != null && os.toLowerCase().startsWith("mac os x"); 188 } 189}