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

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

fix #10960 - Add note API search dialog (modified patch by ToeBee). Enable notes by default

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
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.Graphics;
14import java.awt.GridBagLayout;
15import java.awt.event.ActionEvent;
16import java.awt.event.ActionListener;
17import java.awt.event.InputEvent;
18import java.awt.event.KeyEvent;
19import java.awt.event.WindowAdapter;
20import java.awt.event.WindowEvent;
21import java.util.ArrayList;
22import java.util.List;
23
24import javax.swing.AbstractAction;
25import javax.swing.JCheckBox;
26import javax.swing.JComponent;
27import javax.swing.JDialog;
28import javax.swing.JLabel;
29import javax.swing.JOptionPane;
30import javax.swing.JPanel;
31import javax.swing.JTabbedPane;
32import javax.swing.KeyStroke;
33
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.actions.ExpertToggleAction;
36import org.openstreetmap.josm.data.Bounds;
37import org.openstreetmap.josm.gui.MapView;
38import org.openstreetmap.josm.gui.SideButton;
39import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
40import org.openstreetmap.josm.gui.help.HelpUtil;
41import org.openstreetmap.josm.io.OnlineResource;
42import org.openstreetmap.josm.plugins.PluginHandler;
43import org.openstreetmap.josm.tools.GBC;
44import org.openstreetmap.josm.tools.ImageProvider;
45import org.openstreetmap.josm.tools.InputMapUtils;
46import org.openstreetmap.josm.tools.OsmUrlToBounds;
47import org.openstreetmap.josm.tools.Utils;
48import org.openstreetmap.josm.tools.WindowGeometry;
49
50/**
51 * Dialog displayed to download OSM and/or GPS data from OSM server.
52 */
53public class DownloadDialog extends JDialog {
54 /** the unique instance of the download dialog */
55 private static DownloadDialog instance;
56
57 /**
58 * Replies the unique instance of the download dialog
59 *
60 * @return the unique instance of the download dialog
61 */
62 public static DownloadDialog getInstance() {
63 if (instance == null) {
64 instance = new DownloadDialog(Main.parent);
65 }
66 return instance;
67 }
68
69 protected SlippyMapChooser slippyMapChooser;
70 protected final List<DownloadSelection> downloadSelections = new ArrayList<>();
71 protected final JTabbedPane tpDownloadAreaSelectors = new JTabbedPane();
72 protected JCheckBox cbNewLayer;
73 protected JCheckBox cbStartup;
74 protected final JLabel sizeCheck = new JLabel();
75 protected Bounds currentBounds = null;
76 protected boolean canceled;
77
78 protected JCheckBox cbDownloadOsmData;
79 protected JCheckBox cbDownloadGpxData;
80 protected JCheckBox cbDownloadNotes;
81 /** the download action and button */
82 private DownloadAction actDownload;
83 protected SideButton btnDownload;
84
85 private void makeCheckBoxRespondToEnter(JCheckBox cb) {
86 cb.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "doDownload");
87 cb.getActionMap().put("doDownload", actDownload);
88 }
89
90 protected final JPanel buildMainPanel() {
91 JPanel pnl = new JPanel();
92 pnl.setLayout(new GridBagLayout());
93
94 // adding the download tasks
95 pnl.add(new JLabel(tr("Data Sources and Types:")), GBC.std().insets(5,5,1,5));
96 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true);
97 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area."));
98 pnl.add(cbDownloadOsmData, GBC.std().insets(1,5,1,5));
99 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data"));
100 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area."));
101 pnl.add(cbDownloadGpxData, GBC.std().insets(5,5,1,5));
102 cbDownloadNotes = new JCheckBox(tr("Notes"));
103 cbDownloadNotes.setToolTipText(tr("Select to download notes in the selected download area."));
104 pnl.add(cbDownloadNotes, GBC.eol().insets(50, 5, 1, 5));
105
106 // hook for subclasses
107 buildMainPanelAboveDownloadSelections(pnl);
108
109 slippyMapChooser = new SlippyMapChooser();
110
111 // predefined download selections
112 downloadSelections.add(slippyMapChooser);
113 downloadSelections.add(new BookmarkSelection());
114 downloadSelections.add(new BoundingBoxSelection());
115 downloadSelections.add(new PlaceSelection());
116 downloadSelections.add(new TileSelection());
117
118 // add selections from plugins
119 PluginHandler.addDownloadSelection(downloadSelections);
120
121 // now everybody may add their tab to the tabbed pane
122 // (not done right away to allow plugins to remove one of
123 // the default selectors!)
124 for (DownloadSelection s : downloadSelections) {
125 s.addGui(this);
126 }
127
128 pnl.add(tpDownloadAreaSelectors, GBC.eol().fill());
129
130 try {
131 tpDownloadAreaSelectors.setSelectedIndex(Main.pref.getInteger("download.tab", 0));
132 } catch (Exception ex) {
133 Main.pref.putInteger("download.tab", 0);
134 }
135
136 Font labelFont = sizeCheck.getFont();
137 sizeCheck.setFont(labelFont.deriveFont(Font.PLAIN, labelFont.getSize()));
138
139 cbNewLayer = new JCheckBox(tr("Download as new layer"));
140 cbNewLayer.setToolTipText(tr("<html>Select to download data into a new data layer.<br>"
141 +"Unselect to download into the currently active data layer.</html>"));
142
143 cbStartup = new JCheckBox(tr("Open this dialog on startup"));
144 cbStartup.setToolTipText(tr("<html>Autostart ''Download from OSM'' dialog every time JOSM is started.<br>You can open it manually from File menu or toolbar.</html>"));
145 cbStartup.addActionListener(new ActionListener() {
146 @Override
147 public void actionPerformed(ActionEvent e) {
148 Main.pref.put("download.autorun", cbStartup.isSelected());
149 }});
150
151 pnl.add(cbNewLayer, GBC.std().anchor(GBC.WEST).insets(5,5,5,5));
152 pnl.add(cbStartup, GBC.std().anchor(GBC.WEST).insets(15,5,5,5));
153
154 pnl.add(sizeCheck, GBC.eol().anchor(GBC.EAST).insets(5,5,5,2));
155
156 if (!ExpertToggleAction.isExpert()) {
157 JLabel infoLabel = new JLabel(tr("Use left click&drag to select area, arrows or right mouse button to scroll map, wheel or +/- to zoom."));
158 pnl.add(infoLabel,GBC.eol().anchor(GBC.SOUTH).insets(0,0,0,0));
159 }
160 return pnl;
161 }
162
163 /* This should not be necessary, but if not here, repaint is not always correct in SlippyMap! */
164 @Override
165 public void paint(Graphics g) {
166 tpDownloadAreaSelectors.getSelectedComponent().paint(g);
167 super.paint(g);
168 }
169
170 protected final JPanel buildButtonPanel() {
171 JPanel pnl = new JPanel();
172 pnl.setLayout(new FlowLayout());
173
174 // -- download button
175 pnl.add(btnDownload = new SideButton(actDownload = new DownloadAction()));
176 InputMapUtils.enableEnter(btnDownload);
177
178 makeCheckBoxRespondToEnter(cbDownloadGpxData);
179 makeCheckBoxRespondToEnter(cbDownloadOsmData);
180 makeCheckBoxRespondToEnter(cbDownloadNotes);
181 makeCheckBoxRespondToEnter(cbNewLayer);
182
183 // -- cancel button
184 SideButton btnCancel;
185 CancelAction actCancel = new CancelAction();
186 pnl.add(btnCancel = new SideButton(actCancel));
187 InputMapUtils.enableEnter(btnCancel);
188
189 // -- cancel on ESC
190 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "cancel");
191 getRootPane().getActionMap().put("cancel", actCancel);
192
193 // -- help button
194 SideButton btnHelp;
195 pnl.add(btnHelp = new SideButton(new ContextSensitiveHelpAction(ht("/Action/Download"))));
196 InputMapUtils.enableEnter(btnHelp);
197
198 return pnl;
199 }
200
201 /**
202 * Constructs a new {@code DownloadDialog}.
203 * @param parent the parent component
204 */
205 public DownloadDialog(Component parent) {
206 super(JOptionPane.getFrameForComponent(parent),tr("Download"), ModalityType.DOCUMENT_MODAL);
207 getContentPane().setLayout(new BorderLayout());
208 getContentPane().add(buildMainPanel(), BorderLayout.CENTER);
209 getContentPane().add(buildButtonPanel(), BorderLayout.SOUTH);
210
211 getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
212 KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK), "checkClipboardContents");
213
214 getRootPane().getActionMap().put("checkClipboardContents", new AbstractAction() {
215 @Override
216 public void actionPerformed(ActionEvent e) {
217 String clip = Utils.getClipboardContent();
218 if (clip == null) {
219 return;
220 }
221 Bounds b = OsmUrlToBounds.parse(clip);
222 if (b != null) {
223 boundingBoxChanged(new Bounds(b), null);
224 }
225 }
226 });
227 HelpUtil.setHelpContext(getRootPane(), ht("/Action/Download"));
228 addWindowListener(new WindowEventHandler());
229 restoreSettings();
230 }
231
232 private void updateSizeCheck() {
233 if (currentBounds == null) {
234 sizeCheck.setText(tr("No area selected yet"));
235 sizeCheck.setForeground(Color.darkGray);
236 } else if (currentBounds.getArea() > Main.pref.getDouble("osm-server.max-request-area", 0.25)) {
237 sizeCheck.setText(tr("Download area too large; will probably be rejected by server"));
238 sizeCheck.setForeground(Color.red);
239 } else {
240 sizeCheck.setText(tr("Download area ok, size probably acceptable to server"));
241 sizeCheck.setForeground(Color.darkGray);
242 }
243 }
244
245 /**
246 * Distributes a "bounding box changed" from one DownloadSelection
247 * object to the others, so they may update or clear their input fields.
248 *
249 * @param eventSource - the DownloadSelection object that fired this notification.
250 */
251 public void boundingBoxChanged(Bounds b, DownloadSelection eventSource) {
252 this.currentBounds = b;
253 for (DownloadSelection s : downloadSelections) {
254 if (s != eventSource) {
255 s.setDownloadArea(currentBounds);
256 }
257 }
258 updateSizeCheck();
259 }
260
261 /**
262 * Invoked by
263 * @param b
264 */
265 public void startDownload(Bounds b) {
266 this.currentBounds = b;
267 actDownload.run();
268 }
269
270 /**
271 * Replies true if the user selected to download OSM data
272 *
273 * @return true if the user selected to download OSM data
274 */
275 public boolean isDownloadOsmData() {
276 return cbDownloadOsmData.isSelected();
277 }
278
279 /**
280 * Replies true if the user selected to download GPX data
281 *
282 * @return true if the user selected to download GPX data
283 */
284 public boolean isDownloadGpxData() {
285 return cbDownloadGpxData.isSelected();
286 }
287
288 /**
289 * Replies true if user selected to download notes
290 *
291 * @return true if user selected to download notes
292 */
293 public boolean isDownloadNotes() {
294 return cbDownloadNotes.isSelected();
295 }
296
297 /**
298 * Replies true if the user requires to download into a new layer
299 *
300 * @return true if the user requires to download into a new layer
301 */
302 public boolean isNewLayerRequired() {
303 return cbNewLayer.isSelected();
304 }
305
306 /**
307 * Adds a new download area selector to the download dialog
308 *
309 * @param selector the download are selector
310 * @param displayName the display name of the selector
311 */
312 public void addDownloadAreaSelector(JPanel selector, String displayName) {
313 tpDownloadAreaSelectors.add(displayName, selector);
314 }
315
316 /**
317 * Refreshes the tile sources
318 * @since 6364
319 */
320 public final void refreshTileSources() {
321 if (slippyMapChooser != null) {
322 slippyMapChooser.refreshTileSources();
323 }
324 }
325
326 /**
327 * Remembers the current settings in the download dialog.
328 */
329 public void rememberSettings() {
330 Main.pref.put("download.tab", Integer.toString(tpDownloadAreaSelectors.getSelectedIndex()));
331 Main.pref.put("download.osm", cbDownloadOsmData.isSelected());
332 Main.pref.put("download.gps", cbDownloadGpxData.isSelected());
333 Main.pref.put("download.notes", cbDownloadNotes.isSelected());
334 Main.pref.put("download.newlayer", cbNewLayer.isSelected());
335 if (currentBounds != null) {
336 Main.pref.put("osm-download.bounds", currentBounds.encodeAsString(";"));
337 }
338 }
339
340 /**
341 * Restores the previous settings in the download dialog.
342 */
343 public void restoreSettings() {
344 cbDownloadOsmData.setSelected(Main.pref.getBoolean("download.osm", true));
345 cbDownloadGpxData.setSelected(Main.pref.getBoolean("download.gps", false));
346 cbDownloadNotes.setSelected(Main.pref.getBoolean("download.notes", false));
347 cbNewLayer.setSelected(Main.pref.getBoolean("download.newlayer", false));
348 cbStartup.setSelected( isAutorunEnabled() );
349 int idx = Main.pref.getInteger("download.tab", 0);
350 if (idx < 0 || idx > tpDownloadAreaSelectors.getTabCount()) {
351 idx = 0;
352 }
353 tpDownloadAreaSelectors.setSelectedIndex(idx);
354
355 if (Main.isDisplayingMapView()) {
356 MapView mv = Main.map.mapView;
357 currentBounds = new Bounds(
358 mv.getLatLon(0, mv.getHeight()),
359 mv.getLatLon(mv.getWidth(), 0)
360 );
361 boundingBoxChanged(currentBounds,null);
362 }
363 else {
364 Bounds bounds = getSavedDownloadBounds();
365 if (bounds != null) {
366 currentBounds = bounds;
367 boundingBoxChanged(currentBounds, null);
368 }
369 }
370 }
371
372 /**
373 * Returns the previously saved bounding box from preferences.
374 * @return The bounding box saved in preferences if any, {@code null} otherwise
375 * @since 6509
376 */
377 public static Bounds getSavedDownloadBounds() {
378 String value = Main.pref.get("osm-download.bounds");
379 if (!value.isEmpty()) {
380 try {
381 return new Bounds(value, ";");
382 } catch (IllegalArgumentException e) {
383 Main.warn(e);
384 }
385 }
386 return null;
387 }
388
389 /**
390 * Determines if the dialog autorun is enabled in preferences.
391 * @return {@code true} if the download dialog must be open at startup, {@code false} otherwise
392 */
393 public static boolean isAutorunEnabled() {
394 return Main.pref.getBoolean("download.autorun",false);
395 }
396
397 public static void autostartIfNeeded() {
398 if (isAutorunEnabled()) {
399 Main.main.menu.download.actionPerformed(null);
400 }
401 }
402
403 /**
404 * Replies the currently selected download area.
405 * @return the currently selected download area. May be {@code null}, if no download area is selected yet.
406 */
407 public Bounds getSelectedDownloadArea() {
408 return currentBounds;
409 }
410
411 @Override
412 public void setVisible(boolean visible) {
413 if (visible) {
414 new WindowGeometry(
415 getClass().getName() + ".geometry",
416 WindowGeometry.centerInWindow(
417 getParent(),
418 new Dimension(1000,600)
419 )
420 ).applySafe(this);
421 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
422 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
423 }
424 super.setVisible(visible);
425 }
426
427 /**
428 * Replies true if the dialog was canceled
429 *
430 * @return true if the dialog was canceled
431 */
432 public boolean isCanceled() {
433 return canceled;
434 }
435
436 protected void setCanceled(boolean canceled) {
437 this.canceled = canceled;
438 }
439
440 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
441 }
442
443 class CancelAction extends AbstractAction {
444 public CancelAction() {
445 putValue(NAME, tr("Cancel"));
446 putValue(SMALL_ICON, ImageProvider.get("cancel"));
447 putValue(SHORT_DESCRIPTION, tr("Click to close the dialog and to abort downloading"));
448 }
449
450 public void run() {
451 setCanceled(true);
452 setVisible(false);
453 }
454
455 @Override
456 public void actionPerformed(ActionEvent e) {
457 run();
458 }
459 }
460
461 class DownloadAction extends AbstractAction {
462 public DownloadAction() {
463 putValue(NAME, tr("Download"));
464 putValue(SMALL_ICON, ImageProvider.get("download"));
465 putValue(SHORT_DESCRIPTION, tr("Click to download the currently selected area"));
466 setEnabled(!Main.isOffline(OnlineResource.OSM_API));
467 }
468
469 public void run() {
470 if (currentBounds == null) {
471 JOptionPane.showMessageDialog(
472 DownloadDialog.this,
473 tr("Please select a download area first."),
474 tr("Error"),
475 JOptionPane.ERROR_MESSAGE
476 );
477 return;
478 }
479 if (!isDownloadOsmData() && !isDownloadGpxData() && !isDownloadNotes()) {
480 JOptionPane.showMessageDialog(
481 DownloadDialog.this,
482 tr("<html>Neither <strong>{0}</strong> nor <strong>{1}</strong> nor <strong>{2}</strong> is enabled.<br>"
483 + "Please choose to either download OSM data, or GPX data, or Notes, or all.</html>",
484 cbDownloadOsmData.getText(),
485 cbDownloadGpxData.getText(),
486 cbDownloadNotes.getText()
487 ),
488 tr("Error"),
489 JOptionPane.ERROR_MESSAGE
490 );
491 return;
492 }
493 setCanceled(false);
494 setVisible(false);
495 }
496
497 @Override
498 public void actionPerformed(ActionEvent e) {
499 run();
500 }
501 }
502
503 class WindowEventHandler extends WindowAdapter {
504 @Override
505 public void windowClosing(WindowEvent e) {
506 new CancelAction().run();
507 }
508
509 @Override
510 public void windowActivated(WindowEvent e) {
511 btnDownload.requestFocusInWindow();
512 }
513 }
514}
Note: See TracBrowser for help on using the repository browser.