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

Last change on this file since 5958 was 5958, checked in by Don-vip, 11 years ago
  • Improve PopupMenuLauncher to automatically select JTable/JList/JTree line under cursor
  • Simplify all popup menus with this new feature
  • Remove custom popup menus in BoundingBoxSelection and BoundingBoxSelection to use default text field popup menus recently introduced
  • Fix EDT violations in changeset window
  • Make Autoscale actions publicly available in MainMenu
  • Add a new "Zoom to problem" mode in AutoScaleAction
  • Make "Zoom to problem" menu item in validator dialog use this new feature
  • Update enabled state of "Zoom to Conflict" and "Zoom to problem" against selection of conflict/validator dialog
  • Property svn:eol-style set to native
File size: 10.7 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 public void addGui(final DownloadDialog gui) {
84 buildDownloadAreaInputFields();
85 final JPanel dlg = new JPanel(new GridBagLayout());
86
87 tfOsmUrl.getDocument().addDocumentListener(new OsmUrlRefresher());
88
89 // select content on receiving focus. this seems to be the default in the
90 // windows look+feel but not for others. needs invokeLater to avoid strange
91 // side effects that will cancel out the newly made selection otherwise.
92 tfOsmUrl.addFocusListener(new SelectAllOnFocusHandler(tfOsmUrl));
93 tfOsmUrl.setLineWrap(true);
94 tfOsmUrl.setBorder(latlon[0].getBorder());
95
96 dlg.add(new JLabel(tr("min lat")), GBC.std().insets(10,20,5,0));
97 dlg.add(latlon[0], GBC.std().insets(0,20,0,0));
98 dlg.add(new JLabel(tr("min lon")), GBC.std().insets(10,20,5,0));
99 dlg.add(latlon[1], GBC.eol().insets(0,20,0,0));
100 dlg.add(new JLabel(tr("max lat")), GBC.std().insets(10,0,5,0));
101 dlg.add(latlon[2], GBC.std());
102 dlg.add(new JLabel(tr("max lon")), GBC.std().insets(10,0,5,0));
103 dlg.add(latlon[3], GBC.eol());
104
105 final JButton btnClear = new JButton(tr("Clear textarea"));
106 btnClear.addMouseListener(new MouseAdapter() {
107 @Override
108 public void mouseClicked(MouseEvent arg0) {
109 tfOsmUrl.setText("");
110 }
111 });
112 dlg.add(btnClear, GBC.eol().insets(10,20,0,0));
113
114 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));
115 dlg.add(tfOsmUrl, GBC.eop().insets(10,0,5,0).fill());
116 dlg.add(showUrl, GBC.eop().insets(10,0,5,5));
117 showUrl.setEditable(false);
118 showUrl.setBackground(dlg.getBackground());
119 showUrl.addFocusListener(new SelectAllOnFocusHandler(showUrl));
120
121 gui.addDownloadAreaSelector(dlg, tr("Bounding Box"));
122 this.parent = gui;
123 }
124
125 public void setDownloadArea(Bounds area) {
126 updateBboxFields(area);
127 updateUrl(area);
128 }
129
130 /**
131 * Replies the download area.
132 * @return The download area
133 */
134 public Bounds getDownloadArea() {
135 double[] values = new double[4];
136 for (int i=0; i < 4; i++) {
137 try {
138 values[i] = Double.parseDouble(latlon[i].getText());
139 } catch(NumberFormatException x) {
140 return null;
141 }
142 }
143 if (!LatLon.isValidLat(values[0]) || !LatLon.isValidLon(values[1]))
144 return null;
145 if (!LatLon.isValidLat(values[2]) || !LatLon.isValidLon(values[3]))
146 return null;
147 return new Bounds(values);
148 }
149
150 private boolean parseURL(DownloadDialog gui) {
151 Bounds b = OsmUrlToBounds.parse(tfOsmUrl.getText());
152 if(b == null) return false;
153 gui.boundingBoxChanged(b,BoundingBoxSelection.this);
154 updateBboxFields(b);
155 updateUrl(b);
156 return true;
157 }
158
159 private void updateBboxFields(Bounds area) {
160 if (area == null) return;
161 latlon[0].setText(area.getMin().latToString(CoordinateFormat.DECIMAL_DEGREES));
162 latlon[1].setText(area.getMin().lonToString(CoordinateFormat.DECIMAL_DEGREES));
163 latlon[2].setText(area.getMax().latToString(CoordinateFormat.DECIMAL_DEGREES));
164 latlon[3].setText(area.getMax().lonToString(CoordinateFormat.DECIMAL_DEGREES));
165 for (JosmTextField tf: latlon) {
166 resetErrorMessage(tf);
167 }
168 }
169
170 private void updateUrl(Bounds area) {
171 if (area == null) return;
172 showUrl.setText(OsmUrlToBounds.getURL(area));
173 }
174
175 private Border errorBorder = BorderFactory.createLineBorder(Color.RED, 1);
176
177 protected void setErrorMessage(JosmTextField tf, String msg) {
178 tf.setBorder(errorBorder);
179 tf.setToolTipText(msg);
180 }
181
182 protected void resetErrorMessage(JosmTextField tf) {
183 tf.setBorder(UIManager.getBorder("TextField.border"));
184 tf.setToolTipText("");
185 }
186
187 class LatValueChecker extends FocusAdapter implements ActionListener{
188 private JosmTextField tfLatValue;
189
190 public LatValueChecker(JosmTextField tfLatValue) {
191 this.tfLatValue = tfLatValue;
192 }
193
194 protected void check() {
195 double value = 0;
196 try {
197 value = Double.parseDouble(tfLatValue.getText());
198 } catch(NumberFormatException ex) {
199 setErrorMessage(tfLatValue,tr("The string ''{0}'' is not a valid double value.", tfLatValue.getText()));
200 return;
201 }
202 if (!LatLon.isValidLat(value)) {
203 setErrorMessage(tfLatValue,tr("Value for latitude in range [-90,90] required.", tfLatValue.getText()));
204 return;
205 }
206 resetErrorMessage(tfLatValue);
207 }
208
209 @Override
210 public void focusLost(FocusEvent e) {
211 check();
212 }
213
214 public void actionPerformed(ActionEvent e) {
215 check();
216 }
217 }
218
219 class LonValueChecker extends FocusAdapter implements ActionListener {
220 private JosmTextField tfLonValue;
221
222 public LonValueChecker(JosmTextField tfLonValue) {
223 this.tfLonValue = tfLonValue;
224 }
225
226 protected void check() {
227 double value = 0;
228 try {
229 value = Double.parseDouble(tfLonValue.getText());
230 } catch(NumberFormatException ex) {
231 setErrorMessage(tfLonValue,tr("The string ''{0}'' is not a valid double value.", tfLonValue.getText()));
232 return;
233 }
234 if (!LatLon.isValidLon(value)) {
235 setErrorMessage(tfLonValue,tr("Value for longitude in range [-180,180] required.", tfLonValue.getText()));
236 return;
237 }
238 resetErrorMessage(tfLonValue);
239 }
240
241 @Override
242 public void focusLost(FocusEvent e) {
243 check();
244 }
245
246 public void actionPerformed(ActionEvent e) {
247 check();
248 }
249 }
250
251 static class SelectAllOnFocusHandler extends FocusAdapter {
252 private JTextComponent tfTarget;
253 public SelectAllOnFocusHandler(JTextComponent tfTarget) {
254 this.tfTarget = tfTarget;
255 }
256
257 @Override
258 public void focusGained(FocusEvent e) {
259 tfTarget.selectAll();
260 }
261 }
262
263 class OsmUrlRefresher implements DocumentListener {
264 public void changedUpdate(DocumentEvent e) { parseURL(parent); }
265 public void insertUpdate(DocumentEvent e) { parseURL(parent); }
266 public void removeUpdate(DocumentEvent e) { parseURL(parent); }
267 }
268
269 class BoundingBoxBuilder extends FocusAdapter implements ActionListener {
270 protected Bounds build() {
271 double minlon, minlat, maxlon,maxlat;
272 try {
273 minlat = Double.parseDouble(latlon[0].getText().trim());
274 minlon = Double.parseDouble(latlon[1].getText().trim());
275 maxlat = Double.parseDouble(latlon[2].getText().trim());
276 maxlon = Double.parseDouble(latlon[3].getText().trim());
277 } catch(NumberFormatException e) {
278 return null;
279 }
280 if (!LatLon.isValidLon(minlon) || !LatLon.isValidLon(maxlon)
281 || !LatLon.isValidLat(minlat) || ! LatLon.isValidLat(maxlat))
282 return null;
283 if (minlon > maxlon)
284 return null;
285 if (minlat > maxlat)
286 return null;
287 return new Bounds(minlat,minlon,maxlat,maxlon);
288 }
289
290 protected void refreshBounds() {
291 Bounds b = build();
292 parent.boundingBoxChanged(b, BoundingBoxSelection.this);
293 }
294
295 @Override
296 public void focusLost(FocusEvent e) {
297 refreshBounds();
298 }
299
300 public void actionPerformed(ActionEvent e) {
301 refreshBounds();
302 }
303 }
304}
Note: See TracBrowser for help on using the repository browser.