- Timestamp:
- 2010-05-22T00:58:27+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AddNodeAction.java
r3083 r3266 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 6 7 import java.awt.BorderLayout;8 import java.awt.Color;9 import java.awt.Component;10 import java.awt.FlowLayout;11 import java.awt.GridBagLayout;12 7 import java.awt.event.ActionEvent; 13 import java.awt.event.FocusEvent;14 import java.awt.event.FocusListener;15 8 import java.awt.event.KeyEvent; 16 import java.awt.event.WindowAdapter;17 import java.awt.event.WindowEvent;18 import java.text.NumberFormat;19 import java.text.ParsePosition;20 import java.util.Locale;21 22 import javax.swing.AbstractAction;23 import javax.swing.BorderFactory;24 import javax.swing.JComponent;25 import javax.swing.JDialog;26 import javax.swing.JLabel;27 import javax.swing.JOptionPane;28 import javax.swing.JPanel;29 import javax.swing.JTextField;30 import javax.swing.KeyStroke;31 import javax.swing.UIManager;32 import javax.swing.event.DocumentEvent;33 import javax.swing.event.DocumentListener;34 9 35 10 import org.openstreetmap.josm.Main; 36 11 import org.openstreetmap.josm.command.AddCommand; 37 import org.openstreetmap.josm.data.coor.CoordinateFormat;38 12 import org.openstreetmap.josm.data.coor.LatLon; 39 13 import org.openstreetmap.josm.data.osm.Node; 40 import org.openstreetmap.josm.gui.SideButton; 41 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction; 42 import org.openstreetmap.josm.gui.help.HelpUtil; 43 import org.openstreetmap.josm.tools.GBC; 44 import org.openstreetmap.josm.tools.ImageProvider; 14 import org.openstreetmap.josm.gui.dialogs.LatLonDialog; 45 15 import org.openstreetmap.josm.tools.Shortcut; 46 import org.openstreetmap.josm.tools.WindowGeometry;47 16 48 17 /** … … 84 53 setEnabled(getEditLayer() != null); 85 54 } 86 87 static private class LatLonDialog extends JDialog {88 private static final Color BG_COLOR_ERROR = new Color(255,224,224);89 90 private JTextField tfLat;91 private JTextField tfLon;92 private boolean canceled = false;93 private LatLon coordinates;94 private OKAction actOK;95 private CancelAction actCancel;96 97 protected JPanel buildInputForm() {98 JPanel pnl = new JPanel(new GridBagLayout());99 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));100 pnl.add(new JLabel("<html>"+101 tr("Enter the coordinates for the new node.") +102 "<br>" + tr("Use decimal degrees.") +103 "<br>" + tr("Negative values denote Western/Southern hemisphere.")),104 GBC.eol());105 106 pnl.add(new JLabel(tr("Latitude")), GBC.std().insets(0,10,5,0));107 tfLat = new JTextField(12);108 pnl.add(tfLat, GBC.eol().insets(0,10,0,0));109 pnl.add(new JLabel(tr("Longitude")), GBC.std().insets(0,0,5,10));110 tfLon = new JTextField(12);111 pnl.add(tfLon, GBC.eol().insets(0,0,0,10));112 113 // parse and verify input on the fly114 //115 LatLonInputVerifier inputVerifier = new LatLonInputVerifier();116 tfLat.getDocument().addDocumentListener(inputVerifier);117 tfLon.getDocument().addDocumentListener(inputVerifier);118 119 // select the text in the field on focus120 //121 TextFieldFocusHandler focusHandler = new TextFieldFocusHandler();122 tfLat.addFocusListener(focusHandler);123 tfLon.addFocusListener(focusHandler);124 return pnl;125 }126 127 protected JPanel buildButtonRow() {128 JPanel pnl = new JPanel(new FlowLayout());129 130 SideButton btn;131 pnl.add(btn = new SideButton(actOK = new OKAction()));132 makeButtonRespondToEnter(btn);133 pnl.add(btn = new SideButton(actCancel = new CancelAction()));134 makeButtonRespondToEnter(btn);135 pnl.add(new SideButton(new ContextSensitiveHelpAction(ht("/Action/AddNode"))));136 return pnl;137 }138 139 protected void makeButtonRespondToEnter(SideButton btn) {140 btn.setFocusable(true);141 btn.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "enter");142 btn.getActionMap().put("enter", btn.getAction());143 }144 145 protected void build() {146 getContentPane().setLayout(new BorderLayout());147 getContentPane().add(buildInputForm(), BorderLayout.CENTER);148 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);149 pack();150 151 // make dialog respond to ESCAPE152 //153 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "escape");154 getRootPane().getActionMap().put("escape", actCancel);155 156 // make dialog respond to F1157 //158 HelpUtil.setHelpContext(getRootPane(), ht("/Action/AddNode"));159 }160 161 public LatLonDialog(Component parent) {162 super(JOptionPane.getFrameForComponent(parent), true /* modal */);163 setTitle(tr("Add Node..."));164 build();165 addWindowListener(new WindowEventHandler());166 setCoordinates(null);167 }168 169 public void setCoordinates(LatLon coordinates) {170 if (coordinates == null) {171 coordinates = new LatLon(0,0);172 }173 this.coordinates = coordinates;174 tfLat.setText(coordinates.latToString(CoordinateFormat.DECIMAL_DEGREES));175 tfLon.setText(coordinates.lonToString(CoordinateFormat.DECIMAL_DEGREES));176 actOK.setEnabled(true);177 }178 179 public LatLon getCoordinates() {180 return coordinates;181 }182 183 protected void setErrorFeedback(JTextField tf, String message) {184 tf.setBorder(BorderFactory.createLineBorder(Color.RED, 1));185 tf.setToolTipText(message);186 tf.setBackground(BG_COLOR_ERROR);187 }188 189 protected void clearErrorFeedback(JTextField tf, String message) {190 tf.setBorder(UIManager.getBorder("TextField.border"));191 tf.setToolTipText(message);192 tf.setBackground(UIManager.getColor("TextField.background"));193 }194 195 protected Double parseDoubleFromUserInput(String input) {196 if (input == null) return null;197 // remove white space and an optional degree symbol198 //199 input = input.trim();200 input = input.replaceAll("\u00B0", ""); // the degree symbol201 202 // try to parse using the current locale203 //204 NumberFormat f = NumberFormat.getNumberInstance();205 Number n=null;206 ParsePosition pp = new ParsePosition(0);207 n = f.parse(input,pp);208 if (pp.getErrorIndex() >= 0 || pp.getIndex()<input.length()) {209 // fall back - try to parse with the english locale210 //211 pp = new ParsePosition(0);212 f = NumberFormat.getNumberInstance(Locale.ENGLISH);213 n = f.parse(input, pp);214 if (pp.getErrorIndex() >= 0 || pp.getIndex()<input.length())215 return null;216 }217 return n== null ? null : n.doubleValue();218 }219 220 protected Double parseLatFromUserInput() {221 Double d = parseDoubleFromUserInput(tfLat.getText());222 if (d == null || ! LatLon.isValidLat(d)) {223 setErrorFeedback(tfLat, tr("Please enter a valid latitude in the range -90..90"));224 return null;225 } else {226 clearErrorFeedback(tfLat,tr("Please enter a latitude in the range -90..90"));227 }228 return d;229 }230 231 protected Double parseLonFromUserInput() {232 Double d = parseDoubleFromUserInput(tfLon.getText());233 if (d == null || ! LatLon.isValidLon(d)) {234 setErrorFeedback(tfLon, tr("Please enter a valid longitude in the range -180..180"));235 return null;236 } else {237 clearErrorFeedback(tfLon,tr("Please enter a longitude in the range -180..180"));238 }239 return d;240 }241 242 protected void parseUserInput() {243 Double lat = parseLatFromUserInput();244 Double lon = parseLonFromUserInput();245 if (lat == null || lon == null) {246 coordinates = null;247 actOK.setEnabled(false);248 } else {249 coordinates = new LatLon(lat,lon);250 actOK.setEnabled(true);251 }252 }253 254 public boolean isCanceled() {255 return canceled;256 }257 258 protected void setCanceled(boolean canceled) {259 this.canceled = canceled;260 }261 262 @Override263 public void setVisible(boolean visible) {264 if (visible) {265 setCanceled(false);266 WindowGeometry.centerInWindow(Main.parent, getSize()).applySafe(this);267 }268 super.setVisible(visible);269 }270 271 class OKAction extends AbstractAction {272 public OKAction() {273 putValue(NAME, tr("OK"));274 putValue(SHORT_DESCRIPTION, tr("Close the dialog and create a new node"));275 putValue(SMALL_ICON, ImageProvider.get("ok"));276 }277 278 public void actionPerformed(ActionEvent e) {279 setCanceled(false);280 setVisible(false);281 }282 }283 284 class CancelAction extends AbstractAction {285 public CancelAction() {286 putValue(NAME, tr("Cancel"));287 putValue(SHORT_DESCRIPTION, tr("Close the dialog, do not create a new node"));288 putValue(SMALL_ICON, ImageProvider.get("cancel"));289 }290 291 public void actionPerformed(ActionEvent e) {292 setCanceled(true);293 setVisible(false);294 }295 }296 297 class LatLonInputVerifier implements DocumentListener {298 public void changedUpdate(DocumentEvent e) {299 parseUserInput();300 }301 302 public void insertUpdate(DocumentEvent e) {303 parseUserInput();304 }305 306 public void removeUpdate(DocumentEvent e) {307 parseUserInput();308 }309 }310 311 static class TextFieldFocusHandler implements FocusListener {312 public void focusGained(FocusEvent e) {313 Component c = e.getComponent();314 if (c instanceof JTextField) {315 JTextField tf = (JTextField)c;316 tf.selectAll();317 }318 }319 public void focusLost(FocusEvent e) {}320 }321 322 class WindowEventHandler extends WindowAdapter {323 @Override324 public void windowClosing(WindowEvent e) {325 setCanceled(true);326 setVisible(false);327 }328 329 @Override330 public void windowOpened(WindowEvent e) {331 tfLat.requestFocusInWindow();332 }333 }334 }335 55 } -
trunk/src/org/openstreetmap/josm/command/MoveCommand.java
r3262 r3266 12 12 import javax.swing.JLabel; 13 13 14 import org.openstreetmap.josm.data.coor.CachedLatLon; 15 import org.openstreetmap.josm.data.coor.EastNorth; 14 16 import org.openstreetmap.josm.data.coor.LatLon; 15 17 import org.openstreetmap.josm.data.osm.Node; … … 55 57 this(Collections.singleton(osm), x, y); 56 58 } 59 60 public MoveCommand(Node node, LatLon position) { 61 this(Collections.singleton((OsmPrimitive) node), node.getEastNorth().sub(new CachedLatLon(position).getEastNorth())); 62 } 63 64 public MoveCommand(Collection<OsmPrimitive> objects, EastNorth offset) { 65 this(objects, offset.getX(), offset.getY()); 66 } 67 57 68 /** 58 69 * Create a MoveCommand and assign the initial object set and movement vector. -
trunk/src/org/openstreetmap/josm/gui/MainMenu.java
r2923 r3266 45 45 import org.openstreetmap.josm.actions.MergeSelectionAction; 46 46 import org.openstreetmap.josm.actions.MirrorAction; 47 import org.openstreetmap.josm.actions.MoveNodeAction; 47 48 import org.openstreetmap.josm.actions.NewAction; 48 49 import org.openstreetmap.josm.actions.OpenFileAction; … … 141 142 public final JosmAction mirror = new MirrorAction(); 142 143 public final AddNodeAction addnode = new AddNodeAction(); 144 public final MoveNodeAction movenode = new MoveNodeAction(); 143 145 public final JosmAction createCircle = new CreateCircleAction(); 144 146 public final JosmAction mergeNodes = new MergeNodesAction(); … … 291 293 toolsMenu.addSeparator(); 292 294 add(toolsMenu, addnode); 295 add(toolsMenu, movenode); 293 296 add(toolsMenu, createCircle); 294 297 toolsMenu.addSeparator();
Note:
See TracChangeset
for help on using the changeset viewer.