source: josm/trunk/src/org/openstreetmap/josm/actions/ImageryAdjustAction.java

Last change on this file was 18211, checked in by Don-vip, 3 years ago

global use of !Utils.isEmpty/isBlank

  • Property svn:eol-style set to native
File size: 13.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.AWTEvent;
7import java.awt.Cursor;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
10import java.awt.Toolkit;
11import java.awt.event.AWTEventListener;
12import java.awt.event.ActionEvent;
13import java.awt.event.FocusEvent;
14import java.awt.event.FocusListener;
15import java.awt.event.KeyEvent;
16import java.awt.event.MouseEvent;
17import java.util.Locale;
18
19import javax.swing.JLabel;
20import javax.swing.JPanel;
21
22import org.openstreetmap.josm.actions.mapmode.MapMode;
23import org.openstreetmap.josm.data.coor.EastNorth;
24import org.openstreetmap.josm.data.coor.LatLon;
25import org.openstreetmap.josm.data.imagery.OffsetBookmark;
26import org.openstreetmap.josm.data.projection.ProjectionRegistry;
27import org.openstreetmap.josm.gui.ExtendedDialog;
28import org.openstreetmap.josm.gui.MainApplication;
29import org.openstreetmap.josm.gui.MapFrame;
30import org.openstreetmap.josm.gui.MapView;
31import org.openstreetmap.josm.gui.layer.AbstractTileSourceLayer;
32import org.openstreetmap.josm.gui.util.WindowGeometry;
33import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
34import org.openstreetmap.josm.gui.widgets.JosmTextField;
35import org.openstreetmap.josm.tools.GBC;
36import org.openstreetmap.josm.tools.ImageProvider;
37import org.openstreetmap.josm.tools.JosmDecimalFormatSymbolsProvider;
38import org.openstreetmap.josm.tools.Logging;
39import org.openstreetmap.josm.tools.Utils;
40
41/**
42 * Adjust the position of an imagery layer.
43 * @since 3715
44 */
45public class ImageryAdjustAction extends MapMode implements AWTEventListener {
46 private static ImageryOffsetDialog offsetDialog;
47
48 private transient OffsetBookmark old;
49 private transient OffsetBookmark tempOffset;
50 private EastNorth prevEastNorth;
51 private transient AbstractTileSourceLayer<?> layer;
52 private MapMode oldMapMode;
53 private boolean exitingMode;
54 private boolean restoreOldMode;
55
56 /**
57 * Constructs a new {@code ImageryAdjustAction} for the given layer.
58 * @param layer The imagery layer
59 */
60 public ImageryAdjustAction(AbstractTileSourceLayer<?> layer) {
61 super(tr("New offset"), "adjustimg", tr("Adjust the position of this imagery layer"),
62 ImageProvider.getCursor("normal", "move"));
63 putValue("toolbar", Boolean.FALSE);
64 this.layer = layer;
65 }
66
67 @Override
68 public void enterMode() {
69 super.enterMode();
70 if (layer == null)
71 return;
72 if (!layer.isVisible()) {
73 layer.setVisible(true);
74 }
75 old = layer.getDisplaySettings().getOffsetBookmark();
76 EastNorth curOff = old == null ? EastNorth.ZERO : old.getDisplacement(ProjectionRegistry.getProjection());
77 LatLon center;
78 if (MainApplication.isDisplayingMapView()) {
79 center = ProjectionRegistry.getProjection().eastNorth2latlon(MainApplication.getMap().mapView.getCenter());
80 } else {
81 center = LatLon.ZERO;
82 }
83 tempOffset = new OffsetBookmark(
84 ProjectionRegistry.getProjection().toCode(),
85 layer.getInfo().getId(),
86 layer.getInfo().getName(),
87 null,
88 curOff, center);
89 layer.getDisplaySettings().setOffsetBookmark(tempOffset);
90 addListeners();
91 showOffsetDialog(new ImageryOffsetDialog());
92 }
93
94 private static void showOffsetDialog(ImageryOffsetDialog dlg) {
95 offsetDialog = dlg;
96 offsetDialog.setVisible(true);
97 }
98
99 private static void hideOffsetDialog() {
100 offsetDialog.setVisible(false);
101 offsetDialog = null;
102 }
103
104 protected void addListeners() {
105 MapView mapView = MainApplication.getMap().mapView;
106 mapView.addMouseListener(this);
107 mapView.addMouseMotionListener(this);
108 try {
109 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
110 } catch (SecurityException ex) {
111 Logging.error(ex);
112 }
113 }
114
115 @Override
116 public void exitMode() {
117 // do not restore old mode here - this is called when the new mode is already known.
118 restoreOldMode = false;
119 doExitMode();
120 }
121
122 private void doExitMode() {
123 exitingMode = true;
124 try {
125 super.exitMode();
126 } catch (IllegalArgumentException e) {
127 Logging.trace(e);
128 }
129 if (offsetDialog != null) {
130 if (layer != null) {
131 layer.getDisplaySettings().setOffsetBookmark(old);
132 }
133 hideOffsetDialog();
134 }
135 removeListeners();
136 exitingMode = false;
137 }
138
139 protected void removeListeners() {
140 try {
141 Toolkit.getDefaultToolkit().removeAWTEventListener(this);
142 } catch (SecurityException ex) {
143 Logging.error(ex);
144 }
145 if (MainApplication.isDisplayingMapView()) {
146 MapFrame map = MainApplication.getMap();
147 map.mapView.removeMouseMotionListener(this);
148 map.mapView.removeMouseListener(this);
149 }
150 }
151
152 @Override
153 public void eventDispatched(AWTEvent event) {
154 if (!(event instanceof KeyEvent)
155 || (event.getID() != KeyEvent.KEY_PRESSED)
156 || (layer == null)
157 || (offsetDialog != null && offsetDialog.areFieldsInFocus())) {
158 return;
159 }
160 KeyEvent kev = (KeyEvent) event;
161 int dx = 0;
162 int dy = 0;
163 switch (kev.getKeyCode()) {
164 case KeyEvent.VK_UP : dy = +1; break;
165 case KeyEvent.VK_DOWN : dy = -1; break;
166 case KeyEvent.VK_LEFT : dx = -1; break;
167 case KeyEvent.VK_RIGHT : dx = +1; break;
168 case KeyEvent.VK_ESCAPE:
169 if (offsetDialog != null) {
170 restoreOldMode = true;
171 offsetDialog.setVisible(false);
172 return;
173 }
174 break;
175 default: // Do nothing
176 }
177 if (dx != 0 || dy != 0) {
178 double ppd = layer.getPPD();
179 EastNorth d = tempOffset.getDisplacement().add(new EastNorth(dx / ppd, dy / ppd));
180 tempOffset.setDisplacement(d);
181 layer.getDisplaySettings().setOffsetBookmark(tempOffset);
182 if (offsetDialog != null) {
183 offsetDialog.updateOffset();
184 }
185 if (Logging.isDebugEnabled()) {
186 Logging.debug("{0} consuming event {1}", getClass().getName(), kev);
187 }
188 kev.consume();
189 }
190 }
191
192 @Override
193 public void mousePressed(MouseEvent e) {
194 if (e.getButton() != MouseEvent.BUTTON1)
195 return;
196
197 if (layer.isVisible()) {
198 requestFocusInMapView();
199 MapView mapView = MainApplication.getMap().mapView;
200 prevEastNorth = mapView.getEastNorth(e.getX(), e.getY());
201 mapView.setNewCursor(Cursor.MOVE_CURSOR, this);
202 }
203 }
204
205 @Override
206 public void mouseDragged(MouseEvent e) {
207 if (layer == null || prevEastNorth == null) return;
208 EastNorth eastNorth = MainApplication.getMap().mapView.getEastNorth(e.getX(), e.getY());
209 EastNorth d = tempOffset.getDisplacement().add(eastNorth).subtract(prevEastNorth);
210 tempOffset.setDisplacement(d);
211 layer.getDisplaySettings().setOffsetBookmark(tempOffset);
212 if (offsetDialog != null) {
213 offsetDialog.updateOffset();
214 }
215 prevEastNorth = eastNorth;
216 }
217
218 @Override
219 public void mouseReleased(MouseEvent e) {
220 MapView mapView = MainApplication.getMap().mapView;
221 mapView.repaint();
222 mapView.resetCursor(this);
223 prevEastNorth = null;
224 }
225
226 @Override
227 public void actionPerformed(ActionEvent e) {
228 MapFrame map = MainApplication.getMap();
229 if (offsetDialog != null || layer == null || map == null)
230 return;
231 oldMapMode = map.mapMode;
232 super.actionPerformed(e);
233 }
234
235 private static final class ConfirmOverwriteBookmarkDialog extends ExtendedDialog {
236 ConfirmOverwriteBookmarkDialog() {
237 super(MainApplication.getMainFrame(), tr("Overwrite"), tr("Overwrite"), tr("Cancel"));
238 contentInsets = new Insets(10, 15, 10, 15);
239 setContent(tr("Offset bookmark already exists. Overwrite?"));
240 setButtonIcons("ok", "cancel");
241 }
242 }
243
244 private class ImageryOffsetDialog extends ExtendedDialog implements FocusListener {
245 private final JosmTextField tOffset = new JosmTextField();
246 private final JosmTextField tBookmarkName = new JosmTextField();
247 private boolean ignoreListener;
248
249 /**
250 * Constructs a new {@code ImageryOffsetDialog}.
251 */
252 ImageryOffsetDialog() {
253 super(MainApplication.getMainFrame(),
254 tr("Adjust imagery offset"),
255 new String[] {tr("OK"), tr("Cancel")},
256 false, false); // Do not dispose on close, so HIDE_ON_CLOSE remains the default behaviour and setVisible is called
257 setButtonIcons("ok", "cancel");
258 configureContextsensitiveHelp("Action/ImageryAdjust", true);
259 contentInsets = new Insets(10, 15, 5, 15);
260 JPanel pnl = new JPanel(new GridBagLayout());
261 pnl.add(new JMultilineLabel(tr("Use arrow keys or drag the imagery layer with mouse to adjust the imagery offset.\n" +
262 "You can also enter east and north offset in the {0} coordinates.\n" +
263 "If you want to save the offset as bookmark, enter the bookmark name below",
264 ProjectionRegistry.getProjection().toString())), GBC.eop());
265 pnl.add(new JLabel(tr("Offset:")), GBC.std());
266 pnl.add(tOffset, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5));
267 pnl.add(new JLabel(tr("Bookmark name: ")), GBC.std());
268 pnl.add(tBookmarkName, GBC.eol().fill(GBC.HORIZONTAL));
269 tOffset.setColumns(16);
270 updateOffsetIntl();
271 tOffset.addFocusListener(this);
272 setContent(pnl);
273 setupDialog();
274 setRememberWindowGeometry(getClass().getName() + ".geometry",
275 WindowGeometry.centerInWindow(MainApplication.getMainFrame(), getSize()));
276 }
277
278 private boolean areFieldsInFocus() {
279 return tOffset.hasFocus();
280 }
281
282 @Override
283 public void focusGained(FocusEvent e) {
284 // Do nothing
285 }
286
287 @Override
288 public void focusLost(FocusEvent e) {
289 if (ignoreListener) return;
290 String ostr = tOffset.getText();
291 int semicolon = ostr.indexOf(';');
292 if (layer != null && semicolon >= 0 && semicolon + 1 < ostr.length()) {
293 try {
294 String easting = ostr.substring(0, semicolon).trim();
295 String northing = ostr.substring(semicolon + 1).trim();
296 double dx = JosmDecimalFormatSymbolsProvider.parseDouble(easting);
297 double dy = JosmDecimalFormatSymbolsProvider.parseDouble(northing);
298 tempOffset.setDisplacement(new EastNorth(dx, dy));
299 layer.getDisplaySettings().setOffsetBookmark(tempOffset);
300 } catch (NumberFormatException nfe) {
301 // we repaint offset numbers in any case
302 Logging.trace(nfe);
303 }
304 }
305 updateOffsetIntl();
306 if (layer != null) {
307 layer.invalidate();
308 }
309 }
310
311 private void updateOffset() {
312 ignoreListener = true;
313 updateOffsetIntl();
314 ignoreListener = false;
315 }
316
317 private void updateOffsetIntl() {
318 if (layer != null) {
319 // ROOT locale to force decimal separator to be '.'
320 tOffset.setText(layer.getDisplaySettings().getDisplacementString(Locale.ROOT));
321 }
322 }
323
324 private boolean confirmOverwriteBookmark() {
325 return new ConfirmOverwriteBookmarkDialog().showDialog().getValue() == 1;
326 }
327
328 @Override
329 protected void buttonAction(int buttonIndex, ActionEvent evt) {
330 restoreOldMode = true;
331 if (buttonIndex == 0 && !Utils.isEmpty(tBookmarkName.getText()) &&
332 OffsetBookmark.getBookmarkByName(layer, tBookmarkName.getText()) != null &&
333 !confirmOverwriteBookmark()) {
334 return;
335 }
336 super.buttonAction(buttonIndex, evt);
337 }
338
339 @Override
340 public void setVisible(boolean visible) {
341 super.setVisible(visible);
342 if (visible)
343 return;
344 ignoreListener = true;
345 offsetDialog = null;
346 if (layer != null) {
347 if (getValue() != 1) {
348 layer.getDisplaySettings().setOffsetBookmark(old);
349 } else if (!Utils.isEmpty(tBookmarkName.getText())) {
350 OffsetBookmark.bookmarkOffset(tBookmarkName.getText(), layer);
351 }
352 }
353 MainApplication.getMenu().imageryMenu.refreshOffsetMenu();
354 restoreMapModeState();
355 }
356
357 private void restoreMapModeState() {
358 MapFrame map = MainApplication.getMap();
359 if (map == null)
360 return;
361 if (oldMapMode != null) {
362 if (restoreOldMode || (!exitingMode && getValue() == ExtendedDialog.DialogClosedOtherwise)) {
363 map.selectMapMode(oldMapMode);
364 }
365 oldMapMode = null;
366 } else if (!exitingMode && !map.selectSelectTool(false)) {
367 exitModeAndRestoreOldMode();
368 map.mapMode = null;
369 }
370 }
371
372 private void exitModeAndRestoreOldMode() {
373 restoreOldMode = true;
374 doExitMode();
375 restoreOldMode = false;
376 }
377 }
378
379 @Override
380 public void destroy() {
381 super.destroy();
382 removeListeners();
383 this.layer = null;
384 this.oldMapMode = null;
385 }
386}
Note: See TracBrowser for help on using the repository browser.