Ticket #18340: 18340.1.patch
| File 18340.1.patch, 21.4 KB (added by , 6 years ago) |
|---|
-
src/org/openstreetmap/josm/gui/download/OSMDownloadSource.java
8 8 import java.awt.Dimension; 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; 14 16 import java.util.concurrent.Future; … … 24 26 import org.openstreetmap.josm.actions.downloadtasks.DownloadNotesTask; 25 27 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask; 26 28 import org.openstreetmap.josm.actions.downloadtasks.DownloadParams; 29 import org.openstreetmap.josm.actions.downloadtasks.DownloadTask; 27 30 import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler; 28 31 import org.openstreetmap.josm.data.Bounds; 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; 33 39 import org.openstreetmap.josm.gui.MapFrame; … … 49 55 */ 50 56 public static final String SIMPLE_NAME = "osmdownloadpanel"; 51 57 58 /** The possible methods to get data */ 59 static final List<DataDownloadType> DOWNLOAD_POSSIBILITIES = new ArrayList<>(); 60 static { 61 // Order is important (determines button order, and what gets zoomed to) 62 DOWNLOAD_POSSIBILITIES.add(new OsmDataDownloadType()); 63 DOWNLOAD_POSSIBILITIES.add(new GpsDataDownloadType()); 64 DOWNLOAD_POSSIBILITIES.add(new NotesDataDownloadType()); 65 } 66 52 67 @Override 53 68 public AbstractDownloadSourcePanel<OSMDownloadData> createPanel(DownloadDialog dialog) { 54 69 return new OSMDownloadSourcePanel(this, dialog); … … 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)); 78 final List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>(); 79 DataDownloadType zoomTask = zoom ? data.getDownloadPossibilities().stream().findFirst().orElse(null) : null; 80 data.getDownloadPossibilities().parallelStream().filter(DataDownloadType::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); 72 92 } 73 } 93 }); 74 94 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 }94 95 95 if (zoom && tasks.size() > 1) { 96 96 MainApplication.worker.submit(() -> { 97 97 ProjectionBounds bounds = null; … … 130 130 } 131 131 132 132 /** 133 * @return The possible downloads that JOSM can make in the default Download 134 * screen 135 * @since xxx 136 */ 137 public List<DataDownloadType> getDownloadTypes() { 138 return Collections.unmodifiableList(DOWNLOAD_POSSIBILITIES); 139 } 140 141 /** 142 * @param type The DataDownloadType object to remove 143 * @return true if the list was modified 144 * @since xxx 145 */ 146 public boolean removeDownloadType(DataDownloadType type) { 147 boolean modified = false; 148 if (!(type instanceof OsmDataDownloadType) && !(type instanceof GpsDataDownloadType) 149 && !(type instanceof NotesDataDownloadType)) { 150 modified = DOWNLOAD_POSSIBILITIES.remove(type); 151 } 152 return modified; 153 } 154 155 /** 156 * Add a download type to the default JOSM download window 157 * 158 * @param type The initialized type to download 159 * @return true if the list was modified 160 * @since xxx 161 */ 162 public boolean addDownloadType(DataDownloadType type) { 163 boolean modified = false; 164 if (!(type instanceof OsmDataDownloadType) && !(type instanceof GpsDataDownloadType) 165 && !(type instanceof NotesDataDownloadType) 166 || DOWNLOAD_POSSIBILITIES.parallelStream() 167 .noneMatch(possibility -> type.getClass().isInstance(possibility))) { 168 modified = DOWNLOAD_POSSIBILITIES.add(type); 169 } 170 return modified; 171 } 172 173 /** 133 174 * The GUI representation of the OSM download source. 134 175 * @since 12652 135 176 */ 136 177 public static class OSMDownloadSourcePanel extends AbstractDownloadSourcePanel<OSMDownloadData> { 137 138 private final JCheckBox cbDownloadOsmData;139 private final JCheckBox cbDownloadGpxData;140 private final JCheckBox cbDownloadNotes;141 178 private final JLabel sizeCheck = new JLabel(); 142 179 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);146 147 180 /** 148 181 * Label used in front of data types available for download. Made public for reuse in other download dialogs. 149 182 * @since 16155 … … 166 199 167 200 // adding the download tasks 168 201 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 202 Font labelFont = sizeCheck.getFont(); 182 203 sizeCheck.setFont(labelFont.deriveFont(Font.PLAIN, labelFont.getSize())); 183 204 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)); 205 DOWNLOAD_POSSIBILITIES 206 .forEach(obj -> add(obj.getCheckBox(checkboxChangeListener), GBC.std().insets(1, 5, 1, 5))); 187 207 add(sizeCheck, GBC.eol().anchor(GBC.EAST).insets(5, 5, 5, 2)); 188 208 189 209 setMinimumSize(new Dimension(450, 115)); … … 191 211 192 212 @Override 193 213 public OSMDownloadData getData() { 194 return new OSMDownloadData( 195 isDownloadOsmData(), 196 isDownloadNotes(), 197 isDownloadGpxData()); 214 return new OSMDownloadData(DOWNLOAD_POSSIBILITIES); 198 215 } 199 216 200 217 @Override 201 218 public void rememberSettings() { 202 DOWNLOAD_OSM.put(isDownloadOsmData()); 203 DOWNLOAD_GPS.put(isDownloadGpxData()); 204 DOWNLOAD_NOTES.put(isDownloadNotes()); 219 DOWNLOAD_POSSIBILITIES.forEach(type -> type.getBooleanProperty().put(type.getCheckBox().isSelected())); 205 220 } 206 221 207 222 @Override 208 223 public void restoreSettings() { 209 cbDownloadOsmData.setSelected(DOWNLOAD_OSM.get()); 210 cbDownloadGpxData.setSelected(DOWNLOAD_GPS.get()); 211 cbDownloadNotes.setSelected(DOWNLOAD_NOTES.get()); 224 DOWNLOAD_POSSIBILITIES.forEach(type -> type.getCheckBox().setSelected(type.isEnabled())); 212 225 } 213 226 214 227 @Override … … 232 245 * must be chosen : raw osm data, gpx data, notes. 233 246 * If none of those are selected, then the corresponding dialog is shown to inform the user. 234 247 */ 235 if (!isDownloadOsmData() && !isDownloadGpxData() && !isDownloadNotes()) { 248 if (DOWNLOAD_POSSIBILITIES.parallelStream().noneMatch(type -> type.isEnabled())) { 249 StringBuilder line1 = new StringBuilder("<html>"); 250 StringBuilder line2 = new StringBuilder(tr("Please choose to either download")); 251 DOWNLOAD_POSSIBILITIES.forEach(type -> { 252 if (line1.length() == 6) { 253 line1.append(tr("Neither")); 254 } else { 255 line1.append(tr("nor")); 256 } 257 line1.append(" <strong>").append(type.getCheckBox().getText()).append("</strong> "); 258 line2.append(' ').append(type.getCheckBox().getText()).append(tr(", or")); 259 }); 260 line1.append(tr("is enabled.")).append("<br>"); 261 line2.append(tr(" all.")).append("</html>"); 236 262 JOptionPane.showMessageDialog( 237 263 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 ), 264 line1.append(line2).toString(), 244 265 tr("Error"), 245 266 JOptionPane.ERROR_MESSAGE 246 267 ); … … 257 278 * Replies true if the user selected to download OSM data 258 279 * 259 280 * @return true if the user selected to download OSM data 281 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 282 * {@code get(0).getCheckBox().isSelected()} 260 283 */ 284 @Deprecated 261 285 public boolean isDownloadOsmData() { 262 return cbDownloadOsmData.isSelected();286 return DOWNLOAD_POSSIBILITIES.get(0).getCheckBox().isSelected(); 263 287 } 264 288 265 289 /** … … 266 290 * Replies true if the user selected to download GPX data 267 291 * 268 292 * @return true if the user selected to download GPX data 293 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 294 * {@code get(1).getCheckBox().isSelected()} 269 295 */ 296 @Deprecated 270 297 public boolean isDownloadGpxData() { 271 return cbDownloadGpxData.isSelected();298 return DOWNLOAD_POSSIBILITIES.get(1).getCheckBox().isSelected(); 272 299 } 273 300 274 301 /** … … 275 302 * Replies true if user selected to download notes 276 303 * 277 304 * @return true if user selected to download notes 305 * @deprecated since xxx -- use {@link OSMDownloadSource#getDownloadTypes} with 306 * {@code get(2).getCheckBox().isSelected()} 278 307 */ 308 @Deprecated 279 309 public boolean isDownloadNotes() { 280 return cbDownloadNotes.isSelected();310 return DOWNLOAD_POSSIBILITIES.get(2).getCheckBox().isSelected(); 281 311 } 282 312 283 313 @Override … … 302 332 return; 303 333 } 304 334 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); 335 displaySizeCheckResult(DOWNLOAD_POSSIBILITIES.parallelStream() 336 .anyMatch(type -> type.isDownloadAreaTooLarge(bbox))); 317 337 } 318 338 319 339 private void displaySizeCheckResult(boolean isAreaTooLarge) { … … 332 352 * Encapsulates data that is required to download from the OSM server. 333 353 */ 334 354 static class OSMDownloadData { 335 private final boolean downloadOSMData;336 private final boolean downloadNotes;337 private final boolean downloadGPX;338 355 339 OSMDownloadData(boolean downloadOSMData, boolean downloadNotes, boolean downloadGPX) { 340 this.downloadOSMData = downloadOSMData; 341 this.downloadNotes = downloadNotes; 342 this.downloadGPX = downloadGPX; 356 private List<DataDownloadType> downloadPossibilities; 357 358 /** 359 * @param downloadPossibilities A list of DataDownloadTypes (instantiated, with 360 * options set) 361 */ 362 OSMDownloadData(List<DataDownloadType> downloadPossibilities) { 363 this.downloadPossibilities = downloadPossibilities; 343 364 } 344 365 345 boolean isDownloadOSMData() { 346 return downloadOSMData; 366 /** 367 * @return A list of DataDownloadTypes (instantiated, with options set) 368 */ 369 public List<DataDownloadType> getDownloadPossibilities() { 370 return downloadPossibilities; 347 371 } 372 } 348 373 349 boolean isDownloadNotes() { 350 return downloadNotes; 374 /** 375 * An interface to allow arbitrary download sources and types in the primary 376 * download window of JOSM 377 * 378 * @since xxx 379 */ 380 interface DataDownloadType { 381 /** 382 * @return The checkbox to be added to the UI 383 */ 384 default JCheckBox getCheckBox() { 385 return getCheckBox(null); 351 386 } 352 387 353 boolean isDownloadGPX() { 354 return downloadGPX; 388 /** 389 * @param checkboxChangeListener The listener for checkboxes (may be 390 * {@code null}) 391 * @return The checkbox to be added to the UI 392 */ 393 JCheckBox getCheckBox(ChangeListener checkboxChangeListener); 394 395 /** 396 * @return The {@link DownloadTask} class which will be getting the data 397 */ 398 Class<? extends AbstractDownloadTask<?>> getDownloadClass(); 399 400 /** 401 * @return The boolean indicating the last state of the download type 402 */ 403 default boolean isEnabled() { 404 return getBooleanProperty().get(); 355 405 } 406 407 /** 408 * @return The boolean property for this particular download type 409 */ 410 BooleanProperty getBooleanProperty(); 411 412 /** 413 * Check if the area is too large for the current DataDownloadType 414 * 415 * @param bound The bound that will be downloaded 416 * @return {@code true} if we definitely cannot download the area; 417 */ 418 boolean isDownloadAreaTooLarge(Bounds bound); 356 419 } 420 421 private static class OsmDataDownloadType implements DataDownloadType { 422 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.data", true); 423 JCheckBox cbDownloadOsmData; 424 425 @Override 426 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 427 if (cbDownloadOsmData == null) { 428 cbDownloadOsmData = new JCheckBox(tr("OpenStreetMap data"), true); 429 cbDownloadOsmData.setToolTipText(tr("Select to download OSM data in the selected download area.")); 430 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener); 431 } 432 if (checkboxChangeListener != null) { 433 cbDownloadOsmData.getModel().addChangeListener(checkboxChangeListener); 434 } 435 return cbDownloadOsmData; 436 } 437 438 @Override 439 public Class<? extends AbstractDownloadTask<DataSet>> getDownloadClass() { 440 return DownloadOsmTask.class; 441 } 442 443 @Override 444 public BooleanProperty getBooleanProperty() { 445 return IS_ENABLED; 446 } 447 448 @Override 449 public boolean isDownloadAreaTooLarge(Bounds bound) { 450 // see max_request_area in 451 // https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml 452 return bound.getArea() > Config.getPref().getDouble("osm-server.max-request-area", 0.25); 453 } 454 } 455 456 private static class GpsDataDownloadType implements DataDownloadType { 457 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.gps", false); 458 private JCheckBox cbDownloadGpxData; 459 460 @Override 461 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 462 if (cbDownloadGpxData == null) { 463 cbDownloadGpxData = new JCheckBox(tr("Raw GPS data")); 464 cbDownloadGpxData.setToolTipText(tr("Select to download GPS traces in the selected download area.")); 465 } 466 if (checkboxChangeListener != null) { 467 cbDownloadGpxData.getModel().addChangeListener(checkboxChangeListener); 468 } 469 470 return cbDownloadGpxData; 471 } 472 473 @Override 474 public Class<? extends AbstractDownloadTask<GpxData>> getDownloadClass() { 475 return DownloadGpsTask.class; 476 } 477 478 @Override 479 public BooleanProperty getBooleanProperty() { 480 return IS_ENABLED; 481 } 482 483 @Override 484 public boolean isDownloadAreaTooLarge(Bounds bound) { 485 return false; 486 } 487 } 488 489 private static class NotesDataDownloadType implements DataDownloadType { 490 static final BooleanProperty IS_ENABLED = new BooleanProperty("download.osm.notes", false); 491 private JCheckBox cbDownloadNotes; 492 493 @Override 494 public JCheckBox getCheckBox(ChangeListener checkboxChangeListener) { 495 if (cbDownloadNotes == null) { 496 cbDownloadNotes = new JCheckBox(tr("Notes")); 497 cbDownloadNotes.setToolTipText(tr("Select to download notes in the selected download area.")); 498 } 499 if (checkboxChangeListener != null) { 500 cbDownloadNotes.getModel().addChangeListener(checkboxChangeListener); 501 } 502 503 return cbDownloadNotes; 504 } 505 506 @Override 507 public Class<? extends AbstractDownloadTask<NoteData>> getDownloadClass() { 508 return DownloadNotesTask.class; 509 } 510 511 @Override 512 public BooleanProperty getBooleanProperty() { 513 return IS_ENABLED; 514 } 515 516 @Override 517 public boolean isDownloadAreaTooLarge(Bounds bound) { 518 // see max_note_request_area in 519 // https://github.com/openstreetmap/openstreetmap-website/blob/master/config/example.application.yml 520 return bound.getArea() > Config.getPref().getDouble("osm-server.max-request-area-notes", 25); 521 } 522 } 523 357 524 }
