- Timestamp:
- 2017-08-06T20:13:06+02:00 (7 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/DownloadAction.java
r11774 r12574 9 9 import java.util.ArrayList; 10 10 import java.util.List; 11 import java.util.Optional; 11 12 import java.util.concurrent.ExecutionException; 12 13 import java.util.concurrent.Future; 14 15 import javax.swing.JOptionPane; 13 16 14 17 import org.openstreetmap.josm.Main; … … 51 54 dialog.restoreSettings(); 52 55 dialog.setVisible(true); 53 if (!dialog.isCanceled()) { 54 dialog.rememberSettings(); 55 final Bounds area = dialog.getSelectedDownloadArea(); 56 final boolean zoom = dialog.isZoomToDownloadedDataRequired(); 57 final List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>(); 58 if (dialog.isDownloadOsmData()) { 59 DownloadOsmTask task = new DownloadOsmTask(); 60 task.setZoomAfterDownload(zoom && !dialog.isDownloadGpxData() && !dialog.isDownloadNotes()); 61 Future<?> future = task.download(dialog.isNewLayerRequired(), area, null); 62 Main.worker.submit(new PostDownloadHandler(task, future)); 63 if (zoom) { 64 tasks.add(new Pair<>(task, future)); 56 57 if (dialog.isCanceled()) { 58 return; 59 } 60 61 dialog.rememberSettings(); 62 63 Optional<Bounds> selectedArea = dialog.getSelectedDownloadArea(); 64 if (!selectedArea.isPresent()) { 65 JOptionPane.showMessageDialog( 66 dialog, 67 tr("Please select a download area first."), 68 tr("Error"), 69 JOptionPane.ERROR_MESSAGE 70 ); 71 return; 72 } 73 74 final Bounds area = selectedArea.get(); 75 final boolean zoom = dialog.isZoomToDownloadedDataRequired(); 76 final List<Pair<AbstractDownloadTask<?>, Future<?>>> tasks = new ArrayList<>(); 77 78 if (dialog.isDownloadOsmData()) { 79 DownloadOsmTask task = new DownloadOsmTask(); 80 task.setZoomAfterDownload(zoom && !dialog.isDownloadGpxData() && !dialog.isDownloadNotes()); 81 Future<?> future = task.download(dialog.isNewLayerRequired(), area, null); 82 Main.worker.submit(new PostDownloadHandler(task, future)); 83 if (zoom) { 84 tasks.add(new Pair<>(task, future)); 85 } 86 } 87 88 if (dialog.isDownloadGpxData()) { 89 DownloadGpsTask task = new DownloadGpsTask(); 90 task.setZoomAfterDownload(zoom && !dialog.isDownloadOsmData() && !dialog.isDownloadNotes()); 91 Future<?> future = task.download(dialog.isNewLayerRequired(), area, null); 92 Main.worker.submit(new PostDownloadHandler(task, future)); 93 if (zoom) { 94 tasks.add(new Pair<>(task, future)); 95 } 96 } 97 98 if (dialog.isDownloadNotes()) { 99 DownloadNotesTask task = new DownloadNotesTask(); 100 task.setZoomAfterDownload(zoom && !dialog.isDownloadOsmData() && !dialog.isDownloadGpxData()); 101 Future<?> future = task.download(false, area, null); 102 Main.worker.submit(new PostDownloadHandler(task, future)); 103 if (zoom) { 104 tasks.add(new Pair<>(task, future)); 105 } 106 } 107 108 if (zoom && tasks.size() > 1) { 109 Main.worker.submit(() -> { 110 ProjectionBounds bounds = null; 111 // Wait for completion of download jobs 112 for (Pair<AbstractDownloadTask<?>, Future<?>> p : tasks) { 113 try { 114 p.b.get(); 115 ProjectionBounds b = p.a.getDownloadProjectionBounds(); 116 if (bounds == null) { 117 bounds = b; 118 } else if (b != null) { 119 bounds.extend(b); 120 } 121 } catch (InterruptedException | ExecutionException ex) { 122 Main.warn(ex); 123 } 65 124 } 66 } 67 if (dialog.isDownloadGpxData()) { 68 DownloadGpsTask task = new DownloadGpsTask(); 69 task.setZoomAfterDownload(zoom && !dialog.isDownloadOsmData() && !dialog.isDownloadNotes()); 70 Future<?> future = task.download(dialog.isNewLayerRequired(), area, null); 71 Main.worker.submit(new PostDownloadHandler(task, future)); 72 if (zoom) { 73 tasks.add(new Pair<>(task, future)); 125 // Zoom to the larger download bounds 126 if (Main.map != null && bounds != null) { 127 final ProjectionBounds pb = bounds; 128 GuiHelper.runInEDTAndWait(() -> Main.map.mapView.zoomTo(new ViewportData(pb))); 74 129 } 75 } 76 if (dialog.isDownloadNotes()) { 77 DownloadNotesTask task = new DownloadNotesTask(); 78 task.setZoomAfterDownload(zoom && !dialog.isDownloadOsmData() && !dialog.isDownloadGpxData()); 79 Future<?> future = task.download(false, area, null); 80 Main.worker.submit(new PostDownloadHandler(task, future)); 81 if (zoom) { 82 tasks.add(new Pair<>(task, future)); 83 } 84 } 85 if (zoom && tasks.size() > 1) { 86 Main.worker.submit(() -> { 87 ProjectionBounds bounds = null; 88 // Wait for completion of download jobs 89 for (Pair<AbstractDownloadTask<?>, Future<?>> p : tasks) { 90 try { 91 p.b.get(); 92 ProjectionBounds b = p.a.getDownloadProjectionBounds(); 93 if (bounds == null) { 94 bounds = b; 95 } else if (b != null) { 96 bounds.extend(b); 97 } 98 } catch (InterruptedException | ExecutionException ex) { 99 Main.warn(ex); 100 } 101 } 102 // Zoom to the larger download bounds 103 if (Main.map != null && bounds != null) { 104 final ProjectionBounds pb = bounds; 105 GuiHelper.runInEDTAndWait(() -> Main.map.mapView.zoomTo(new ViewportData(pb))); 106 } 107 }); 108 } 130 }); 109 131 } 110 132 } -
trunk/src/org/openstreetmap/josm/actions/OverpassDownloadAction.java
r11658 r12574 7 7 import java.awt.BorderLayout; 8 8 import java.awt.Component; 9 import java.awt. GridLayout;10 import java.awt. Rectangle;9 import java.awt.Dimension; 10 import java.awt.GridBagLayout; 11 11 import java.awt.event.ActionEvent; 12 import java.awt.event.ActionListener;13 12 import java.awt.event.FocusEvent; 14 13 import java.awt.event.FocusListener; 15 14 import java.awt.event.KeyEvent; 16 15 import java.util.ArrayList; 16 import java.util.Arrays; 17 17 import java.util.Collection; 18 18 import java.util.Collections; 19 import java.util.Deque; 20 import java.util.LinkedList; 19 import java.util.Optional; 21 20 import java.util.concurrent.Future; 21 import java.util.function.Consumer; 22 22 23 23 import javax.swing.AbstractAction; … … 25 25 import javax.swing.ActionMap; 26 26 import javax.swing.JButton; 27 import javax.swing.J Component;27 import javax.swing.JEditorPane; 28 28 import javax.swing.JLabel; 29 import javax.swing.JMenuItem;30 29 import javax.swing.JOptionPane; 31 30 import javax.swing.JPanel; 32 import javax.swing.JPopupMenu;33 31 import javax.swing.JScrollPane; 32 import javax.swing.event.HyperlinkEvent; 34 33 import javax.swing.plaf.basic.BasicArrowButton; 34 import javax.swing.text.JTextComponent; 35 35 36 36 import org.openstreetmap.josm.Main; … … 38 38 import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler; 39 39 import org.openstreetmap.josm.data.Bounds; 40 import org.openstreetmap.josm.data.preferences.BooleanProperty; 40 41 import org.openstreetmap.josm.data.preferences.CollectionProperty; 41 import org.openstreetmap.josm.data.preferences.IntegerProperty; 42 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 42 import org.openstreetmap.josm.gui.ExtendedDialog; 43 43 import org.openstreetmap.josm.gui.download.DownloadDialog; 44 import org.openstreetmap.josm.gui.download.OverpassQueryList; 44 45 import org.openstreetmap.josm.gui.preferences.server.OverpassServerPreference; 45 46 import org.openstreetmap.josm.gui.util.GuiHelper; … … 48 49 import org.openstreetmap.josm.io.OverpassDownloadReader; 49 50 import org.openstreetmap.josm.tools.GBC; 50 import org.openstreetmap.josm.tools. InputMapUtils;51 import org.openstreetmap.josm.tools.OpenBrowser; 51 52 import org.openstreetmap.josm.tools.OverpassTurboQueryWizard; 52 53 import org.openstreetmap.josm.tools.Shortcut; … … 77 78 dialog.restoreSettings(); 78 79 dialog.setVisible(true); 79 if (!dialog.isCanceled()) { 80 dialog.rememberSettings(); 81 Bounds area = dialog.getSelectedDownloadArea(); 82 DownloadOsmTask task = new DownloadOsmTask(); 83 task.setZoomAfterDownload(dialog.isZoomToDownloadedDataRequired()); 84 Future<?> future = task.download( 85 new OverpassDownloadReader(area, OverpassServerPreference.getOverpassServer(), dialog.getOverpassQuery()), 86 dialog.isNewLayerRequired(), area, null); 87 Main.worker.submit(new PostDownloadHandler(task, future)); 88 } 80 81 if (dialog.isCanceled()) { 82 return; 83 } 84 85 dialog.rememberSettings(); 86 Optional<Bounds> selectedArea = dialog.getSelectedDownloadArea(); 87 String overpassQuery = dialog.getOverpassQuery(); 88 89 /* 90 * Absence of the selected area can be justified only if the overpass query 91 * is not restricted to bbox. 92 */ 93 if (!selectedArea.isPresent() && overpassQuery.contains("{{bbox}}")) { 94 JOptionPane.showMessageDialog( 95 dialog, 96 tr("Please select a download area first."), 97 tr("Error"), 98 JOptionPane.ERROR_MESSAGE 99 ); 100 return; 101 } 102 103 /* 104 * A callback that is passed to PostDownloadReporter that is called once the download task 105 * has finished. According to the number of errors happened, their type we decide whether we 106 * want to save the last query in OverpassQueryList. 107 */ 108 Consumer<Collection> errorReporter = (errors) -> { 109 110 boolean onlyNoDataError = errors.size() == 1 && 111 errors.contains("No data found in this area."); 112 113 if (errors.isEmpty() || onlyNoDataError) { 114 dialog.saveHistoricItemOnSuccess(); 115 } 116 }; 117 118 /* 119 * In order to support queries generated by the Overpass Turbo Query Wizard tool 120 * which do not require the area to be specified. 121 */ 122 Bounds area = selectedArea.orElseGet(() -> new Bounds(0, 0, 0, 0)); 123 DownloadOsmTask task = new DownloadOsmTask(); 124 task.setZoomAfterDownload(dialog.isZoomToDownloadedDataRequired()); 125 Future<?> future = task.download( 126 new OverpassDownloadReader(area, OverpassServerPreference.getOverpassServer(), dialog.getOverpassQuery()), 127 dialog.isNewLayerRequired(), area, null); 128 Main.worker.submit(new PostDownloadHandler(task, future, errorReporter)); 89 129 } 90 130 … … 122 162 private static final class OverpassDownloadDialog extends DownloadDialog { 123 163 124 private HistoryComboBox overpassWizard;125 164 private JosmTextArea overpassQuery; 165 private OverpassQueryList overpassQueryList; 126 166 private static OverpassDownloadDialog instance; 127 private static final CollectionProperty OVERPASS_WIZARD_HISTORY = new CollectionProperty("download.overpass.wizard",128 new ArrayList<String>());167 private static final BooleanProperty OVERPASS_QUERY_LIST_OPENED = 168 new BooleanProperty("download.overpass.query-list.opened", false); 129 169 130 170 private OverpassDownloadDialog(Component parent) { … … 146 186 @Override 147 187 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) { 188 // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes 189 pnl.add(new JLabel(), GBC.eol()); 148 190 149 191 DisableActionsFocusListener disableActionsFocusListener = 150 192 new DisableActionsFocusListener(slippyMapChooser.getNavigationComponentActionMap()); 151 193 152 pnl.add(new JLabel(), GBC.eol()); // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes 153 154 final String tooltip = tr("Builds an Overpass query using the Overpass Turbo query wizard"); 155 overpassWizard = new HistoryComboBox(); 156 overpassWizard.setToolTipText(tooltip); 157 overpassWizard.getEditorComponent().addFocusListener(disableActionsFocusListener); 158 final JButton buildQuery = new JButton(tr("Build query")); 159 final Action buildQueryAction = new AbstractAction() { 194 String tooltip = tr("Build an Overpass query using the Overpass Turbo Query Wizard tool"); 195 Action queryWizardAction = new AbstractAction() { 160 196 @Override 161 197 public void actionPerformed(ActionEvent e) { 162 final String overpassWizardText = overpassWizard.getText(); 163 try { 164 overpassQuery.setText(OverpassTurboQueryWizard.getInstance().constructQuery(overpassWizardText)); 165 } catch (UncheckedParseException ex) { 166 Main.error(ex); 167 HelpAwareOptionPane.showOptionDialog( 168 Main.parent, 169 tr("<html>The Overpass wizard could not parse the following query:" 170 + Utils.joinAsHtmlUnorderedList(Collections.singleton(overpassWizardText))), 171 tr("Parse error"), 172 JOptionPane.ERROR_MESSAGE, 173 null 174 ); 175 } 198 QueryWizardDialog.getInstance().showDialog(); 176 199 } 177 200 }; 178 buildQuery.addActionListener(buildQueryAction); 179 buildQuery.setToolTipText(tooltip); 180 pnl.add(buildQuery, GBC.std().insets(5, 5, 5, 5)); 181 pnl.add(overpassWizard, GBC.eol().fill(GBC.HORIZONTAL)); 182 InputMapUtils.addEnterAction(overpassWizard.getEditorComponent(), buildQueryAction); 183 184 overpassQuery = new JosmTextArea("", 8, 80); 185 overpassQuery.setFont(GuiHelper.getMonospacedFont(overpassQuery)); 186 overpassQuery.addFocusListener(disableActionsFocusListener); 201 202 JButton openQueryWizard = new JButton("Query Wizard"); 203 openQueryWizard.setToolTipText(tooltip); 204 openQueryWizard.addActionListener(queryWizardAction); 205 206 // CHECKSTYLE.OFF: LineLength 207 this.overpassQuery = new JosmTextArea( 208 "/*\n" + 209 tr("Place your Overpass query below or generate one using the Overpass Turbo Query Wizard") 210 + "\n*/", 211 8, 80); 212 // CHECKSTYLE.ON: LineLength 213 this.overpassQuery.setFont(GuiHelper.getMonospacedFont(overpassQuery)); 214 this.overpassQuery.addFocusListener(disableActionsFocusListener); 215 this.overpassQuery.addFocusListener(new FocusListener() { 216 @Override 217 public void focusGained(FocusEvent e) { 218 overpassQuery.selectAll(); 219 } 220 221 @Override 222 public void focusLost(FocusEvent e) { 223 224 } 225 }); 226 227 this.overpassQueryList = new OverpassQueryList(this, this.overpassQuery); 228 overpassQueryList.setToolTipText(tr("Show/hide Overpass snippet list")); 229 overpassQueryList.setVisible(OVERPASS_QUERY_LIST_OPENED.get()); 230 overpassQueryList.setPreferredSize(new Dimension(350, 300)); 187 231 JScrollPane scrollPane = new JScrollPane(overpassQuery); 188 final JPanel pane = new JPanel(new BorderLayout()); 189 final BasicArrowButton arrowButton = new BasicArrowButton(BasicArrowButton.SOUTH); 190 arrowButton.addActionListener(new AbstractAction() { 191 @Override 192 public void actionPerformed(ActionEvent e) { 193 OverpassQueryHistoryPopup.show(arrowButton, OverpassDownloadDialog.this); 232 BasicArrowButton arrowButton = new BasicArrowButton(overpassQueryList.isVisible() 233 ? BasicArrowButton.EAST 234 : BasicArrowButton.WEST); 235 arrowButton.addActionListener(e -> { 236 if (overpassQueryList.isVisible()) { 237 overpassQueryList.setVisible(false); 238 arrowButton.setDirection(BasicArrowButton.WEST); 239 OVERPASS_QUERY_LIST_OPENED.put(false); 240 } else { 241 overpassQueryList.setVisible(true); 242 arrowButton.setDirection(BasicArrowButton.EAST); 243 OVERPASS_QUERY_LIST_OPENED.put(false); 194 244 } 195 245 }); 196 pane.add(scrollPane, BorderLayout.CENTER); 197 pane.add(arrowButton, BorderLayout.EAST); 198 pnl.add(new JLabel(tr("Overpass query: ")), GBC.std().insets(5, 5, 5, 5)); 199 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL); 200 gbc.ipady = 200; 246 247 JPanel innerPanel = new JPanel(new BorderLayout()); 248 innerPanel.add(scrollPane, BorderLayout.CENTER); 249 innerPanel.add(arrowButton, BorderLayout.EAST); 250 251 JPanel pane = new JPanel(new BorderLayout()); 252 pane.add(innerPanel, BorderLayout.CENTER); 253 pane.add(overpassQueryList, BorderLayout.EAST); 254 255 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL); gbc.ipady = 200; 256 pnl.add(openQueryWizard, GBC.std().insets(5, 5, 5, 5)); 201 257 pnl.add(pane, gbc); 202 203 } 204 205 public String getOverpassQuery() { 258 } 259 260 String getOverpassQuery() { 206 261 return overpassQuery.getText(); 207 262 } 208 263 209 publicvoid setOverpassQuery(String text) {264 void setOverpassQuery(String text) { 210 265 overpassQuery.setText(text); 211 266 } 212 267 213 @Override 214 public void restoreSettings() { 215 super.restoreSettings(); 216 overpassWizard.setPossibleItems(OVERPASS_WIZARD_HISTORY.get()); 217 } 218 219 @Override 220 public void rememberSettings() { 221 super.rememberSettings(); 222 overpassWizard.addCurrentItemToHistory(); 223 OVERPASS_WIZARD_HISTORY.put(overpassWizard.getHistory()); 224 OverpassQueryHistoryPopup.addToHistory(getOverpassQuery()); 268 /** 269 * Adds the current query to {@link OverpassQueryList}. 270 */ 271 void saveHistoricItemOnSuccess() { 272 overpassQueryList.saveHistoricItem(overpassQuery.getText()); 225 273 } 226 274 … … 229 277 displaySizeCheckResult(false); 230 278 } 279 280 /** 281 * Triggers the download action to fire. 282 */ 283 private void triggerDownload() { 284 super.btnDownload.doClick(); 285 } 231 286 } 232 287 233 static class OverpassQueryHistoryPopup extends JPopupMenu { 234 235 static final CollectionProperty OVERPASS_QUERY_HISTORY = new CollectionProperty("download.overpass.query", new ArrayList<String>()); 236 static final IntegerProperty OVERPASS_QUERY_HISTORY_SIZE = new IntegerProperty("download.overpass.query.size", 12); 237 238 OverpassQueryHistoryPopup(final OverpassDownloadDialog dialog) { 239 final Collection<String> history = OVERPASS_QUERY_HISTORY.get(); 240 setLayout(new GridLayout((int) Math.ceil(history.size() / 2.), 2)); 241 for (final String i : history) { 242 add(new OverpassQueryHistoryItem(i, dialog)); 243 } 244 } 245 246 static void show(final JComponent parent, final OverpassDownloadDialog dialog) { 247 final OverpassQueryHistoryPopup menu = new OverpassQueryHistoryPopup(dialog); 248 final Rectangle r = parent.getBounds(); 249 menu.show(parent.getParent(), r.x + r.width - (int) menu.getPreferredSize().getWidth(), r.y + r.height); 250 } 251 252 static void addToHistory(final String query) { 253 final Deque<String> history = new LinkedList<>(OVERPASS_QUERY_HISTORY.get()); 254 if (!history.contains(query)) { 255 history.add(query); 256 } 257 while (history.size() > OVERPASS_QUERY_HISTORY_SIZE.get()) { 258 history.removeFirst(); 259 } 260 OVERPASS_QUERY_HISTORY.put(history); 288 private static final class QueryWizardDialog extends ExtendedDialog { 289 290 private static QueryWizardDialog dialog; 291 private final HistoryComboBox queryWizard; 292 private final OverpassTurboQueryWizard overpassQueryBuilder; 293 private static final CollectionProperty OVERPASS_WIZARD_HISTORY = 294 new CollectionProperty("download.overpass.wizard", new ArrayList<String>()); 295 296 // dialog buttons 297 private static final int BUILD_QUERY = 0; 298 private static final int BUILD_AN_EXECUTE_QUERY = 1; 299 private static final int CANCEL = 2; 300 301 /** 302 * Get an instance of {@link QueryWizardDialog}. 303 * @return The instance 304 */ 305 public static QueryWizardDialog getInstance() { 306 if (dialog == null) { 307 dialog = new QueryWizardDialog(); 308 } 309 310 return dialog; 311 } 312 313 private static final String DESCRIPTION_STYLE = 314 "<style type=\"text/css\">\n" 315 + "table { border-spacing: 0pt;}\n" 316 + "h3 {text-align: center; padding: 8px;}\n" 317 + "td {border: 1px solid #dddddd; text-align: left; padding: 8px;}\n" 318 + "#desc {width: 350px;}" 319 + "</style>\n"; 320 321 private QueryWizardDialog() { 322 super(OverpassDownloadDialog.getInstance(), tr("Overpass Turbo Query Wizard"), 323 tr("Build query"), tr("Build query and execute"), tr("Cancel")); 324 325 this.queryWizard = new HistoryComboBox(); 326 this.overpassQueryBuilder = OverpassTurboQueryWizard.getInstance(); 327 328 JPanel panel = new JPanel(new GridBagLayout()); 329 330 JLabel searchLabel = new JLabel(tr("Search :")); 331 JTextComponent descPane = this.buildDescriptionSection(); 332 JScrollPane scroll = GuiHelper.embedInVerticalScrollPane(descPane); 333 scroll.getVerticalScrollBar().setUnitIncrement(10); // make scrolling smooth 334 335 panel.add(searchLabel, GBC.std().insets(0, 0, 0, 20).anchor(GBC.SOUTHEAST)); 336 panel.add(queryWizard, GBC.eol().insets(0, 0, 0, 15).fill(GBC.HORIZONTAL).anchor(GBC.SOUTH)); 337 panel.add(scroll, GBC.eol().fill(GBC.BOTH).anchor(GBC.CENTER)); 338 339 queryWizard.setPossibleItems(OVERPASS_WIZARD_HISTORY.get()); 340 341 setCancelButton(CANCEL); 342 setDefaultButton(BUILD_AN_EXECUTE_QUERY + 1); // Build and execute button 343 setContent(panel, false); 344 } 345 346 @Override 347 public void buttonAction(int buttonIndex, ActionEvent evt) { 348 switch (buttonIndex) { 349 case BUILD_QUERY: 350 if (this.buildQueryAction()) { 351 this.saveHistory(); 352 super.buttonAction(BUILD_QUERY, evt); 353 } 354 break; 355 case BUILD_AN_EXECUTE_QUERY: 356 if (this.buildQueryAction()) { 357 this.saveHistory(); 358 super.buttonAction(BUILD_AN_EXECUTE_QUERY, evt); 359 360 OverpassDownloadDialog.getInstance().triggerDownload(); 361 } 362 break; 363 default: 364 super.buttonAction(buttonIndex, evt); 365 366 } 367 } 368 369 /** 370 * Saves the latest, successfully parsed search term. 371 */ 372 private void saveHistory() { 373 queryWizard.addCurrentItemToHistory(); 374 OVERPASS_WIZARD_HISTORY.put(queryWizard.getHistory()); 375 } 376 377 /** 378 * Tries to process a search term using {@link OverpassTurboQueryWizard}. If the term cannot 379 * be parsed, the the corresponding dialog is shown. 380 * @param searchTerm The search term to parse. 381 * @return {@link Optional#empty()} if an exception was thrown when parsing, meaning 382 * that the term cannot be processed, or non-empty {@link Optional} containing the result 383 * of parsing. 384 */ 385 private Optional<String> tryParseSearchTerm(String searchTerm) { 386 try { 387 String query = this.overpassQueryBuilder.constructQuery(searchTerm); 388 389 return Optional.of(query); 390 } catch (UncheckedParseException ex) { 391 Main.error(ex); 392 JOptionPane.showMessageDialog( 393 OverpassDownloadDialog.getInstance(), 394 "<html>" + 395 tr("The Overpass wizard could not parse the following query:") + 396 Utils.joinAsHtmlUnorderedList(Collections.singleton(searchTerm)) + 397 "</html>", 398 tr("Parse error"), 399 JOptionPane.ERROR_MESSAGE 400 ); 401 402 return Optional.empty(); 403 } 404 } 405 406 /** 407 * Builds an Overpass query out from {@link QueryWizardDialog#queryWizard} contents. 408 * @return {@code true} if the query successfully built, {@code false} otherwise. 409 */ 410 private boolean buildQueryAction() { 411 final String wizardSearchTerm = this.queryWizard.getText(); 412 413 Optional<String> q = this.tryParseSearchTerm(wizardSearchTerm); 414 if (q.isPresent()) { 415 String query = q.get(); 416 OverpassDownloadDialog.getInstance().setOverpassQuery(query); 417 418 return true; 419 } 420 421 return false; 422 } 423 424 private JTextComponent buildDescriptionSection() { 425 JEditorPane descriptionSection = new JEditorPane("text/html", this.getDescriptionContent()); 426 descriptionSection.setEditable(false); 427 descriptionSection.addHyperlinkListener(e -> { 428 if (HyperlinkEvent.EventType.ACTIVATED.equals(e.getEventType())) { 429 OpenBrowser.displayUrl(e.getURL().toString()); 430 } 431 }); 432 433 return descriptionSection; 434 } 435 436 private String getDescriptionContent() { 437 return new StringBuilder("<html>") 438 .append(DESCRIPTION_STYLE) 439 .append("<body>") 440 .append("<h3>") 441 .append(tr("Query Wizard")) 442 .append("</h3>") 443 .append("<p>") 444 .append(tr("Allows you to interact with <i>Overpass API</i> by writing declarative, human-readable terms.")) 445 .append(tr("The <i>Query Wizard</i> tool will transform those to a valid overpass query.")) 446 .append(tr("For more detailed description see ")) 447 .append(tr("<a href=\"{0}\">OSM Wiki</a>.", Main.getOSMWebsite() + "/wiki/Overpass_turbo/Wizard")) 448 .append("</p>") 449 .append("<h3>").append(tr("Hints")).append("</h3>") 450 .append("<table>").append("<tr>").append("<td>") 451 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>type:node</i>", "<i>type:relation</i>", "<i>type:way</i>"))) 452 .append("</td>").append("<td>") 453 .append("<span>").append(tr("Download objects of a certain type.")).append("</span>") 454 .append("</td>").append("</tr>") 455 .append("<tr>").append("<td>") 456 .append(Utils.joinAsHtmlUnorderedList( 457 Arrays.asList("<i>key=value in <u>location</u></i>", 458 "<i>key=value around <u>location</u></i>", 459 "<i>key=value in bbox</i>"))) 460 .append("</td>").append("<td>") 461 .append(tr("Download object by specifying a specific location. For example,")) 462 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList( 463 tr("{0} all objects having {1} as attribute are downloaded.", "<i>tourism=hotel in Berlin</i> -", "'tourism=hotel'"), 464 tr("{0} all object with the corresponding key/value pair located around Berlin. Note, the default value for radius "+ 465 "is set to 1000m, but it can be changed in the generated query.", "<i>tourism=hotel around Berlin</i> -"), 466 tr("{0} all objects within the current selection that have {1} as attribute.", "<i>tourism=hotel in bbox</i> -", 467 "'tourism=hotel'")))) 468 .append("<span>") 469 .append(tr("Instead of <i>location</i> any valid place name can be used like address, city, etc.")) 470 .append("</span>") 471 .append("</td>").append("</tr>") 472 .append("<tr>").append("<td>") 473 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>key=value</i>", "<i>key=*</i>", "<i>key~regex</i>", 474 "<i>key!=value</i>", "<i>key!~regex</i>", "<i>key=\"combined value\"</i>"))) 475 .append("</td>").append("<td>") 476 .append(tr("<span>Download objects that have some concrete key/value pair, only the key with any contents for the value, " + 477 "the value matching some regular expression. 'Not equal' operators are supported as well.</span>")) 478 .append("</td>").append("</tr>") 479 .append("<tr>").append("<td>") 480 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList( 481 tr("<i>expression1 {0} expression2</i>", "or"), 482 tr("<i>expression1 {0} expression2</i>", "and")))) 483 .append("</td>").append("<td>") 484 .append("<span>") 485 .append(tr("Basic logical operators can be used to create more sophisticated queries. Instead of 'or' - '|', '||' " + 486 "can be used, and instead of 'and' - '&', '&&'.")) 487 .append("</span>") 488 .append("</td>").append("</tr>").append("</table>") 489 .append("</body>") 490 .append("</html>") 491 .toString(); 261 492 } 262 493 } 263 264 static class OverpassQueryHistoryItem extends JMenuItem implements ActionListener {265 266 final String query;267 final OverpassDownloadDialog dialog;268 269 OverpassQueryHistoryItem(final String query, final OverpassDownloadDialog dialog) {270 this.query = query;271 this.dialog = dialog;272 setText("<html><pre style='width:300px;'>" +273 Utils.escapeReservedCharactersHTML(Utils.restrictStringLines(query, 7)));274 addActionListener(this);275 }276 277 @Override278 public void actionPerformed(ActionEvent e) {279 dialog.setOverpassQuery(query);280 }281 }282 283 494 } -
trunk/src/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandler.java
r12307 r12574 12 12 import java.util.concurrent.ExecutionException; 13 13 import java.util.concurrent.Future; 14 import java.util.function.Consumer; 14 15 15 16 import javax.swing.JOptionPane; … … 29 30 private final DownloadTask task; 30 31 private final Future<?> future; 32 private Consumer<Collection> errorReporter; 31 33 32 34 /** … … 38 40 this.task = task; 39 41 this.future = future; 42 } 43 44 /** 45 * constructor 46 * @param task the asynchronous download task 47 * @param future the future on which the completion of the download task can be synchronized 48 * @param errorReporter a callback to inform about the number errors happened during the download 49 * task 50 */ 51 public PostDownloadHandler(DownloadTask task, Future<?> future, Consumer<Collection> errorReporter) { 52 this(task, future); 53 this.errorReporter = errorReporter; 40 54 } 41 55 … … 54 68 // 55 69 Set<Object> errors = new LinkedHashSet<>(task.getErrorObjects()); 56 if (errors.isEmpty()) 70 if (this.errorReporter != null) { 71 errorReporter.accept(errors); 72 } 73 74 if (errors.isEmpty()) { 57 75 return; 76 } 58 77 59 78 // just one error object? -
trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java
r12523 r12574 20 20 import java.util.ArrayList; 21 21 import java.util.List; 22 import java.util.Optional; 22 23 23 24 import javax.swing.AbstractAction; … … 458 459 459 460 /** 460 * Replies the currently selected download area. 461 * @return the currently selected download area. May be {@code null}, if no download area is selected yet. 462 */ 463 public Bounds getSelectedDownloadArea() { 464 return currentBounds; 461 * Returns an {@link Optional} of the currently selected download area. 462 * @return An {@link Optional} of the currently selected download area. 463 * @since 12574 Return type changed to optional 464 */ 465 public Optional<Bounds> getSelectedDownloadArea() { 466 return Optional.ofNullable(currentBounds); 465 467 } 466 468 … … 525 527 526 528 public void run() { 527 if (currentBounds == null) { 528 JOptionPane.showMessageDialog( 529 DownloadDialog.this, 530 tr("Please select a download area first."), 531 tr("Error"), 532 JOptionPane.ERROR_MESSAGE 533 ); 534 return; 535 } 529 /* 530 * Checks if the user selected the type of data to download. At least one the following 531 * must be chosen : raw osm data, gpx data, notes. 532 * If none of those are selected, then the corresponding dialog is shown to inform the user. 533 */ 536 534 if (!isDownloadOsmData() && !isDownloadGpxData() && !isDownloadNotes()) { 537 535 JOptionPane.showMessageDialog( 538 536 DownloadDialog.this, 539 537 tr("<html>Neither <strong>{0}</strong> nor <strong>{1}</strong> nor <strong>{2}</strong> is enabled.<br>" 540 + "Please choose to either download OSM data, or GPX data, or Notes, or all.</html>",538 + "Please choose to either download OSM data, or GPX data, or Notes, or all.</html>", 541 539 cbDownloadOsmData.getText(), 542 540 cbDownloadGpxData.getText(), … … 548 546 return; 549 547 } 548 550 549 setCanceled(false); 551 550 setVisible(false);
Note:
See TracChangeset
for help on using the changeset viewer.