source: josm/trunk/src/org/openstreetmap/josm/gui/download/BoundingBoxSelection.java@ 8840

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

sonar - squid:S3052 - Fields should not be initialized to default values

  • Property svn:eol-style set to native
File size: 10.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.download;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Dimension;
8import java.awt.GridBagLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.ActionListener;
11import java.awt.event.FocusAdapter;
12import java.awt.event.FocusEvent;
13import java.awt.event.MouseAdapter;
14import java.awt.event.MouseEvent;
15
16import javax.swing.BorderFactory;
17import javax.swing.JButton;
18import javax.swing.JLabel;
19import javax.swing.JPanel;
20import javax.swing.UIManager;
21import javax.swing.border.Border;
22import javax.swing.event.DocumentEvent;
23import javax.swing.event.DocumentListener;
24import javax.swing.text.JTextComponent;
25
26import org.openstreetmap.josm.data.Bounds;
27import org.openstreetmap.josm.data.coor.CoordinateFormat;
28import org.openstreetmap.josm.data.coor.LatLon;
29import org.openstreetmap.josm.gui.widgets.JosmTextArea;
30import org.openstreetmap.josm.gui.widgets.JosmTextField;
31import org.openstreetmap.josm.tools.GBC;
32import org.openstreetmap.josm.tools.OsmUrlToBounds;
33
34/**
35 * Bounding box selector.
36 *
37 * Provides max/min lat/lon input fields as well as the "URL from www.openstreetmap.org" text field.
38 *
39 * @author Frederik Ramm
40 *
41 */
42public class BoundingBoxSelection implements DownloadSelection {
43
44 private JosmTextField[] latlon;
45 private final JosmTextArea tfOsmUrl = new JosmTextArea();
46 private final JosmTextArea showUrl = new JosmTextArea();
47 private DownloadDialog parent;
48
49 protected void registerBoundingBoxBuilder() {
50 BoundingBoxBuilder bboxbuilder = new BoundingBoxBuilder();
51 for (JosmTextField ll : latlon) {
52 ll.addFocusListener(bboxbuilder);
53 ll.addActionListener(bboxbuilder);
54 }
55 }
56
57 protected void buildDownloadAreaInputFields() {
58 latlon = new JosmTextField[4];
59 for (int i = 0; i < 4; i++) {
60 latlon[i] = new JosmTextField(11);
61 latlon[i].setMinimumSize(new Dimension(100, new JosmTextField().getMinimumSize().height));
62 latlon[i].addFocusListener(new SelectAllOnFocusHandler(latlon[i]));
63 }
64 LatValueChecker latChecker = new LatValueChecker(latlon[0]);
65 latlon[0].addFocusListener(latChecker);
66 latlon[0].addActionListener(latChecker);
67
68 latChecker = new LatValueChecker(latlon[2]);
69 latlon[2].addFocusListener(latChecker);
70 latlon[2].addActionListener(latChecker);
71
72 LonValueChecker lonChecker = new LonValueChecker(latlon[1]);
73 latlon[1].addFocusListener(lonChecker);
74 latlon[1].addActionListener(lonChecker);
75
76 lonChecker = new LonValueChecker(latlon[3]);
77 latlon[3].addFocusListener(lonChecker);
78 latlon[3].addActionListener(lonChecker);
79
80 registerBoundingBoxBuilder();
81 }
82
83 @Override
84 public void addGui(final DownloadDialog gui) {
85 buildDownloadAreaInputFields();
86 final JPanel dlg = new JPanel(new GridBagLayout());
87
88 tfOsmUrl.getDocument().addDocumentListener(new OsmUrlRefresher());
89
90 // select content on receiving focus. this seems to be the default in the
91 // windows look+feel but not for others. needs invokeLater to avoid strange
92 // side effects that will cancel out the newly made selection otherwise.
93 tfOsmUrl.addFocusListener(new SelectAllOnFocusHandler(tfOsmUrl));
94 tfOsmUrl.setLineWrap(true);
95 tfOsmUrl.setBorder(latlon[0].getBorder());
96
97 dlg.add(new JLabel(tr("min lat")), GBC.std().insets(10, 20, 5, 0));
98 dlg.add(latlon[0], GBC.std().insets(0, 20, 0, 0));
99 dlg.add(new JLabel(tr("min lon")), GBC.std().insets(10, 20, 5, 0));
100 dlg.add(latlon[1], GBC.eol().insets(0, 20, 0, 0));
101 dlg.add(new JLabel(tr("max lat")), GBC.std().insets(10, 0, 5, 0));
102 dlg.add(latlon[2], GBC.std());
103 dlg.add(new JLabel(tr("max lon")), GBC.std().insets(10, 0, 5, 0));
104 dlg.add(latlon[3], GBC.eol());
105
106 final JButton btnClear = new JButton(tr("Clear textarea"));
107 btnClear.addMouseListener(new MouseAdapter() {
108 @Override
109 public void mouseClicked(MouseEvent arg0) {
110 tfOsmUrl.setText("");
111 }
112 });
113 dlg.add(btnClear, GBC.eol().insets(10, 20, 0, 0));
114
115 dlg.add(new JLabel(tr("URL from www.openstreetmap.org (you can paste an URL here to download the area)")),
116 GBC.eol().insets(10, 5, 5, 0));
117 dlg.add(tfOsmUrl, GBC.eop().insets(10, 0, 5, 0).fill());
118 dlg.add(showUrl, GBC.eop().insets(10, 0, 5, 5));
119 showUrl.setEditable(false);
120 showUrl.setBackground(dlg.getBackground());
121 showUrl.addFocusListener(new SelectAllOnFocusHandler(showUrl));
122
123 gui.addDownloadAreaSelector(dlg, tr("Bounding Box"));
124 this.parent = gui;
125 }
126
127 @Override
128 public void setDownloadArea(Bounds area) {
129 updateBboxFields(area);
130 updateUrl(area);
131 }
132
133 /**
134 * Replies the download area.
135 * @return The download area
136 */
137 public Bounds getDownloadArea() {
138 double[] values = new double[4];
139 for (int i = 0; i < 4; i++) {
140 try {
141 values[i] = Double.parseDouble(latlon[i].getText());
142 } catch (NumberFormatException x) {
143 return null;
144 }
145 }
146 if (!LatLon.isValidLat(values[0]) || !LatLon.isValidLon(values[1]))
147 return null;
148 if (!LatLon.isValidLat(values[2]) || !LatLon.isValidLon(values[3]))
149 return null;
150 return new Bounds(values);
151 }
152
153 private boolean parseURL(DownloadDialog gui) {
154 Bounds b = OsmUrlToBounds.parse(tfOsmUrl.getText());
155 if (b == null) return false;
156 gui.boundingBoxChanged(b, BoundingBoxSelection.this);
157 updateBboxFields(b);
158 updateUrl(b);
159 return true;
160 }
161
162 private void updateBboxFields(Bounds area) {
163 if (area == null) return;
164 latlon[0].setText(area.getMin().latToString(CoordinateFormat.DECIMAL_DEGREES));
165 latlon[1].setText(area.getMin().lonToString(CoordinateFormat.DECIMAL_DEGREES));
166 latlon[2].setText(area.getMax().latToString(CoordinateFormat.DECIMAL_DEGREES));
167 latlon[3].setText(area.getMax().lonToString(CoordinateFormat.DECIMAL_DEGREES));
168 for (JosmTextField tf: latlon) {
169 resetErrorMessage(tf);
170 }
171 }
172
173 private void updateUrl(Bounds area) {
174 if (area == null) return;
175 showUrl.setText(OsmUrlToBounds.getURL(area));
176 }
177
178 private Border errorBorder = BorderFactory.createLineBorder(Color.RED, 1);
179
180 protected void setErrorMessage(JosmTextField tf, String msg) {
181 tf.setBorder(errorBorder);
182 tf.setToolTipText(msg);
183 }
184
185 protected void resetErrorMessage(JosmTextField tf) {
186 tf.setBorder(UIManager.getBorder("TextField.border"));
187 tf.setToolTipText(null);
188 }
189
190 class LatValueChecker extends FocusAdapter implements ActionListener{
191 private JosmTextField tfLatValue;
192
193 LatValueChecker(JosmTextField tfLatValue) {
194 this.tfLatValue = tfLatValue;
195 }
196
197 protected void check() {
198 double value = 0;
199 try {
200 value = Double.parseDouble(tfLatValue.getText());
201 } catch (NumberFormatException ex) {
202 setErrorMessage(tfLatValue, tr("The string ''{0}'' is not a valid double value.", tfLatValue.getText()));
203 return;
204 }
205 if (!LatLon.isValidLat(value)) {
206 setErrorMessage(tfLatValue, tr("Value for latitude in range [-90,90] required.", tfLatValue.getText()));
207 return;
208 }
209 resetErrorMessage(tfLatValue);
210 }
211
212 @Override
213 public void focusLost(FocusEvent e) {
214 check();
215 }
216
217 @Override
218 public void actionPerformed(ActionEvent e) {
219 check();
220 }
221 }
222
223 class LonValueChecker extends FocusAdapter implements ActionListener {
224 private JosmTextField tfLonValue;
225
226 LonValueChecker(JosmTextField tfLonValue) {
227 this.tfLonValue = tfLonValue;
228 }
229
230 protected void check() {
231 double value = 0;
232 try {
233 value = Double.parseDouble(tfLonValue.getText());
234 } catch (NumberFormatException ex) {
235 setErrorMessage(tfLonValue, tr("The string ''{0}'' is not a valid double value.", tfLonValue.getText()));
236 return;
237 }
238 if (!LatLon.isValidLon(value)) {
239 setErrorMessage(tfLonValue, tr("Value for longitude in range [-180,180] required.", tfLonValue.getText()));
240 return;
241 }
242 resetErrorMessage(tfLonValue);
243 }
244
245 @Override
246 public void focusLost(FocusEvent e) {
247 check();
248 }
249
250 @Override
251 public void actionPerformed(ActionEvent e) {
252 check();
253 }
254 }
255
256 static class SelectAllOnFocusHandler extends FocusAdapter {
257 private JTextComponent tfTarget;
258
259 SelectAllOnFocusHandler(JTextComponent tfTarget) {
260 this.tfTarget = tfTarget;
261 }
262
263 @Override
264 public void focusGained(FocusEvent e) {
265 tfTarget.selectAll();
266 }
267 }
268
269 class OsmUrlRefresher implements DocumentListener {
270 @Override
271 public void changedUpdate(DocumentEvent e) {
272 parseURL(parent);
273 }
274
275 @Override
276 public void insertUpdate(DocumentEvent e) {
277 parseURL(parent);
278 }
279
280 @Override
281 public void removeUpdate(DocumentEvent e) {
282 parseURL(parent);
283 }
284 }
285
286 class BoundingBoxBuilder extends FocusAdapter implements ActionListener {
287 protected Bounds build() {
288 double minlon, minlat, maxlon, maxlat;
289 try {
290 minlat = Double.parseDouble(latlon[0].getText().trim());
291 minlon = Double.parseDouble(latlon[1].getText().trim());
292 maxlat = Double.parseDouble(latlon[2].getText().trim());
293 maxlon = Double.parseDouble(latlon[3].getText().trim());
294 } catch (NumberFormatException e) {
295 return null;
296 }
297 if (!LatLon.isValidLon(minlon) || !LatLon.isValidLon(maxlon)
298 || !LatLon.isValidLat(minlat) || !LatLon.isValidLat(maxlat))
299 return null;
300 if (minlon > maxlon)
301 return null;
302 if (minlat > maxlat)
303 return null;
304 return new Bounds(minlat, minlon, maxlat, maxlon);
305 }
306
307 protected void refreshBounds() {
308 Bounds b = build();
309 parent.boundingBoxChanged(b, BoundingBoxSelection.this);
310 }
311
312 @Override
313 public void focusLost(FocusEvent e) {
314 refreshBounds();
315 }
316
317 @Override
318 public void actionPerformed(ActionEvent e) {
319 refreshBounds();
320 }
321 }
322}
Note: See TracBrowser for help on using the repository browser.