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

Last change on this file since 12706 was 11620, checked in by Don-vip, 7 years ago

checkstyle - enable CatchParameterName rule

  • Property svn:eol-style set to native
File size: 10.9 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 if (gui != null)
124 gui.addDownloadAreaSelector(dlg, tr("Bounding Box"));
125 this.parent = gui;
126 }
127
128 @Override
129 public void setDownloadArea(Bounds area) {
130 updateBboxFields(area);
131 updateUrl(area);
132 }
133
134 /**
135 * Replies the download area.
136 * @return The download area
137 */
138 public Bounds getDownloadArea() {
139 double[] values = new double[4];
140 for (int i = 0; i < 4; i++) {
141 try {
142 values[i] = Double.parseDouble(latlon[i].getText());
143 } catch (NumberFormatException ex) {
144 return null;
145 }
146 }
147 if (!LatLon.isValidLat(values[0]) || !LatLon.isValidLon(values[1]))
148 return null;
149 if (!LatLon.isValidLat(values[2]) || !LatLon.isValidLon(values[3]))
150 return null;
151 return new Bounds(values);
152 }
153
154 private boolean parseURL(DownloadDialog gui) {
155 Bounds b = OsmUrlToBounds.parse(tfOsmUrl.getText());
156 if (b == null) return false;
157 gui.boundingBoxChanged(b, this);
158 updateBboxFields(b);
159 updateUrl(b);
160 return true;
161 }
162
163 private void updateBboxFields(Bounds area) {
164 if (area == null) return;
165 latlon[0].setText(area.getMin().latToString(CoordinateFormat.DECIMAL_DEGREES));
166 latlon[1].setText(area.getMin().lonToString(CoordinateFormat.DECIMAL_DEGREES));
167 latlon[2].setText(area.getMax().latToString(CoordinateFormat.DECIMAL_DEGREES));
168 latlon[3].setText(area.getMax().lonToString(CoordinateFormat.DECIMAL_DEGREES));
169 for (JosmTextField tf: latlon) {
170 resetErrorMessage(tf);
171 }
172 }
173
174 private void updateUrl(Bounds area) {
175 if (area == null) return;
176 showUrl.setText(OsmUrlToBounds.getURL(area));
177 }
178
179 private final Border errorBorder = BorderFactory.createLineBorder(Color.RED, 1);
180
181 protected void setErrorMessage(JosmTextField tf, String msg) {
182 tf.setBorder(errorBorder);
183 tf.setToolTipText(msg);
184 }
185
186 protected void resetErrorMessage(JosmTextField tf) {
187 tf.setBorder(UIManager.getBorder("TextField.border"));
188 tf.setToolTipText(null);
189 }
190
191 class LatValueChecker extends FocusAdapter implements ActionListener {
192 private final JosmTextField tfLatValue;
193
194 LatValueChecker(JosmTextField tfLatValue) {
195 this.tfLatValue = tfLatValue;
196 }
197
198 protected void check() {
199 double value = 0;
200 try {
201 value = Double.parseDouble(tfLatValue.getText());
202 } catch (NumberFormatException ex) {
203 setErrorMessage(tfLatValue, tr("The string ''{0}'' is not a valid double value.", tfLatValue.getText()));
204 return;
205 }
206 if (!LatLon.isValidLat(value)) {
207 setErrorMessage(tfLatValue, tr("Value for latitude in range [-90,90] required.", tfLatValue.getText()));
208 return;
209 }
210 resetErrorMessage(tfLatValue);
211 }
212
213 @Override
214 public void focusLost(FocusEvent e) {
215 check();
216 }
217
218 @Override
219 public void actionPerformed(ActionEvent e) {
220 check();
221 }
222 }
223
224 class LonValueChecker extends FocusAdapter implements ActionListener {
225 private final JosmTextField tfLonValue;
226
227 LonValueChecker(JosmTextField tfLonValue) {
228 this.tfLonValue = tfLonValue;
229 }
230
231 protected void check() {
232 double value = 0;
233 try {
234 value = Double.parseDouble(tfLonValue.getText());
235 } catch (NumberFormatException ex) {
236 setErrorMessage(tfLonValue, tr("The string ''{0}'' is not a valid double value.", tfLonValue.getText()));
237 return;
238 }
239 if (!LatLon.isValidLon(value)) {
240 setErrorMessage(tfLonValue, tr("Value for longitude in range [-180,180] required.", tfLonValue.getText()));
241 return;
242 }
243 resetErrorMessage(tfLonValue);
244 }
245
246 @Override
247 public void focusLost(FocusEvent e) {
248 check();
249 }
250
251 @Override
252 public void actionPerformed(ActionEvent e) {
253 check();
254 }
255 }
256
257 static class SelectAllOnFocusHandler extends FocusAdapter {
258 private final JTextComponent tfTarget;
259
260 SelectAllOnFocusHandler(JTextComponent tfTarget) {
261 this.tfTarget = tfTarget;
262 }
263
264 @Override
265 public void focusGained(FocusEvent e) {
266 tfTarget.selectAll();
267 }
268 }
269
270 class OsmUrlRefresher implements DocumentListener {
271 @Override
272 public void changedUpdate(DocumentEvent e) {
273 parseURL(parent);
274 }
275
276 @Override
277 public void insertUpdate(DocumentEvent e) {
278 parseURL(parent);
279 }
280
281 @Override
282 public void removeUpdate(DocumentEvent e) {
283 parseURL(parent);
284 }
285 }
286
287 class BoundingBoxBuilder extends FocusAdapter implements ActionListener {
288 protected Bounds build() {
289 double minlon, minlat, maxlon, maxlat;
290 try {
291 minlat = Double.parseDouble(latlon[0].getText().trim());
292 minlon = Double.parseDouble(latlon[1].getText().trim());
293 maxlat = Double.parseDouble(latlon[2].getText().trim());
294 maxlon = Double.parseDouble(latlon[3].getText().trim());
295 } catch (NumberFormatException e) {
296 return null;
297 }
298 if (!LatLon.isValidLon(minlon) || !LatLon.isValidLon(maxlon)
299 || !LatLon.isValidLat(minlat) || !LatLon.isValidLat(maxlat))
300 return null;
301 if (minlon > maxlon)
302 return null;
303 if (minlat > maxlat)
304 return null;
305 return new Bounds(minlat, minlon, maxlat, maxlon);
306 }
307
308 protected void refreshBounds() {
309 Bounds b = build();
310 parent.boundingBoxChanged(b, BoundingBoxSelection.this);
311 }
312
313 @Override
314 public void focusLost(FocusEvent e) {
315 refreshBounds();
316 }
317
318 @Override
319 public void actionPerformed(ActionEvent e) {
320 refreshBounds();
321 }
322 }
323}
Note: See TracBrowser for help on using the repository browser.