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