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

Last change on this file since 8978 was 8846, checked in by Don-vip, 9 years ago

sonar - fb-contrib - minor performance improvements:

  • Method passes constant String of length 1 to character overridden method
  • Method needlessly boxes a boolean constant
  • Method uses iterator().next() on a List to get the first item
  • Method converts String to boxed primitive using excessive boxing
  • Method converts String to primitive using excessive boxing
  • Method creates array using constants
  • Class defines List based fields but uses them like Sets
  • Property svn:eol-style set to native
File size: 11.4 KB
RevLine 
[3719]1// License: GPL. For details, see LICENSE file.
[3715]2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
[3722]6import java.awt.AWTEvent;
[3715]7import java.awt.Cursor;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
[3722]10import java.awt.Toolkit;
11import java.awt.event.AWTEventListener;
[3715]12import java.awt.event.ActionEvent;
[3948]13import java.awt.event.FocusEvent;
14import java.awt.event.FocusListener;
[3722]15import java.awt.event.KeyEvent;
[3715]16import java.awt.event.MouseEvent;
17import java.awt.event.MouseListener;
18import java.awt.event.MouseMotionListener;
[8152]19import java.awt.event.WindowAdapter;
20import java.awt.event.WindowEvent;
[7033]21import java.util.Formatter;
22import java.util.Locale;
[3715]23
24import javax.swing.JLabel;
25import javax.swing.JPanel;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.actions.mapmode.MapMode;
29import org.openstreetmap.josm.data.coor.EastNorth;
30import org.openstreetmap.josm.data.imagery.OffsetBookmark;
31import org.openstreetmap.josm.gui.ExtendedDialog;
32import org.openstreetmap.josm.gui.layer.ImageryLayer;
[6792]33import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
34import org.openstreetmap.josm.gui.widgets.JosmTextField;
[3715]35import org.openstreetmap.josm.tools.GBC;
36import org.openstreetmap.josm.tools.ImageProvider;
37
[7859]38/**
39 * Adjust the position of an imagery layer.
40 * @since 3715
41 */
[3722]42public class ImageryAdjustAction extends MapMode implements MouseListener, MouseMotionListener, AWTEventListener{
[8126]43 private static volatile ImageryOffsetDialog offsetDialog;
[7859]44 private static Cursor cursor = ImageProvider.getCursor("normal", "move");
[3715]45
[7859]46 private double oldDx, oldDy;
47 private EastNorth prevEastNorth;
[8308]48 private transient ImageryLayer layer;
[3715]49 private MapMode oldMapMode;
50
[6792]51 /**
52 * Constructs a new {@code ImageryAdjustAction} for the given layer.
53 * @param layer The imagery layer
54 */
[3715]55 public ImageryAdjustAction(ImageryLayer layer) {
56 super(tr("New offset"), "adjustimg",
57 tr("Adjust the position of this imagery layer"), Main.map,
58 cursor);
[8377]59 putValue("toolbar", Boolean.FALSE);
[3715]60 this.layer = layer;
61 }
62
[6792]63 @Override
64 public void enterMode() {
[3715]65 super.enterMode();
66 if (layer == null)
67 return;
68 if (!layer.isVisible()) {
69 layer.setVisible(true);
70 }
[6107]71 oldDx = layer.getDx();
72 oldDy = layer.getDy();
73 addListeners();
74 offsetDialog = new ImageryOffsetDialog();
75 offsetDialog.setVisible(true);
76 }
[6792]77
[6107]78 protected void addListeners() {
[3715]79 Main.map.mapView.addMouseListener(this);
80 Main.map.mapView.addMouseMotionListener(this);
[3722]81 try {
82 Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
83 } catch (SecurityException ex) {
[6792]84 Main.error(ex);
[3722]85 }
[3715]86 }
87
[6792]88 @Override
89 public void exitMode() {
[3715]90 super.exitMode();
91 if (offsetDialog != null) {
[7350]92 if (layer != null) {
93 layer.setOffset(oldDx, oldDy);
94 }
[3715]95 offsetDialog.setVisible(false);
96 offsetDialog = null;
97 }
[6107]98 removeListeners();
99 }
[6792]100
[6107]101 protected void removeListeners() {
[3722]102 try {
103 Toolkit.getDefaultToolkit().removeAWTEventListener(this);
104 } catch (SecurityException ex) {
[6792]105 Main.error(ex);
[3722]106 }
[6107]107 if (Main.isDisplayingMapView()) {
108 Main.map.mapView.removeMouseMotionListener(this);
109 Main.map.mapView.removeMouseListener(this);
110 }
[3715]111 }
112
[3722]113 @Override
114 public void eventDispatched(AWTEvent event) {
[7859]115 if (!(event instanceof KeyEvent)
116 || (event.getID() != KeyEvent.KEY_PRESSED)
117 || (layer == null)
118 || (offsetDialog != null && offsetDialog.areFieldsInFocus())) {
119 return;
120 }
[8510]121 KeyEvent kev = (KeyEvent) event;
[7859]122 int dx = 0, dy = 0;
[3722]123 switch (kev.getKeyCode()) {
124 case KeyEvent.VK_UP : dy = +1; break;
125 case KeyEvent.VK_DOWN : dy = -1; break;
126 case KeyEvent.VK_LEFT : dx = -1; break;
127 case KeyEvent.VK_RIGHT : dx = +1; break;
128 }
129 if (dx != 0 || dy != 0) {
130 double ppd = layer.getPPD();
131 layer.displace(dx / ppd, dy / ppd);
132 if (offsetDialog != null) {
133 offsetDialog.updateOffset();
134 }
[8441]135 if (Main.isDebugEnabled()) {
136 Main.debug(getClass().getName()+" consuming event "+kev);
137 }
[3722]138 kev.consume();
139 Main.map.repaint();
140 }
141 }
142
[6792]143 @Override
144 public void mousePressed(MouseEvent e) {
[3715]145 if (e.getButton() != MouseEvent.BUTTON1)
146 return;
147
148 if (layer.isVisible()) {
[5962]149 requestFocusInMapView();
[8510]150 prevEastNorth = Main.map.mapView.getEastNorth(e.getX(), e.getY());
[3919]151 Main.map.mapView.setNewCursor(Cursor.MOVE_CURSOR, this);
[3715]152 }
153 }
154
[6792]155 @Override
156 public void mouseDragged(MouseEvent e) {
[3715]157 if (layer == null || prevEastNorth == null) return;
158 EastNorth eastNorth =
[8510]159 Main.map.mapView.getEastNorth(e.getX(), e.getY());
[3715]160 double dx = layer.getDx()+eastNorth.east()-prevEastNorth.east();
161 double dy = layer.getDy()+eastNorth.north()-prevEastNorth.north();
162 layer.setOffset(dx, dy);
163 if (offsetDialog != null) {
164 offsetDialog.updateOffset();
165 }
166 Main.map.repaint();
167 prevEastNorth = eastNorth;
168 }
169
[6792]170 @Override
171 public void mouseReleased(MouseEvent e) {
[3715]172 Main.map.mapView.repaint();
[3919]173 Main.map.mapView.resetCursor(this);
[3715]174 prevEastNorth = null;
175 }
176
177 @Override
178 public void actionPerformed(ActionEvent e) {
179 if (offsetDialog != null || layer == null || Main.map == null)
180 return;
181 oldMapMode = Main.map.mapMode;
182 super.actionPerformed(e);
183 }
184
[7859]185 private class ImageryOffsetDialog extends ExtendedDialog implements FocusListener {
186 private final JosmTextField tOffset = new JosmTextField();
187 private final JosmTextField tBookmarkName = new JosmTextField();
[3715]188 private boolean ignoreListener;
[7859]189
190 /**
191 * Constructs a new {@code ImageryOffsetDialog}.
192 */
[8836]193 ImageryOffsetDialog() {
[3715]194 super(Main.parent,
195 tr("Adjust imagery offset"),
[8510]196 new String[] {tr("OK"), tr("Cancel")},
[3715]197 false);
[8443]198 setButtonIcons(new String[] {"ok", "cancel"});
[3722]199 contentInsets = new Insets(10, 15, 5, 15);
200 JPanel pnl = new JPanel(new GridBagLayout());
201 pnl.add(new JMultilineLabel(tr("Use arrow keys or drag the imagery layer with mouse to adjust the imagery offset.\n" +
202 "You can also enter east and north offset in the {0} coordinates.\n" +
[7859]203 "If you want to save the offset as bookmark, enter the bookmark name below",
204 Main.getProjection().toString())), GBC.eop());
[8510]205 pnl.add(new JLabel(tr("Offset: ")), GBC.std());
206 pnl.add(tOffset, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 0, 5));
207 pnl.add(new JLabel(tr("Bookmark name: ")), GBC.std());
208 pnl.add(tBookmarkName, GBC.eol().fill(GBC.HORIZONTAL));
[4001]209 tOffset.setColumns(16);
210 updateOffsetIntl();
211 tOffset.addFocusListener(this);
[3715]212 setContent(pnl);
213 setupDialog();
[8152]214 addWindowListener(new WindowEventHandler());
[3715]215 }
216
[7859]217 private boolean areFieldsInFocus() {
[4001]218 return tOffset.hasFocus();
219 }
220
[3715]221 @Override
[3948]222 public void focusGained(FocusEvent e) {
[7859]223 // Do nothing
[3948]224 }
225
226 @Override
227 public void focusLost(FocusEvent e) {
[3715]228 if (ignoreListener) return;
[4001]229 String ostr = tOffset.getText();
230 int semicolon = ostr.indexOf(';');
[8443]231 if (semicolon >= 0 && semicolon + 1 < ostr.length()) {
[4001]232 try {
233 // here we assume that Double.parseDouble() needs '.' as a decimal separator
234 String easting = ostr.substring(0, semicolon).trim().replace(',', '.');
235 String northing = ostr.substring(semicolon + 1).trim().replace(',', '.');
236 double dx = Double.parseDouble(easting);
237 double dy = Double.parseDouble(northing);
238 layer.setOffset(dx, dy);
239 } catch (NumberFormatException nfe) {
240 // we repaint offset numbers in any case
[8513]241 if (Main.isTraceEnabled()) {
242 Main.trace(nfe.getMessage());
243 }
[4001]244 }
[3948]245 }
[4001]246 updateOffsetIntl();
[5460]247 if (Main.isDisplayingMapView()) {
[4845]248 Main.map.repaint();
249 }
[3715]250 }
251
[8512]252 private void updateOffset() {
[3715]253 ignoreListener = true;
[4001]254 updateOffsetIntl();
[3715]255 ignoreListener = false;
256 }
257
[8512]258 private void updateOffsetIntl() {
[4001]259 // Support projections with very small numbers (e.g. 4326)
[4126]260 int precision = Main.getProjection().getDefaultZoomInPPD() >= 1.0 ? 2 : 7;
[4001]261 // US locale to force decimal separator to be '.'
[7033]262 try (Formatter us = new Formatter(Locale.US)) {
263 tOffset.setText(us.format(
[8846]264 "%1." + precision + "f; %1." + precision + 'f',
[4001]265 layer.getDx(), layer.getDy()).toString());
[7033]266 }
[4001]267 }
268
[3734]269 private boolean confirmOverwriteBookmark() {
270 ExtendedDialog dialog = new ExtendedDialog(
271 Main.parent,
272 tr("Overwrite"),
273 new String[] {tr("Overwrite"), tr("Cancel")}
[8510]274 ) { {
[3734]275 contentInsets = new Insets(10, 15, 10, 15);
[8510]276 } };
[3734]277 dialog.setContent(tr("Offset bookmark already exists. Overwrite?"));
278 dialog.setButtonIcons(new String[] {"ok.png", "cancel.png"});
279 dialog.setupDialog();
280 dialog.setVisible(true);
281 return dialog.getValue() == 1;
282 }
283
[3715]284 @Override
285 protected void buttonAction(int buttonIndex, ActionEvent evt) {
[6087]286 if (buttonIndex == 0 && tBookmarkName.getText() != null && !tBookmarkName.getText().isEmpty() &&
[7859]287 OffsetBookmark.getBookmarkByName(layer, tBookmarkName.getText()) != null &&
288 !confirmOverwriteBookmark()) {
289 return;
[3734]290 }
[3715]291 super.buttonAction(buttonIndex, evt);
[3780]292 }
293
294 @Override
295 public void setVisible(boolean visible) {
296 super.setVisible(visible);
297 if (visible) return;
[3715]298 offsetDialog = null;
[3780]299 if (getValue() != 1) {
[3715]300 layer.setOffset(oldDx, oldDy);
[6087]301 } else if (tBookmarkName.getText() != null && !tBookmarkName.getText().isEmpty()) {
[3734]302 OffsetBookmark.bookmarkOffset(tBookmarkName.getText(), layer);
[3715]303 }
[3737]304 Main.main.menu.imageryMenu.refreshOffsetMenu();
[3715]305 if (Main.map == null) return;
306 if (oldMapMode != null) {
307 Main.map.selectMapMode(oldMapMode);
308 oldMapMode = null;
309 } else {
310 Main.map.selectSelectTool(false);
311 }
312 }
[8152]313
314 class WindowEventHandler extends WindowAdapter {
315 @Override
316 public void windowClosing(WindowEvent e) {
317 setVisible(false);
318 }
319 }
[3715]320 }
[6107]321
322 @Override
323 public void destroy() {
324 super.destroy();
325 removeListeners();
326 this.layer = null;
327 this.oldMapMode = null;
328 }
[3715]329}
Note: See TracBrowser for help on using the repository browser.