source: josm/trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java@ 4380

Last change on this file since 4380 was 4380, checked in by simon04, 13 years ago

fix #4609 - copy node coordinate to clipboard

  • Property svn:eol-style set to native
File size: 15.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.download;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BorderLayout;
8import java.awt.Color;
9import java.awt.Component;
10import java.awt.Dimension;
11import java.awt.FlowLayout;
12import java.awt.Font;
13import java.awt.GridBagConstraints;
14import java.awt.GridBagLayout;
15import java.awt.event.ActionEvent;
16import java.awt.event.InputEvent;
17import java.awt.event.KeyEvent;
18import java.awt.event.WindowAdapter;
19import java.awt.event.WindowEvent;
20import java.util.ArrayList;
21import java.util.List;
22
23import javax.swing.AbstractAction;
24import javax.swing.JCheckBox;
25import javax.swing.JComponent;
26import javax.swing.JDialog;
27import javax.swing.JLabel;
28import javax.swing.JOptionPane;
29import javax.swing.JPanel;
30import javax.swing.JTabbedPane;
31import javax.swing.KeyStroke;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.data.Bounds;
35import org.openstreetmap.josm.gui.MapView;
36import org.openstreetmap.josm.gui.SideButton;
37import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
38import org.openstreetmap.josm.gui.help.HelpUtil;
39import org.openstreetmap.josm.plugins.PluginHandler;
40import org.openstreetmap.josm.tools.GBC;
41import org.openstreetmap.josm.tools.ImageProvider;
42import org.openstreetmap.josm.tools.OsmUrlToBounds;
43import org.openstreetmap.josm.tools.Utils;
44import org.openstreetmap.josm.tools.WindowGeometry;
45
46/**
47 *
48 */
49public class DownloadDialog extends JDialog {
50 /** the unique instance of the download dialog */
51 static private DownloadDialog instance;
52
53 /**
54 * Replies the unique instance of the download dialog
55 *
56 * @return the unique instance of the download dialog
57 */
58 static public DownloadDialog getInstance() {
59 if (instance == null) {
60 instance = new DownloadDialog(Main.parent);
61 }
62 return instance;
63 }
64
65 private final List<DownloadSelection> downloadSelections = new ArrayList<DownloadSelection>();
66 private final JTabbedPane tpDownloadAreaSelectors = new JTabbedPane();
67 private JCheckBox cbNewLayer;
68 private final JLabel sizeCheck = new JLabel();
69 private Bounds currentBounds = null;
70 private boolean canceled;
71
72 private JCheckBox cbDownloadOsmData;
73 private JCheckBox cbDownloadGpxData;
74 /** the download action and button */
75 private DownloadAction actDownload;
76 private SideButton btnDownload;
77
78 private void makeCheckBoxRespondToEnter(JCheckBox cb) {
79 cb.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "doDownload");
80 cb.getActionMap().put("doDownload", actDownload);
81 }
82
83 public JPanel buildMainPanel() {
84 // generic constraints used by different components
85 GridBagConstraints gridBagConstraints;
86
87 JPanel pnl = new JPanel();
88 pnl.setLayout(new GridBagLayout());
89
90 // adding the download tasks
91 pnl.add(new JLabel(tr("Data Sources and Types:")), GBC.std().insets(5,5,1,5));
92 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true);
93 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area."));
94 pnl.add(cbDownloadOsmData, GBC.std().insets(1,5,1,5));
95 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data"));
96 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area."));
97 pnl.add(cbDownloadGpxData, GBC.eol().insets(5,5,1,5));
98
99 // predefined download selections
100 downloadSelections.add(new SlippyMapChooser());
101 downloadSelections.add(new BookmarkSelection());
102 downloadSelections.add(new BoundingBoxSelection());
103 downloadSelections.add(new PlaceSelection());
104 downloadSelections.add(new TileSelection());
105
106 // add selections from plugins
107 PluginHandler.addDownloadSelection(downloadSelections);
108
109 // now everybody may add their tab to the tabbed pane
110 // (not done right away to allow plugins to remove one of
111 // the default selectors!)
112 for (DownloadSelection s : downloadSelections) {
113 s.addGui(this);
114 }
115
116 pnl.add(tpDownloadAreaSelectors, GBC.eol().fill());
117
118 try {
119 tpDownloadAreaSelectors.setSelectedIndex(Main.pref.getInteger("download.tab", 0));
120 } catch (Exception ex) {
121 Main.pref.putInteger("download.tab", 0);
122 }
123
124 Font labelFont = sizeCheck.getFont();
125 sizeCheck.setFont(labelFont.deriveFont(Font.PLAIN, labelFont.getSize()));
126
127 cbNewLayer = new JCheckBox(tr("Download as new layer"));
128 cbNewLayer.setToolTipText(tr("<html>Select to download data into a new data layer.<br>"
129 +"Unselect to download into the currently active data layer.</html>"));
130
131 pnl.add(cbNewLayer, GBC.std().anchor(GBC.WEST).insets(5,5,5,5));
132 pnl.add(sizeCheck, GBC.eol().anchor(GBC.EAST).insets(5,5,5,5));
133
134 return pnl;
135 }
136
137 protected JPanel buildButtonPanel() {
138 JPanel pnl = new JPanel();
139 pnl.setLayout(new FlowLayout());
140
141 // -- download button
142 pnl.add(btnDownload = new SideButton(actDownload = new DownloadAction()));
143 btnDownload.setFocusable(true);
144 btnDownload.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "download");
145 btnDownload.getActionMap().put("download",actDownload);
146 makeCheckBoxRespondToEnter(cbDownloadGpxData);
147 makeCheckBoxRespondToEnter(cbDownloadOsmData);
148 makeCheckBoxRespondToEnter(cbNewLayer);
149
150 // -- cancel button
151 SideButton btnCancel;
152 CancelAction actCancel = new CancelAction();
153 pnl.add(btnCancel = new SideButton(actCancel));
154 btnCancel.setFocusable(true);
155 btnCancel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "enter");
156 btnCancel.getActionMap().put("enter",actCancel);
157
158 // -- cancel on ESC
159 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "cancel");
160 getRootPane().getActionMap().put("cancel", actCancel);
161
162 // -- help button
163 SideButton btnHelp;
164 pnl.add(btnHelp = new SideButton(new ContextSensitiveHelpAction(ht("/Dialog/Download"))));
165 btnHelp.setFocusable(true);
166 btnHelp.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "enter");
167 btnHelp.getActionMap().put("enter",btnHelp.getAction());
168
169 return pnl;
170 }
171
172 public DownloadDialog(Component parent) {
173 super(JOptionPane.getFrameForComponent(parent),tr("Download"), ModalityType.DOCUMENT_MODAL);
174 getContentPane().setLayout(new BorderLayout());
175 getContentPane().add(buildMainPanel(), BorderLayout.CENTER);
176 getContentPane().add(buildButtonPanel(), BorderLayout.SOUTH);
177
178 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
179 KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), "checkClipboardContents");
180
181 getRootPane().getActionMap().put("checkClipboardContents", new AbstractAction() {
182 public void actionPerformed(ActionEvent e) {
183 String clip = Utils.getClipboardContent();
184 if (clip == null) {
185 return;
186 }
187 Bounds b = OsmUrlToBounds.parse(clip);
188 if (b != null) {
189 boundingBoxChanged(new Bounds(b), null);
190 }
191 }
192 });
193 HelpUtil.setHelpContext(getRootPane(), ht("/Dialog/Download"));
194 addWindowListener(new WindowEventHandler());
195 restoreSettings();
196 }
197
198 private void updateSizeCheck() {
199 if (currentBounds == null) {
200 sizeCheck.setText(tr("No area selected yet"));
201 sizeCheck.setForeground(Color.darkGray);
202 } else if (currentBounds.getArea() > Main.pref.getDouble("osm-server.max-request-area", 0.25)) {
203 sizeCheck.setText(tr("Download area too large; will probably be rejected by server"));
204 sizeCheck.setForeground(Color.red);
205 } else {
206 sizeCheck.setText(tr("Download area ok, size probably acceptable to server"));
207 sizeCheck.setForeground(Color.darkGray);
208 }
209 }
210
211 /**
212 * Distributes a "bounding box changed" from one DownloadSelection
213 * object to the others, so they may update or clear their input
214 * fields.
215 *
216 * @param eventSource - the DownloadSelection object that fired this notification.
217 */
218 public void boundingBoxChanged(Bounds b, DownloadSelection eventSource) {
219 this.currentBounds = b;
220 for (DownloadSelection s : downloadSelections) {
221 if (s != eventSource) {
222 s.setDownloadArea(currentBounds);
223 }
224 }
225 updateSizeCheck();
226 }
227
228 /**
229 * Invoked by
230 * @param b
231 */
232 public void startDownload(Bounds b) {
233 this.currentBounds = b;
234 actDownload.run();
235 }
236
237 /**
238 * Replies true if the user selected to download OSM data
239 *
240 * @return true if the user selected to download OSM data
241 */
242 public boolean isDownloadOsmData() {
243 return cbDownloadOsmData.isSelected();
244 }
245
246 /**
247 * Replies true if the user selected to download GPX data
248 *
249 * @return true if the user selected to download GPX data
250 */
251 public boolean isDownloadGpxData() {
252 return cbDownloadGpxData.isSelected();
253 }
254
255 /**
256 * Replies true if the user requires to download into a new layer
257 *
258 * @return true if the user requires to download into a new layer
259 */
260 public boolean isNewLayerRequired() {
261 return cbNewLayer.isSelected();
262 }
263
264 /**
265 * Adds a new download area selector to the download dialog
266 *
267 * @param selector the download are selector
268 * @param displayName the display name of the selector
269 */
270 public void addDownloadAreaSelector(JPanel selector, String displayName) {
271 tpDownloadAreaSelectors.add(displayName, selector);
272 }
273
274 /**
275 * Remembers the current settings in the download dialog
276 *
277 */
278 public void rememberSettings() {
279 Main.pref.put("download.tab", Integer.toString(tpDownloadAreaSelectors.getSelectedIndex()));
280 Main.pref.put("download.osm", cbDownloadOsmData.isSelected());
281 Main.pref.put("download.gps", cbDownloadGpxData.isSelected());
282 Main.pref.put("download.newlayer", cbNewLayer.isSelected());
283 if (currentBounds != null) {
284 Main.pref.put("osm-download.bounds", currentBounds.encodeAsString(";"));
285 }
286 }
287
288 public void restoreSettings() {
289 cbDownloadOsmData.setSelected(Main.pref.getBoolean("download.osm", true));
290 cbDownloadGpxData.setSelected(Main.pref.getBoolean("download.gps", false));
291 cbNewLayer.setSelected(Main.pref.getBoolean("download.newlayer", false));
292 int idx = Main.pref.getInteger("download.tab", 0);
293 if (idx < 0 || idx > tpDownloadAreaSelectors.getTabCount()) {
294 idx = 0;
295 }
296 tpDownloadAreaSelectors.setSelectedIndex(idx);
297
298 if (Main.map != null) {
299 MapView mv = Main.map.mapView;
300 currentBounds = new Bounds(
301 mv.getLatLon(0, mv.getHeight()),
302 mv.getLatLon(mv.getWidth(), 0)
303 );
304 boundingBoxChanged(currentBounds,null);
305 }
306 else if (Main.pref.hasKey("osm-download.bounds")) {
307 // read the bounding box from the preferences
308 try {
309 currentBounds = new Bounds(Main.pref.get("osm-download.bounds"), ";");
310 boundingBoxChanged(currentBounds,null);
311 }
312 catch (Exception e) {
313 e.printStackTrace();
314 }
315 }
316 }
317
318 /**
319 * Replies the currently selected download area. May be null, if no download area is selected
320 * yet.
321 */
322 public Bounds getSelectedDownloadArea() {
323 return currentBounds;
324 }
325
326 @Override
327 public void setVisible(boolean visible) {
328 if (visible) {
329 new WindowGeometry(
330 getClass().getName() + ".geometry",
331 WindowGeometry.centerInWindow(
332 getParent(),
333 new Dimension(1000,600)
334 )
335 ).applySafe(this);
336 } else if (!visible && isShowing()){
337 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
338 }
339 super.setVisible(visible);
340 }
341
342 /**
343 * Replies true if the dialog was canceled
344 *
345 * @return true if the dialog was canceled
346 */
347 public boolean isCanceled() {
348 return canceled;
349 }
350
351 protected void setCanceled(boolean canceled) {
352 this.canceled = canceled;
353 }
354
355 class CancelAction extends AbstractAction {
356 public CancelAction() {
357 putValue(NAME, tr("Cancel"));
358 putValue(SMALL_ICON, ImageProvider.get("cancel"));
359 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and to abort downloading"));
360 }
361
362 public void run() {
363 setCanceled(true);
364 setVisible(false);
365 }
366
367 public void actionPerformed(ActionEvent e) {
368 run();
369 }
370 }
371
372 class DownloadAction extends AbstractAction {
373 public DownloadAction() {
374 putValue(NAME, tr("Download"));
375 putValue(SMALL_ICON, ImageProvider.get("download"));
376 putValue(SHORT_DESCRIPTION, tr("Click to download the currently selected area"));
377 }
378
379 public void run() {
380 if (currentBounds == null) {
381 JOptionPane.showMessageDialog(
382 DownloadDialog.this,
383 tr("Please select a download area first."),
384 tr("Error"),
385 JOptionPane.ERROR_MESSAGE
386 );
387 return;
388 }
389 if (!isDownloadOsmData() && !isDownloadGpxData()) {
390 JOptionPane.showMessageDialog(
391 DownloadDialog.this,
392 tr("<html>Neither <strong>{0}</strong> nor <strong>{1}</strong> is enabled.<br>"
393 + "Please choose to either download OSM data, or GPX data, or both.</html>",
394 cbDownloadOsmData.getText(),
395 cbDownloadGpxData.getText()
396 ),
397 tr("Error"),
398 JOptionPane.ERROR_MESSAGE
399 );
400 return;
401 }
402 setCanceled(false);
403 setVisible(false);
404 }
405
406 public void actionPerformed(ActionEvent e) {
407 run();
408 }
409 }
410
411 class WindowEventHandler extends WindowAdapter {
412 @Override
413 public void windowClosing(WindowEvent e) {
414 new CancelAction().run();
415 }
416
417 @Override
418 public void windowActivated(WindowEvent e) {
419 btnDownload.requestFocusInWindow();
420 }
421 }
422}
Note: See TracBrowser for help on using the repository browser.