source: josm/trunk/src/org/openstreetmap/josm/actions/mapmode/MapMode.java@ 13891

Last change on this file since 13891 was 13847, checked in by Don-vip, 6 years ago

fix #16302 - IAE when switching map mode while offset dialog is open

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions.mapmode;
3
4import java.awt.Cursor;
5import java.awt.event.ActionEvent;
6import java.awt.event.InputEvent;
7import java.awt.event.MouseEvent;
8import java.awt.event.MouseListener;
9import java.awt.event.MouseMotionListener;
10import java.util.Collection;
11import java.util.Collections;
12
13import javax.swing.Action;
14
15import org.openstreetmap.josm.actions.JosmAction;
16import org.openstreetmap.josm.data.osm.OsmPrimitive;
17import org.openstreetmap.josm.gui.MainApplication;
18import org.openstreetmap.josm.gui.MapFrame;
19import org.openstreetmap.josm.gui.layer.Layer;
20import org.openstreetmap.josm.gui.layer.OsmDataLayer;
21import org.openstreetmap.josm.spi.preferences.Config;
22import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
23import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
24import org.openstreetmap.josm.tools.ImageProvider;
25import org.openstreetmap.josm.tools.Logging;
26import org.openstreetmap.josm.tools.Shortcut;
27
28/**
29 * A class implementing MapMode is able to be selected as an mode for map editing.
30 * As example scrolling the map is a MapMode, connecting Nodes to new Ways is another.
31 *
32 * MapModes should register/deregister all necessary listeners on the map's view control.
33 */
34public abstract class MapMode extends JosmAction implements MouseListener, MouseMotionListener, PreferenceChangedListener {
35 protected final Cursor cursor;
36 protected boolean ctrl;
37 protected boolean alt;
38 protected boolean shift;
39
40 /**
41 * Constructor for mapmodes without a menu
42 * @param name the action's text
43 * @param iconName icon filename in {@code mapmode} directory
44 * @param tooltip a longer description of the action that will be displayed in the tooltip.
45 * @param shortcut a ready-created shortcut object or null if you don't want a shortcut.
46 * @param cursor cursor displayed when map mode is active
47 * @since 11713
48 */
49 public MapMode(String name, String iconName, String tooltip, Shortcut shortcut, Cursor cursor) {
50 super(name, "mapmode/"+iconName, tooltip, shortcut, false);
51 this.cursor = cursor;
52 putValue("active", Boolean.FALSE);
53 }
54
55 /**
56 * Constructor for mapmodes with a menu (no shortcut will be registered)
57 * @param name the action's text
58 * @param iconName icon filename in {@code mapmode} directory
59 * @param tooltip a longer description of the action that will be displayed in the tooltip.
60 * @param cursor cursor displayed when map mode is active
61 * @since 11713
62 */
63 public MapMode(String name, String iconName, String tooltip, Cursor cursor) {
64 putValue(NAME, name);
65 new ImageProvider("mapmode", iconName).getResource().attachImageIcon(this);
66 putValue(SHORT_DESCRIPTION, tooltip);
67 this.cursor = cursor;
68 }
69
70 /**
71 * Makes this map mode active.
72 */
73 public void enterMode() {
74 Logging.debug("Entering map mode: {0}", getValue(Action.NAME));
75 putValue("active", Boolean.TRUE);
76 Config.getPref().addPreferenceChangeListener(this);
77 readPreferences();
78 MainApplication.getMap().mapView.setNewCursor(cursor, this);
79 updateStatusLine();
80 }
81
82 /**
83 * Makes this map mode inactive.
84 */
85 public void exitMode() {
86 Logging.debug("Exiting map mode: {0}", getValue(Action.NAME));
87 putValue("active", Boolean.FALSE);
88 Config.getPref().removePreferenceChangeListener(this);
89 MainApplication.getMap().mapView.resetCursor(this);
90 }
91
92 protected void updateStatusLine() {
93 MapFrame map = MainApplication.getMap();
94 if (map != null && map.statusLine != null) {
95 map.statusLine.setHelpText(getModeHelpText());
96 map.statusLine.repaint();
97 }
98 }
99
100 /**
101 * Returns a short translated help message describing how this map mode can be used, to be displayed in status line.
102 * @return a short translated help message describing how this map mode can be used
103 */
104 public String getModeHelpText() {
105 return "";
106 }
107
108 protected void readPreferences() {}
109
110 /**
111 * Call selectMapMode(this) on the parent mapFrame.
112 */
113 @Override
114 public void actionPerformed(ActionEvent e) {
115 if (MainApplication.isDisplayingMapView()) {
116 MainApplication.getMap().selectMapMode(this);
117 }
118 }
119
120 /**
121 * Determines if layer {@code l} is supported by this map mode.
122 * By default, all tools will work with all layers.
123 * Can be overwritten to require a special type of layer
124 * @param l layer
125 * @return {@code true} if the layer is supported by this map mode
126 */
127 public boolean layerIsSupported(Layer l) {
128 return l != null;
129 }
130
131 /**
132 * Update internal ctrl, alt, shift mask from given input event.
133 * @param e input event
134 */
135 protected void updateKeyModifiers(InputEvent e) {
136 updateKeyModifiersEx(e.getModifiersEx());
137 }
138
139 /**
140 * Update internal ctrl, alt, shift mask from given mouse event.
141 * @param e mouse event
142 */
143 protected void updateKeyModifiers(MouseEvent e) {
144 updateKeyModifiersEx(e.getModifiersEx());
145 }
146
147 /**
148 * Update internal ctrl, alt, shift mask from given action event.
149 * @param e action event
150 * @since 12526
151 */
152 protected void updateKeyModifiers(ActionEvent e) {
153 // ActionEvent does not have a getModifiersEx() method like other events :(
154 updateKeyModifiersEx(mapOldModifiers(e.getModifiers()));
155 }
156
157 /**
158 * Update internal ctrl, alt, shift mask from given extended modifiers mask.
159 * @param modifiers event extended modifiers mask
160 * @since 12517
161 */
162 protected void updateKeyModifiersEx(int modifiers) {
163 ctrl = (modifiers & InputEvent.CTRL_DOWN_MASK) != 0;
164 alt = (modifiers & (InputEvent.ALT_DOWN_MASK | InputEvent.ALT_GRAPH_DOWN_MASK)) != 0;
165 shift = (modifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
166 }
167
168 /**
169 * Map old (pre jdk 1.4) modifiers to extended modifiers (only for Ctrl, Alt, Shift).
170 * @param modifiers old modifiers
171 * @return extended modifiers
172 */
173 @SuppressWarnings("deprecation")
174 private static int mapOldModifiers(int modifiers) {
175 if ((modifiers & InputEvent.CTRL_MASK) != 0) {
176 modifiers |= InputEvent.CTRL_DOWN_MASK;
177 }
178 if ((modifiers & InputEvent.ALT_MASK) != 0) {
179 modifiers |= InputEvent.ALT_DOWN_MASK;
180 }
181 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
182 modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
183 }
184 if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
185 modifiers |= InputEvent.SHIFT_DOWN_MASK;
186 }
187
188 return modifiers;
189 }
190
191 protected void requestFocusInMapView() {
192 if (isEnabled()) {
193 // request focus in order to enable the expected keyboard shortcuts (see #8710)
194 MainApplication.getMap().mapView.requestFocus();
195 }
196 }
197
198 @Override
199 public void mouseReleased(MouseEvent e) {
200 requestFocusInMapView();
201 }
202
203 @Override
204 public void mouseExited(MouseEvent e) {
205 // Do nothing
206 }
207
208 @Override
209 public void mousePressed(MouseEvent e) {
210 requestFocusInMapView();
211 }
212
213 @Override
214 public void mouseClicked(MouseEvent e) {
215 // Do nothing
216 }
217
218 @Override
219 public void mouseEntered(MouseEvent e) {
220 // Do nothing
221 }
222
223 @Override
224 public void mouseMoved(MouseEvent e) {
225 // Do nothing
226 }
227
228 @Override
229 public void mouseDragged(MouseEvent e) {
230 // Do nothing
231 }
232
233 @Override
234 public void preferenceChanged(PreferenceChangeEvent e) {
235 readPreferences();
236 }
237
238 /**
239 * Gets a collection of primitives that should not be hidden by the filter.
240 * @return The primitives that the filter should not hide.
241 * @deprecated use {@link org.openstreetmap.josm.data.osm.DataSet#allPreservedPrimitives}
242 * @since 11993
243 */
244 @Deprecated
245 public Collection<? extends OsmPrimitive> getPreservedPrimitives() {
246 return Collections.emptySet();
247 }
248
249 /**
250 * Determines if the given layer is a data layer that can be modified.
251 * Useful for {@link #layerIsSupported(Layer)} implementations.
252 * @param l layer
253 * @return {@code true} if the given layer is a data layer that can be modified
254 * @since 13434
255 */
256 protected boolean isEditableDataLayer(Layer l) {
257 return l instanceof OsmDataLayer && !((OsmDataLayer) l).isLocked();
258 }
259}
Note: See TracBrowser for help on using the repository browser.