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 map.setZoom(map.getZoom() - e.getWheelRotation(), e.getPoint()); 086 } 087 } 088 089 public boolean isMovementEnabled() { 090 return movementEnabled; 091 } 092 093 /** 094 * Enables or disables that the map pane can be moved using the mouse. 095 * 096 * @param movementEnabled {@code true} to allow the map pane to be moved using the mouse 097 */ 098 public void setMovementEnabled(boolean movementEnabled) { 099 this.movementEnabled = movementEnabled; 100 } 101 102 public int getMovementMouseButton() { 103 return movementMouseButton; 104 } 105 106 /** 107 * Sets the mouse button that is used for moving the map. Possible values are: 108 * <ul> 109 * <li>{@link MouseEvent#BUTTON1} (left mouse button)</li> 110 * <li>{@link MouseEvent#BUTTON2} (middle mouse button)</li> 111 * <li>{@link MouseEvent#BUTTON3} (right mouse button)</li> 112 * </ul> 113 * 114 * @param movementMouseButton the mouse button that is used for moving the map 115 */ 116 public void setMovementMouseButton(int movementMouseButton) { 117 this.movementMouseButton = movementMouseButton; 118 switch (movementMouseButton) { 119 case MouseEvent.BUTTON1: 120 movementMouseButtonMask = MouseEvent.BUTTON1_DOWN_MASK; 121 break; 122 case MouseEvent.BUTTON2: 123 movementMouseButtonMask = MouseEvent.BUTTON2_DOWN_MASK; 124 break; 125 case MouseEvent.BUTTON3: 126 movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; 127 break; 128 default: 129 throw new RuntimeException("Unsupported button"); 130 } 131 } 132 133 public boolean isWheelZoomEnabled() { 134 return wheelZoomEnabled; 135 } 136 137 public void setWheelZoomEnabled(boolean wheelZoomEnabled) { 138 this.wheelZoomEnabled = wheelZoomEnabled; 139 } 140 141 public boolean isDoubleClickZoomEnabled() { 142 return doubleClickZoomEnabled; 143 } 144 145 public void setDoubleClickZoomEnabled(boolean doubleClickZoomEnabled) { 146 this.doubleClickZoomEnabled = doubleClickZoomEnabled; 147 } 148 149 @Override 150 public void mouseEntered(MouseEvent e) { 151 } 152 153 @Override 154 public void mouseExited(MouseEvent e) { 155 } 156 157 @Override 158 public void mouseMoved(MouseEvent e) { 159 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired. 160 // 161 if (isPlatformOsx()) { 162 if (!movementEnabled || !isMoving) 163 return; 164 // Is only the selected mouse button pressed? 165 if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) { 166 Point p = e.getPoint(); 167 if (lastDragPoint != null) { 168 int diffx = lastDragPoint.x - p.x; 169 int diffy = lastDragPoint.y - p.y; 170 map.moveMap(diffx, diffy); 171 } 172 lastDragPoint = p; 173 } 174 175 } 176 177 } 178 179 /** 180 * Replies true if we are currently running on OSX 181 * 182 * @return true if we are currently running on OSX 183 */ 184 public static boolean isPlatformOsx() { 185 String os = System.getProperty("os.name"); 186 return os != null && os.toLowerCase().startsWith("mac os x"); 187 } 188}