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

Last change on this file since 6101 was 6101, checked in by akks, 11 years ago

revert 6099: seems it was not the described bug

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