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

Last change on this file since 6941 was 6890, checked in by Don-vip, 10 years ago

fix some Sonar issues (Constructor Calls Overridable Method)

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