- Timestamp:
- 2020-05-27T08:03:39+02:00 (4 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui/download
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/download/OSMDownloadSource.java
r16174 r16503 9 9 import java.awt.Font; 10 10 import java.awt.GridBagLayout; 11 import java.lang.reflect.InvocationTargetException; 11 12 import java.util.ArrayList; 13 import java.util.Collections; 12 14 import java.util.List; 13 15 import java.util.concurrent.ExecutionException; … … 18 20 import javax.swing.JLabel; 19 21 import javax.swing.JOptionPane; 22 import javax.swing.JPanel; 20 23 import javax.swing.event.ChangeListener; 21 24 … … 29 32 import org.openstreetmap.josm.data.ProjectionBounds; 30 33 import org.openstreetmap.josm.data.ViewportData; 34 import org.openstreetmap.josm.data.gpx.GpxData; 35 import org.openstreetmap.josm.data.osm.DataSet; 36 import org.openstreetmap.josm.data.osm.NoteData; 31 37 import org.openstreetmap.josm.data.preferences.BooleanProperty; 32 38 import org.openstreetmap.josm.gui.MainApplication; … … 43 49 * @since 12652 44 50 */ 45 public class OSMDownloadSource implements DownloadSource< OSMDownloadSource.OSMDownloadData> {51 public class OSMDownloadSource implements DownloadSource<List<IDownloadSourceType>> { 46 52 /** 47 53 * The simple name for the {@link OSMDownloadSourcePanel} … … 50 56 public static final String SIMPLE_NAME = "osmdownloadpanel"; 51 57 58 /** The possible methods to get data */ 59 static final List<IDownloadSourceType> DOWNLOAD_SOURCES = new ArrayList<>(); 60 static { 61 // Order is important (determines button order, and what gets zoomed to) 62 DOWNLOAD_SOURCES.add(new OsmDataDownloadType()); 63 DOWNLOAD_SOURCES.add(new GpsDataDownloadType()); 64 DOWNLOAD_SOURCES.add(new NotesDataDownloadType()); 65 } 66 52 67 @Override 53 public AbstractDownloadSourcePanel< OSMDownloadData> createPanel(DownloadDialog dialog) {68 public AbstractDownloadSourcePanel<List<IDownloadSourceType>> createPanel(DownloadDialog dialog) { 54 69 return new OSMDownloadSourcePanel(this, dialog); 55 70 } 56 71 57 72 @Override 58 public void doDownload( OSMDownloadDatadata, DownloadSettings settings) {73 public void doDownload(List<IDownloadSourceType> data, DownloadSettings settings) { 59 74 Bounds bbox = settings.getDownloadBounds() 60 75 .orElseThrow(() -> new IllegalArgumentException("OSM downloads requires bounds")); 61 76 boolean zoom = settings.zoomToData(); 62 77 boolean newLayer = settings.asNewLayer(); 63 List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>(); 64 65 if (data.isDownloadOSMData()) { 66 DownloadOsmTask task = new DownloadOsmTask(); 67 task.setZoomAfterDownload(zoom && !data.isDownloadGPX() && !data.isDownloadNotes()); 68 Future<?> future = task.download(new DownloadParams().withNewLayer(newLayer), bbox, null); 69 MainApplication.worker.submit(new PostDownloadHandler(task, future)); 70 if (zoom) { 71 tasks.add(new Pair<>(task, future)); 72 } 73 } 74 75 if (data.isDownloadGPX()) { 76 DownloadGpsTask task = new DownloadGpsTask(); 77 task.setZoomAfterDownload(zoom && !data.isDownloadOSMData() && !data.isDownloadNotes()); 78 Future<?> future = task.download(new DownloadParams().withNewLayer(newLayer), bbox, null); 79 MainApplication.worker.submit(new PostDownloadHandler(task, future)); 80 if (zoom) { 81 tasks.add(new Pair<>(task, future)); 82 } 83 } 84 85 if (data.isDownloadNotes()) { 86 DownloadNotesTask task = new DownloadNotesTask(); 87 task.setZoomAfterDownload(zoom && !data.isDownloadOSMData() && !data.isDownloadGPX()); 88 Future<?> future = task.download(new DownloadParams(), bbox, null); 89 MainApplication.worker.submit(new PostDownloadHandler(task, future)); 90 if (zoom) { 91 tasks.add(new Pair<>(task, future)); 92 } 93 } 78 final List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>(); 79 IDownloadSourceType zoomTask = zoom ? data.stream().findFirst().orElse(null) : null; 80 data.stream().filter(IDownloadSourceType::isEnabled).forEach(type -> { 81 try { 82 AbstractDownloadTask<?> task = type.getDownloadClass().getDeclaredConstructor().newInstance(); 83 task.setZoomAfterDownload(type.equals(zoomTask)); 84 Future<?> future = task.download(new DownloadParams().withNewLayer(newLayer), bbox, null); 85 MainApplication.worker.submit(new PostDownloadHandler(task, future)); 86 if (zoom) { 87 tasks.add(new Pair<AbstractDownloadTask<?>, Future<?>>(task, future)); 88 } 89 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException 90 | InvocationTargetException | NoSuchMethodException | SecurityException e) { 91 Logging.error(e); 92 } 93 }); 94 94 95 95 if (zoom && tasks.size() > 1) { … … 131 131 132 132 /** 133 * @return The possible downloads that JOSM can make in the default Download 134 * screen 135 * @since 16503 136 */ 137 public static List<IDownloadSourceType> getDownloadTypes() { 138 return Collections.unmodifiableList(DOWNLOAD_SOURCES); 139 } 140 141 /** 142 * Get the instance of a data download type 143 * 144 * @param <T> The type to get 145 * @param typeClazz The class of the type 146 * @return The type instance 147 * @since 16503 148 */ 149 public static <T extends IDownloadSourceType> T getDownloadType(Class<T> typeClazz) { 150 return DOWNLOAD_SOURCES.stream().filter(typeClazz::isInstance).map(typeClazz::cast).findFirst().orElse(null); 151 } 152 153 /** 154 * @param type The IDownloadSourceType object to remove 155 * @return true See {@link List#remove}, but it also returns false if the 156 * parameter is a class from JOSM core. 157 * @since 16503 158 */ 159 public static boolean removeDownloadType(IDownloadSourceType type) { 160 boolean modified = false; 161 if (!(type instanceof OsmDataDownloadType) && !(type instanceof GpsDataDownloadType) 162 && !(type instanceof NotesDataDownloadType)) { 163 modified = DOWNLOAD_SOURCES.remove(type); 164 } 165 return modified; 166 } 167 168 /** 169 * Add a download type to the default JOSM download window 170 * 171 * @param type The initialized type to download 172 * @return See {@link List#add}, but it also returns false if the class 173 * already has an instance in the list or it is a class from JOSM core. 174 * @since 16503 175 */ 176 public static boolean addDownloadType(IDownloadSourceType type) { 177 boolean modified = false; 178 if (!(type instanceof OsmDataDownloadType) && !(type instanceof GpsDataDownloadType) 179 && !(type instanceof NotesDataDownloadType) 180 || DOWNLOAD_SOURCES.stream() 181 .noneMatch(possibility -> type.getClass().isInstance(possibility))) { 182 modified = DOWNLOAD_SOURCES.add(type); 183 } else { 184 throw new IllegalArgumentException("There can only be one instance of a class added, and it cannot be a built-in class."); 185 } 186 return modified; 187 } 188 189 /** 133 190 * The GUI representation of the OSM download source. 134 191 * @since 12652 135 192 */ 136 public static class OSMDownloadSourcePanel extends AbstractDownloadSourcePanel<OSMDownloadData> { 137 138 private final JCheckBox cbDownloadOsmData; 139 private final JCheckBox cbDownloadGpxData; 140 private final JCheckBox cbDownloadNotes; 193 public static class OSMDownloadSourcePanel extends AbstractDownloadSourcePanel<List<IDownloadSourceType>> { 141 194 private final JLabel sizeCheck = new JLabel(); 142 195 143 private static final BooleanProperty DOWNLOAD_OSM = new BooleanProperty("download.osm.data", true); 144 private static final BooleanProperty DOWNLOAD_GPS = new BooleanProperty("download.osm.gps", false); 145 private static final BooleanProperty DOWNLOAD_NOTES = new BooleanProperty("download.osm.notes", false); 196 /** This is used to keep track of the components for download sources, and to dynamically update/remove them */ 197 private JPanel downloadSourcesPanel; 198 199 private ChangeListener checkboxChangeListener; 146 200 147 201 /** … … 162 216 163 217 // size check depends on selected data source 164 final ChangeListenercheckboxChangeListener = e ->218 checkboxChangeListener = e -> 165 219 dialog.getSelectedDownloadArea().ifPresent(this::updateSizeCheck); 166 220 167 221 // adding the download tasks 168 222 add(new JLabel(tr(DATA_SOURCES_AND_TYPES)), GBC.std().insets(5, 5, 1, 5).anchor(GBC.CENTER)); 169 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true);170 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area."));171 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener);172 173 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data"));174 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area."));175 cbDownloadGpxData.getModel().addChangeListener(checkboxChangeListener);176 177 cbDownloadNotes = new JCheckBox(tr("Notes"));178 cbDownloadNotes.setToolTipText(tr("Select to download notes in the selected download area."));179 cbDownloadNotes.getModel().addChangeListener(checkboxChangeListener);180 181 223 Font labelFont = sizeCheck.getFont(); 182 224 sizeCheck.setFont(labelFont.deriveFont(Font.PLAIN, labelFont.getSize())); 183 225 184 add(cbDownloadOsmData, GBC.std().insets(1, 5, 1, 5));185 add( cbDownloadGpxData, GBC.std().insets(1, 5, 1, 5));186 add(cbDownloadNotes, GBC.eol().insets(1, 5, 1, 5));226 downloadSourcesPanel = new JPanel(); 227 add(downloadSourcesPanel, GBC.eol().anchor(GBC.EAST)); 228 updateSources(); 187 229 add(sizeCheck, GBC.eol().anchor(GBC.EAST).insets(5, 5, 5, 2)); 188 230 … … 190 232 } 191 233 192 @Override 193 public OSMDownloadData getData() { 194 return new OSMDownloadData( 195 isDownloadOsmData(), 196 isDownloadNotes(), 197 isDownloadGpxData()); 234 /** 235 * Update the source list for downloading data 236 */ 237 protected void updateSources() { 238 downloadSourcesPanel.removeAll(); 239 DOWNLOAD_SOURCES 240 .forEach(obj -> downloadSourcesPanel.add(obj.getCheckBox(checkboxChangeListener), GBC.std().insets(1, 5, 1, 5))); 241 } 242 243 @Override 244 public List<IDownloadSourceType> getData() { 245 return DOWNLOAD_SOURCES; 198 246 } 199 247 200 248 @Override 201 249 public void rememberSettings() { 202 DOWNLOAD_OSM.put(isDownloadOsmData()); 203 DOWNLOAD_GPS.put(isDownloadGpxData()); 204 DOWNLOAD_NOTES.put(isDownloadNotes()); 250 DOWNLOAD_SOURCES.forEach(type -> type.getBooleanProperty().put(type.getCheckBox().isSelected())); 205 251 } 206 252 207 253 @Override 208 254 public void restoreSettings() { 209 cbDownloadOsmData.setSelected(DOWNLOAD_OSM.get()); 210 cbDownloadGpxData.setSelected(DOWNLOAD_GPS.get()); 211 cbDownloadNotes.setSelected(DOWNLOAD_NOTES.get()); 255 updateSources(); 256 DOWNLOAD_SOURCES.forEach(type -> type.getCheckBox().setSelected(type.isEnabled())); 257 } 258 259 @Override 260 public void setVisible(boolean aFlag) { 261 super.setVisible(aFlag); 262 updateSources(); 212 263 } 213 264 … … 233 284 * If none of those are selected, then the corresponding dialog is shown to inform the user. 234 285 */ 235 if (!isDownloadOsmData() && !isDownloadGpxData() && !isDownloadNotes()) { 286 if (DOWNLOAD_SOURCES.stream().noneMatch(IDownloadSourceType::isEnabled)) { 287 StringBuilder line1 = new StringBuilder("<html>").append(tr("None of")); 288 StringBuilder line2 = new StringBuilder(tr("Please choose to either download")); 289 290 DOWNLOAD_SOURCES.forEach(type -> { 291 line1.append(" <strong>").append(type.getCheckBox().getText()).append("</strong> "); 292 line2.append(' ').append(type.getCheckBox().getText()).append(tr(", or")); 293 }); 294 line1.append(tr("is enabled.")).append("<br>"); 295 line2.append(tr(" all.")).append("</html>"); 236 296 JOptionPane.showMessageDialog( 237 297 this.getParent(), 238 tr("<html>Neither <strong>{0}</strong> nor <strong>{1}</strong> nor <strong>{2}</strong> is enabled.<br>" 239 + "Please choose to either download OSM data, or GPX data, or Notes, or all.</html>", 240 cbDownloadOsmData.getText(), 241 cbDownloadGpxData.getText(), 242 cbDownloadNotes.getText() 243 ), 298 line1.append(line2).toString(), 244 299 tr("Error"), 245 300 JOptionPane.ERROR_MESSAGE … … 258 313 * 259 314 * @return true if the user selected to download OSM data 260 */ 315 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 316 * {@code get(0).getCheckBox().isSelected()} 317 */ 318 @Deprecated 261 319 public boolean isDownloadOsmData() { 262 return cbDownloadOsmData.isSelected();320 return DOWNLOAD_SOURCES.get(0).getCheckBox().isSelected(); 263 321 } 264 322 … … 267 325 * 268 326 * @return true if the user selected to download GPX data 269 */ 327 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 328 * {@code get(1).getCheckBox().isSelected()} 329 */ 330 @Deprecated 270 331 public boolean isDownloadGpxData() { 271 return cbDownloadGpxData.isSelected();332 return DOWNLOAD_SOURCES.get(1).getCheckBox().isSelected(); 272 333 } 273 334 … … 276 337 * 277 338 * @return true if user selected to download notes 278 */ 339 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 340 * {@code get(2).getCheckBox().isSelected()} 341 */ 342 @Deprecated 279 343 public boolean isDownloadNotes() { 280 return cbDownloadNotes.isSelected();344 return DOWNLOAD_SOURCES.get(2).getCheckBox().isSelected(); 281 345 } 282 346 … … 303 367 } 304 368 305 boolean isAreaTooLarge = false; 306 if (!isDownloadNotes() && !isDownloadOsmData() && !isDownloadGpxData()) { 307 isAreaTooLarge = false; 308 } else if (isDownloadNotes() && !isDownloadOsmData() && !isDownloadGpxData()) { 309 // see max_note_request_area in https://github.com/openstreetmap/openstreetmap-website/blob/master/config/settings.yml 310 isAreaTooLarge = bbox.getArea() > Config.getPref().getDouble("osm-server.max-request-area-notes", 25); 311 } else { 312 // see max_request_area in https://github.com/openstreetmap/openstreetmap-website/blob/master/config/settings.yml 313 isAreaTooLarge = bbox.getArea() > Config.getPref().getDouble("osm-server.max-request-area", 0.25); 314 } 315 316 displaySizeCheckResult(isAreaTooLarge); 369 displaySizeCheckResult(DOWNLOAD_SOURCES.stream() 370 .anyMatch(type -> type.isDownloadAreaTooLarge(bbox))); 317 371 } 318 372 … … 333 387 */ 334 388 static class OSMDownloadData { 335 private final boolean downloadOSMData; 336 private final boolean downloadNotes; 337 private final boolean downloadGPX; 338 339 OSMDownloadData(boolean downloadOSMData, boolean downloadNotes, boolean downloadGPX) { 340 this.downloadOSMData = downloadOSMData; 341 this.downloadNotes = downloadNotes; 342 this.downloadGPX = downloadGPX; 343 } 344 345 boolean isDownloadOSMData() { 346 return downloadOSMData; 347 } 348 349 boolean isDownloadNotes() { 350 return downloadNotes; 351 } 352 353 boolean isDownloadGPX() { 354 return downloadGPX; 389 390 private List<IDownloadSourceType> downloadPossibilities; 391 392 /** 393 * @param downloadPossibilities A list of DataDownloadTypes (instantiated, with 394 * options set) 395 */ 396 OSMDownloadData(List<IDownloadSourceType> downloadPossibilities) { 397 this.downloadPossibilities = downloadPossibilities; 398 } 399 400 /** 401 * @return A list of DataDownloadTypes (instantiated, with options set) 402 */ 403 public List<IDownloadSourceType> getDownloadPossibilities() { 404 return downloadPossibilities; 405 } 406 } 407 408 private static class OsmDataDownloadType implements IDownloadSourceType { 409 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.data", true); 410 JCheckBox cbDownloadOsmData; 411 412 @Override 413 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 414 if (cbDownloadOsmData == null) { 415 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true); 416 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area.")); 417 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener); 418 } 419 if (checkboxChangeListener != null) { 420 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener); 421 } 422 return cbDownloadOsmData; 423 } 424 425 @Override 426 public Class<? extends AbstractDownloadTask<DataSet>> getDownloadClass() { 427 return DownloadOsmTask.class; 428 } 429 430 @Override 431 public BooleanProperty getBooleanProperty() { 432 return IS_ENABLED; 433 } 434 435 @Override 436 public boolean isDownloadAreaTooLarge(Bounds bound) { 437 // see max_request_area in 438 // https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml 439 return bound.getArea() > Config.getPref().getDouble("osm-server.max-request-area", 0.25); 440 } 441 } 442 443 private static class GpsDataDownloadType implements IDownloadSourceType { 444 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.gps", false); 445 private JCheckBox cbDownloadGpxData; 446 447 @Override 448 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 449 if (cbDownloadGpxData == null) { 450 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data")); 451 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area.")); 452 } 453 if (checkboxChangeListener != null) { 454 cbDownloadGpxData.getModel().addChangeListener(checkboxChangeListener); 455 } 456 457 return cbDownloadGpxData; 458 } 459 460 @Override 461 public Class<? extends AbstractDownloadTask<GpxData>> getDownloadClass() { 462 return DownloadGpsTask.class; 463 } 464 465 @Override 466 public BooleanProperty getBooleanProperty() { 467 return IS_ENABLED; 468 } 469 470 @Override 471 public boolean isDownloadAreaTooLarge(Bounds bound) { 472 return false; 473 } 474 } 475 476 private static class NotesDataDownloadType implements IDownloadSourceType { 477 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.notes", false); 478 private JCheckBox cbDownloadNotes; 479 480 @Override 481 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 482 if (cbDownloadNotes == null) { 483 cbDownloadNotes = new JCheckBox(tr("Notes")); 484 cbDownloadNotes.setToolTipText(tr("Select to download notes in the selected download area.")); 485 } 486 if (checkboxChangeListener != null) { 487 cbDownloadNotes.getModel().addChangeListener(checkboxChangeListener); 488 } 489 490 return cbDownloadNotes; 491 } 492 493 @Override 494 public Class<? extends AbstractDownloadTask<NoteData>> getDownloadClass() { 495 return DownloadNotesTask.class; 496 } 497 498 @Override 499 public BooleanProperty getBooleanProperty() { 500 return IS_ENABLED; 501 } 502 503 @Override 504 public boolean isDownloadAreaTooLarge(Bounds bound) { 505 // see max_note_request_area in 506 // https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml 507 return bound.getArea() > Config.getPref().getDouble("osm-server.max-request-area-notes", 25); 355 508 } 356 509 }
Note:
See TracChangeset
for help on using the changeset viewer.