001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.mapmode; 003 004import java.awt.Cursor; 005import java.awt.event.ActionEvent; 006import java.awt.event.InputEvent; 007import java.awt.event.MouseEvent; 008import java.awt.event.MouseListener; 009import java.awt.event.MouseMotionListener; 010 011import org.openstreetmap.josm.Main; 012import org.openstreetmap.josm.actions.JosmAction; 013import org.openstreetmap.josm.gui.MapFrame; 014import org.openstreetmap.josm.gui.layer.Layer; 015import org.openstreetmap.josm.tools.ImageProvider; 016import org.openstreetmap.josm.tools.Shortcut; 017import org.openstreetmap.josm.data.Preferences.PreferenceChangeEvent; 018import org.openstreetmap.josm.data.Preferences.PreferenceChangedListener; 019 020/** 021 * A class implementing MapMode is able to be selected as an mode for map editing. 022 * As example scrolling the map is a MapMode, connecting Nodes to new Ways is another. 023 * 024 * MapModes should register/deregister all necessary listeners on the map's view control. 025 */ 026public abstract class MapMode extends JosmAction implements MouseListener, MouseMotionListener, PreferenceChangedListener { 027 protected final Cursor cursor; 028 protected boolean ctrl; 029 protected boolean alt; 030 protected boolean shift; 031 032 /** 033 * Constructor for mapmodes without a menu 034 * @param name the action's text 035 * @param iconName icon filename in {@code mapmode} directory 036 * @param tooltip a longer description of the action that will be displayed in the tooltip. 037 * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. 038 * @param mapFrame unused but kept for plugin compatibility. Can be {@code null} 039 * @param cursor cursor displayed when map mode is active 040 */ 041 public MapMode(String name, String iconName, String tooltip, Shortcut shortcut, MapFrame mapFrame, Cursor cursor) { 042 super(name, "mapmode/"+iconName, tooltip, shortcut, false); 043 this.cursor = cursor; 044 putValue("active", Boolean.FALSE); 045 } 046 047 /** 048 * Constructor for mapmodes with a menu (no shortcut will be registered) 049 * @param name the action's text 050 * @param iconName icon filename in {@code mapmode} directory 051 * @param tooltip a longer description of the action that will be displayed in the tooltip. 052 * @param mapFrame unused but kept for plugin compatibility. Can be {@code null} 053 * @param cursor cursor displayed when map mode is active 054 */ 055 public MapMode(String name, String iconName, String tooltip, MapFrame mapFrame, Cursor cursor) { 056 putValue(NAME, name); 057 putValue(SMALL_ICON, ImageProvider.get("mapmode", iconName)); 058 putValue(SHORT_DESCRIPTION, tooltip); 059 this.cursor = cursor; 060 } 061 062 /** 063 * Makes this map mode active. 064 */ 065 public void enterMode() { 066 putValue("active", Boolean.TRUE); 067 Main.pref.addPreferenceChangeListener(this); 068 readPreferences(); 069 Main.map.mapView.setNewCursor(cursor, this); 070 updateStatusLine(); 071 } 072 073 /** 074 * Makes this map mode inactive. 075 */ 076 public void exitMode() { 077 putValue("active", Boolean.FALSE); 078 Main.pref.removePreferenceChangeListener(this); 079 Main.map.mapView.resetCursor(this); 080 } 081 082 protected void updateStatusLine() { 083 Main.map.statusLine.setHelpText(getModeHelpText()); 084 Main.map.statusLine.repaint(); 085 } 086 087 public String getModeHelpText() { 088 return ""; 089 } 090 091 protected void readPreferences() {} 092 093 /** 094 * Call selectMapMode(this) on the parent mapFrame. 095 */ 096 @Override 097 public void actionPerformed(ActionEvent e) { 098 if (Main.isDisplayingMapView()) { 099 Main.map.selectMapMode(this); 100 } 101 } 102 103 /** 104 * Determines if layer {@code l} is supported by this map mode. 105 * By default, all tools will work with all layers. 106 * Can be overwritten to require a special type of layer 107 * @param l layer 108 * @return {@code true} if the layer is supported by this map mode 109 */ 110 public boolean layerIsSupported(Layer l) { 111 return l != null; 112 } 113 114 protected void updateKeyModifiers(InputEvent e) { 115 updateKeyModifiers(e.getModifiers()); 116 } 117 118 protected void updateKeyModifiers(MouseEvent e) { 119 updateKeyModifiers(e.getModifiers()); 120 } 121 122 protected void updateKeyModifiers(int modifiers) { 123 ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0; 124 alt = (modifiers & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0; 125 shift = (modifiers & ActionEvent.SHIFT_MASK) != 0; 126 } 127 128 protected void requestFocusInMapView() { 129 if (isEnabled()) { 130 // request focus in order to enable the expected keyboard shortcuts (see #8710) 131 Main.map.mapView.requestFocus(); 132 } 133 } 134 135 @Override 136 public void mouseReleased(MouseEvent e) { 137 requestFocusInMapView(); 138 } 139 140 @Override 141 public void mouseExited(MouseEvent e) { 142 // Do nothing 143 } 144 145 @Override 146 public void mousePressed(MouseEvent e) { 147 requestFocusInMapView(); 148 } 149 150 @Override 151 public void mouseClicked(MouseEvent e) { 152 // Do nothing 153 } 154 155 @Override 156 public void mouseEntered(MouseEvent e) { 157 // Do nothing 158 } 159 160 @Override 161 public void mouseMoved(MouseEvent e) { 162 // Do nothing 163 } 164 165 @Override 166 public void mouseDragged(MouseEvent e) { 167 // Do nothing 168 } 169 170 @Override 171 public void preferenceChanged(PreferenceChangeEvent e) { 172 readPreferences(); 173 } 174}