source: josm/trunk/src/org/openstreetmap/josm/gui/widgets/BoundingBoxSelectionPanel.java@ 12735

Last change on this file since 12735 was 12735, checked in by bastiK, 7 years ago

see #15229 - move CoordinateFormat code out of LatLon class

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.widgets;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Dimension;
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
10
11import javax.swing.BorderFactory;
12import javax.swing.JLabel;
13import javax.swing.JPanel;
14import javax.swing.event.DocumentEvent;
15import javax.swing.event.DocumentListener;
16import javax.swing.text.JTextComponent;
17
18import org.openstreetmap.josm.data.Bounds;
19import org.openstreetmap.josm.data.coor.LatLon;
20import org.openstreetmap.josm.data.coor.conversion.DecimalDegreesCoordinateFormat;
21import org.openstreetmap.josm.tools.GBC;
22import org.openstreetmap.josm.tools.OsmUrlToBounds;
23
24/**
25 * A panel that allows the user to input the coordinates of a lat/lon box
26 */
27public class BoundingBoxSelectionPanel extends JPanel {
28
29 private JosmTextField[] tfLatLon;
30 private final JosmTextField tfOsmUrl = new JosmTextField();
31
32 protected void buildInputFields() {
33 tfLatLon = new JosmTextField[4];
34 for (int i = 0; i < 4; i++) {
35 tfLatLon[i] = new JosmTextField(11);
36 tfLatLon[i].setMinimumSize(new Dimension(100, new JosmTextField().getMinimumSize().height));
37 SelectAllOnFocusGainedDecorator.decorate(tfLatLon[i]);
38 }
39 LatitudeValidator.decorate(tfLatLon[0]);
40 LatitudeValidator.decorate(tfLatLon[2]);
41 LongitudeValidator.decorate(tfLatLon[1]);
42 LongitudeValidator.decorate(tfLatLon[3]);
43 }
44
45 protected final void build() {
46 buildInputFields();
47 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
48 setLayout(new GridBagLayout());
49 tfOsmUrl.getDocument().addDocumentListener(new OsmUrlRefresher());
50
51 // select content on receiving focus. this seems to be the default in the
52 // windows look+feel but not for others. needs invokeLater to avoid strange
53 // side effects that will cancel out the newly made selection otherwise.
54 tfOsmUrl.addFocusListener(new SelectAllOnFocusGainedDecorator());
55
56 add(new JLabel(tr("Min. latitude")), GBC.std().insets(0, 0, 3, 5));
57 add(tfLatLon[0], GBC.std().insets(0, 0, 3, 5));
58 add(new JLabel(tr("Min. longitude")), GBC.std().insets(0, 0, 3, 5));
59 add(tfLatLon[1], GBC.eol());
60 add(new JLabel(tr("Max. latitude")), GBC.std().insets(0, 0, 3, 5));
61 add(tfLatLon[2], GBC.std().insets(0, 0, 3, 5));
62 add(new JLabel(tr("Max. longitude")), GBC.std().insets(0, 0, 3, 5));
63 add(tfLatLon[3], GBC.eol());
64
65 GridBagConstraints gc = new GridBagConstraints();
66 gc.gridx = 0;
67 gc.gridy = 2;
68 gc.gridwidth = 4;
69 gc.fill = GridBagConstraints.HORIZONTAL;
70 gc.weightx = 1.0;
71 gc.insets = new Insets(10, 0, 0, 3);
72 add(new JMultilineLabel(tr("URL from www.openstreetmap.org (you can paste a download URL here to specify a bounding box)")), gc);
73
74 gc.gridy = 3;
75 gc.insets = new Insets(3, 0, 0, 3);
76 add(tfOsmUrl, gc);
77 }
78
79 /**
80 * Constructs a new {@code BoundingBoxSelectionPanel}.
81 */
82 public BoundingBoxSelectionPanel() {
83 build();
84 }
85
86 /**
87 * Sets the bounding box to the given area
88 * @param area The new input values
89 */
90 public void setBoundingBox(Bounds area) {
91 updateBboxFields(area);
92 }
93
94 /**
95 * Get the bounding box the user selected
96 * @return The box or <code>null</code> if no valid data was input.
97 */
98 public Bounds getBoundingBox() {
99 double minlon, minlat, maxlon, maxlat;
100 try {
101 minlat = Double.parseDouble(tfLatLon[0].getText().trim());
102 minlon = Double.parseDouble(tfLatLon[1].getText().trim());
103 maxlat = Double.parseDouble(tfLatLon[2].getText().trim());
104 maxlon = Double.parseDouble(tfLatLon[3].getText().trim());
105 } catch (NumberFormatException e) {
106 return null;
107 }
108 if (!LatLon.isValidLon(minlon) || !LatLon.isValidLon(maxlon)
109 || !LatLon.isValidLat(minlat) || !LatLon.isValidLat(maxlat))
110 return null;
111 if (minlon > maxlon)
112 return null;
113 if (minlat > maxlat)
114 return null;
115 return new Bounds(minlon, minlat, maxlon, maxlat);
116 }
117
118 private boolean parseURL() {
119 Bounds b = OsmUrlToBounds.parse(tfOsmUrl.getText());
120 if (b == null) return false;
121 updateBboxFields(b);
122 return true;
123 }
124
125 private void updateBboxFields(Bounds area) {
126 if (area == null) return;
127 tfLatLon[0].setText(DecimalDegreesCoordinateFormat.INSTANCE.latToString(area.getMin()));
128 tfLatLon[1].setText(DecimalDegreesCoordinateFormat.INSTANCE.lonToString(area.getMin()));
129 tfLatLon[2].setText(DecimalDegreesCoordinateFormat.INSTANCE.latToString(area.getMax()));
130 tfLatLon[3].setText(DecimalDegreesCoordinateFormat.INSTANCE.lonToString(area.getMax()));
131 }
132
133 private static class LatitudeValidator extends AbstractTextComponentValidator {
134
135 public static void decorate(JTextComponent tc) {
136 new LatitudeValidator(tc);
137 }
138
139 LatitudeValidator(JTextComponent tc) {
140 super(tc);
141 }
142
143 @Override
144 public void validate() {
145 double value = 0;
146 try {
147 value = Double.parseDouble(getComponent().getText());
148 } catch (NumberFormatException ex) {
149 feedbackInvalid(tr("The string ''{0}'' is not a valid double value.", getComponent().getText()));
150 return;
151 }
152 if (!LatLon.isValidLat(value)) {
153 feedbackInvalid(tr("Value for latitude in range [-90,90] required.", getComponent().getText()));
154 return;
155 }
156 feedbackValid("");
157 }
158
159 @Override
160 public boolean isValid() {
161 try {
162 return LatLon.isValidLat(Double.parseDouble(getComponent().getText()));
163 } catch (NumberFormatException ex) {
164 return false;
165 }
166 }
167 }
168
169 private static class LongitudeValidator extends AbstractTextComponentValidator {
170
171 public static void decorate(JTextComponent tc) {
172 new LongitudeValidator(tc);
173 }
174
175 LongitudeValidator(JTextComponent tc) {
176 super(tc);
177 }
178
179 @Override
180 public void validate() {
181 double value = 0;
182 try {
183 value = Double.parseDouble(getComponent().getText());
184 } catch (NumberFormatException ex) {
185 feedbackInvalid(tr("The string ''{0}'' is not a valid double value.", getComponent().getText()));
186 return;
187 }
188 if (!LatLon.isValidLon(value)) {
189 feedbackInvalid(tr("Value for longitude in range [-180,180] required.", getComponent().getText()));
190 return;
191 }
192 feedbackValid("");
193 }
194
195 @Override
196 public boolean isValid() {
197 try {
198 return LatLon.isValidLon(Double.parseDouble(getComponent().getText()));
199 } catch (NumberFormatException ex) {
200 return false;
201 }
202 }
203 }
204
205 class OsmUrlRefresher implements DocumentListener {
206 @Override
207 public void changedUpdate(DocumentEvent e) {
208 parseURL();
209 }
210
211 @Override
212 public void insertUpdate(DocumentEvent e) {
213 parseURL();
214 }
215
216 @Override
217 public void removeUpdate(DocumentEvent e) {
218 parseURL();
219 }
220 }
221}
Note: See TracBrowser for help on using the repository browser.