Changeset 12609 in josm
- Timestamp:
- 2017-08-16T22:08:22+02:00 (7 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/OverpassDownloadAction.java
r12608 r12609 8 8 import java.awt.Component; 9 9 import java.awt.Dimension; 10 import java.awt.GridBagLayout; 10 11 import java.awt.event.ActionEvent; 11 12 import java.awt.event.FocusEvent; … … 25 26 import javax.swing.JPanel; 26 27 import javax.swing.JScrollPane; 28 import javax.swing.event.ListSelectionEvent; 29 import javax.swing.event.ListSelectionListener; 27 30 import javax.swing.plaf.basic.BasicArrowButton; 28 31 … … 41 44 import org.openstreetmap.josm.io.OverpassDownloadReader; 42 45 import org.openstreetmap.josm.tools.GBC; 46 import org.openstreetmap.josm.tools.ImageProvider; 43 47 import org.openstreetmap.josm.tools.Shortcut; 44 48 … … 159 163 private static final BooleanProperty OVERPASS_QUERY_LIST_OPENED = 160 164 new BooleanProperty("download.overpass.query-list.opened", false); 165 private static final String ACTION_IMG_SUBDIR = "dialogs"; 161 166 162 167 private OverpassDownloadDialog(Component parent) { … … 178 183 @Override 179 184 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) { 180 // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes181 pnl.add(new JLabel(), GBC.eol());182 183 185 DisableActionsFocusListener disableActionsFocusListener = 184 186 new DisableActionsFocusListener(slippyMapChooser.getNavigationComponentActionMap()); … … 192 194 }; 193 195 194 JButton openQueryWizard = new JButton( "Query Wizard");196 JButton openQueryWizard = new JButton(tr("Query Wizard")); 195 197 openQueryWizard.setToolTipText(tooltip); 196 198 openQueryWizard.addActionListener(queryWizardAction); 199 200 // use eol() that is needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes 201 pnl.add(openQueryWizard, GBC.eol()); 202 pnl.add(new JLabel(tr("Overpass query:")), GBC.std().insets(5, 5, 0, 0).anchor(GBC.NORTHWEST)); 197 203 198 204 // CHECKSTYLE.OFF: LineLength … … 217 223 }); 218 224 225 219 226 this.overpassQueryList = new OverpassQueryList(this, this.overpassQuery); 220 overpassQueryList.setToolTipText(tr("Show/hide Overpass snippet list")); 221 overpassQueryList.setVisible(OVERPASS_QUERY_LIST_OPENED.get()); 222 overpassQueryList.setPreferredSize(new Dimension(350, 300)); 227 this.overpassQueryList.setPreferredSize(new Dimension(350, 300)); 228 229 EditSnippetAction edit = new EditSnippetAction(); 230 RemoveSnippetAction remove = new RemoveSnippetAction(); 231 this.overpassQueryList.addSelectionListener(edit); 232 this.overpassQueryList.addSelectionListener(remove); 233 234 JPanel listPanel = new JPanel(new GridBagLayout()); 235 listPanel.add(new JLabel(tr("Your saved queries:")), GBC.eol().insets(2).anchor(GBC.CENTER)); 236 listPanel.add(this.overpassQueryList, GBC.eol().fill(GBC.BOTH)); 237 listPanel.add(new JButton(new AddSnippetAction()), GBC.std().fill(GBC.HORIZONTAL)); 238 listPanel.add(new JButton(edit), GBC.std().fill(GBC.HORIZONTAL)); 239 listPanel.add(new JButton(remove), GBC.std().fill(GBC.HORIZONTAL)); 240 listPanel.setVisible(OVERPASS_QUERY_LIST_OPENED.get()); 241 223 242 JScrollPane scrollPane = new JScrollPane(overpassQuery); 224 BasicArrowButton arrowButton = new BasicArrowButton( overpassQueryList.isVisible()243 BasicArrowButton arrowButton = new BasicArrowButton(listPanel.isVisible() 225 244 ? BasicArrowButton.EAST 226 245 : BasicArrowButton.WEST); 246 arrowButton.setToolTipText(tr("Show/hide Overpass snippet list")); 227 247 arrowButton.addActionListener(e -> { 228 if ( overpassQueryList.isVisible()) {229 overpassQueryList.setVisible(false);248 if (listPanel.isVisible()) { 249 listPanel.setVisible(false); 230 250 arrowButton.setDirection(BasicArrowButton.WEST); 231 251 OVERPASS_QUERY_LIST_OPENED.put(Boolean.FALSE); 232 252 } else { 233 overpassQueryList.setVisible(true);253 listPanel.setVisible(true); 234 254 arrowButton.setDirection(BasicArrowButton.EAST); 235 OVERPASS_QUERY_LIST_OPENED.put(Boolean. FALSE);255 OVERPASS_QUERY_LIST_OPENED.put(Boolean.TRUE); 236 256 } 237 257 }); … … 243 263 JPanel pane = new JPanel(new BorderLayout()); 244 264 pane.add(innerPanel, BorderLayout.CENTER); 245 pane.add( overpassQueryList, BorderLayout.EAST);265 pane.add(listPanel, BorderLayout.EAST); 246 266 247 267 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL); gbc.ipady = 200; 248 pnl.add(openQueryWizard, GBC.std().insets(5, 5, 5, 5));249 268 pnl.add(pane, gbc); 250 269 } 251 270 252 String getOverpassQuery() {271 public String getOverpassQuery() { 253 272 return overpassQuery.getText(); 254 273 } … … 310 329 super.btnDownload.doClick(); 311 330 } 331 332 /** 333 * Action that delegates snippet creation to {@link OverpassQueryList#createNewItem()}. 334 */ 335 class AddSnippetAction extends AbstractAction { 336 337 /** 338 * Constructs a new {@code AddSnippetAction}. 339 */ 340 AddSnippetAction() { 341 super(); 342 putValue(SMALL_ICON, ImageProvider.get(ACTION_IMG_SUBDIR, "add")); 343 putValue(SHORT_DESCRIPTION, tr("Add new snippet")); 344 } 345 346 @Override 347 public void actionPerformed(ActionEvent e) { 348 overpassQueryList.createNewItem(); 349 } 350 } 351 352 /** 353 * Action that delegates snippet removal to {@link OverpassQueryList#removeSelectedItem()}. 354 */ 355 class RemoveSnippetAction extends AbstractAction implements ListSelectionListener { 356 357 /** 358 * Constructs a new {@code RemoveSnippetAction}. 359 */ 360 RemoveSnippetAction() { 361 super(); 362 putValue(SMALL_ICON, ImageProvider.get(ACTION_IMG_SUBDIR, "delete")); 363 putValue(SHORT_DESCRIPTION, tr("Delete selected snippet")); 364 checkEnabled(); 365 } 366 367 @Override 368 public void actionPerformed(ActionEvent e) { 369 overpassQueryList.removeSelectedItem(); 370 } 371 372 /** 373 * Disables the action if no items are selected. 374 */ 375 void checkEnabled() { 376 setEnabled(overpassQueryList.getSelectedItem().isPresent()); 377 } 378 379 @Override 380 public void valueChanged(ListSelectionEvent e) { 381 checkEnabled(); 382 } 383 } 384 385 /** 386 * Action that delegates snippet edit to {@link OverpassQueryList#editSelectedItem()}. 387 */ 388 class EditSnippetAction extends AbstractAction implements ListSelectionListener { 389 390 /** 391 * Constructs a new {@code EditSnippetAction}. 392 */ 393 EditSnippetAction() { 394 super(); 395 putValue(SMALL_ICON, ImageProvider.get(ACTION_IMG_SUBDIR, "edit")); 396 putValue(SHORT_DESCRIPTION, tr("Edit selected snippet")); 397 checkEnabled(); 398 } 399 400 @Override 401 public void actionPerformed(ActionEvent e) { 402 overpassQueryList.editSelectedItem(); 403 } 404 405 /** 406 * Disables the action if no items are selected. 407 */ 408 void checkEnabled() { 409 setEnabled(overpassQueryList.getSelectedItem().isPresent()); 410 } 411 412 @Override 413 public void valueChanged(ListSelectionEvent e) { 414 checkEnabled(); 415 } 416 } 312 417 } 313 418 } -
trunk/src/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandler.java
r12575 r12609 20 20 import org.openstreetmap.josm.gui.ExceptionDialogUtil; 21 21 import org.openstreetmap.josm.gui.Notification; 22 import org.openstreetmap.josm.gui.util.GuiHelper; 22 23 import org.openstreetmap.josm.tools.ExceptionUtil; 23 24 import org.openstreetmap.josm.tools.Utils; … … 68 69 // 69 70 Set<Object> errors = new LinkedHashSet<>(task.getErrorObjects()); 71 70 72 if (this.errorReporter != null) { 71 errorReporter.accept(errors);73 GuiHelper.runInEDT(() -> errorReporter.accept(errors)); 72 74 } 73 75 -
trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryList.java
r12578 r12609 16 16 import java.time.LocalDateTime; 17 17 import java.time.format.DateTimeFormatter; 18 import java.time.format.DateTimeParseException; 18 19 import java.util.ArrayList; 19 20 import java.util.Collection; 20 21 import java.util.Collections; 21 22 import java.util.HashMap; 23 import java.util.List; 22 24 import java.util.Locale; 23 25 import java.util.Map; … … 74 76 private static final String KEY_KEY = "key"; 75 77 private static final String QUERY_KEY = "query"; 76 private static final String USE_COUNT_KEY = "useCount";78 private static final String LAST_EDIT_KEY = "lastEdit"; 77 79 private static final String PREFERENCE_ITEMS = "download.overpass.query"; 80 81 private static final String TRANSLATED_HISTORY = tr("history"); 78 82 79 83 /** … … 103 107 public synchronized Optional<SelectorItem> getSelectedItem() { 104 108 int idx = lsResult.getSelectedIndex(); 105 if (lsResultModel.getSize() == 0|| idx == -1) {109 if (lsResultModel.getSize() <= idx || idx == -1) { 106 110 return Optional.empty(); 107 111 } 108 112 109 113 SelectorItem item = lsResultModel.getElementAt(idx); 110 item.increaseUsageCount();111 112 this.items.values().stream()113 .filter(it -> !it.getKey().equals(item.getKey()))114 .forEach(SelectorItem::decreaseUsageCount);115 114 116 115 filterItems(); … … 128 127 public synchronized void saveHistoricItem(String query) { 129 128 boolean historicExist = this.items.values().stream() 130 .filter(it -> it.getKey().contains("history"))131 129 .map(SelectorItem::getQuery) 132 130 .anyMatch(q -> q.equals(query)); … … 134 132 if (!historicExist) { 135 133 SelectorItem item = new SelectorItem( 136 "history " + LocalDateTime.now().format(FORMAT), 137 query); 134 TRANSLATED_HISTORY + " " + LocalDateTime.now().format(FORMAT), query); 138 135 139 136 this.items.put(item.getKey(), item); … … 148 145 * updates the view. 149 146 */ 150 p rivatesynchronized void removeSelectedItem() {147 public synchronized void removeSelectedItem() { 151 148 Optional<SelectorItem> it = this.getSelectedItem(); 152 149 … … 160 157 SelectorItem item = it.get(); 161 158 if (this.items.remove(item.getKey(), item)) { 159 clearSelection(); 162 160 savePreferences(); 163 161 filterItems(); … … 169 167 * to preferences and updates the view. 170 168 */ 171 p rivatesynchronized void editSelectedItem() {169 public synchronized void editSelectedItem() { 172 170 Optional<SelectorItem> it = this.getSelectedItem(); 173 171 … … 185 183 tr("Edit item"), 186 184 item, 187 tr("Save") );185 tr("Save"), tr("Cancel")); 188 186 dialog.showDialog(); 189 187 … … 202 200 * and updates the view. 203 201 */ 204 p rivatesynchronized void createNewItem() {202 public synchronized void createNewItem() { 205 203 EditItemDialog dialog = new EditItemDialog(componentParent, tr("Add snippet"), tr("Add")); 206 204 dialog.showDialog(); … … 208 206 Optional<SelectorItem> newItem = dialog.getOutputItem(); 209 207 newItem.ifPresent(i -> { 210 items.put(i.getKey(), new SelectorItem(i.getKey(), i.getQuery()));208 items.put(i.getKey(), i); 211 209 savePreferences(); 212 210 filterItems(); … … 222 220 protected void filterItems() { 223 221 String text = edSearchText.getText().toLowerCase(Locale.ENGLISH); 224 225 super.lsResultModel.setItems(this.items.values().stream()222 List<SelectorItem> matchingItems = this.items.values().stream() 223 .sorted((i1, i2) -> i2.getLastEdit().compareTo(i1.getLastEdit())) 226 224 .filter(item -> item.getKey().contains(text)) 227 .collect(Collectors.toList())); 225 .collect(Collectors.toList()); 226 227 super.lsResultModel.setItems(matchingItems); 228 228 } 229 229 … … 248 248 it.put(KEY_KEY, item.getKey()); 249 249 it.put(QUERY_KEY, item.getQuery()); 250 it.put( USE_COUNT_KEY, Integer.toString(item.getUsageCount()));250 it.put(LAST_EDIT_KEY, item.getLastEdit().format(FORMAT)); 251 251 252 252 toSave.add(it); … … 266 266 267 267 for (Map<String, String> entry : toRetrieve) { 268 String key = entry.get(KEY_KEY); 269 String query = entry.get(QUERY_KEY); 270 int usageCount = Integer.parseInt(entry.get(USE_COUNT_KEY)); 271 272 result.put(key, new SelectorItem(key, query, usageCount)); 268 try { 269 String key = entry.get(KEY_KEY); 270 String query = entry.get(QUERY_KEY); 271 String lastEditText = entry.get(LAST_EDIT_KEY); 272 // Compatibility: Some entries may not have a last edit set. 273 LocalDateTime lastEdit = lastEditText == null ? LocalDateTime.MIN : LocalDateTime.parse(lastEditText, FORMAT); 274 275 result.put(key, new SelectorItem(key, query, lastEdit)); 276 } catch (IllegalArgumentException | DateTimeParseException e) { 277 // skip any corrupted item 278 Main.error(e); 279 } 273 280 } 274 281 … … 412 419 private final JTextField name; 413 420 private final JosmTextArea query; 414 private final int initialNameHash;415 421 416 422 private final transient AbstractTextComponentValidator queryValidator; … … 419 425 private static final int SUCCESS_BTN = 0; 420 426 private static final int CANCEL_BTN = 1; 427 428 private final transient SelectorItem itemToEdit; 421 429 422 430 /** … … 437 445 super(parent, title, buttonTexts); 438 446 439 String nameToEdit = itemToEdit != null ? itemToEdit.getKey() : ""; 440 String queryToEdit = itemToEdit != null ? itemToEdit.getQuery() : ""; 441 this.initialNameHash = nameToEdit.hashCode(); 447 this.itemToEdit = itemToEdit; 448 449 String nameToEdit = itemToEdit == null ? "" : itemToEdit.getKey(); 450 String queryToEdit = itemToEdit == null ? "" : itemToEdit.getQuery(); 442 451 443 452 this.name = new JTextField(nameToEdit); … … 458 467 public boolean isValid() { 459 468 String currentName = name.getText(); 460 int currentHash = currentName.hashCode(); 461 462 return !Utils.isStripEmpty(currentName) && 463 !(currentHash != initialNameHash && 464 items.containsKey(currentName)); 469 470 boolean notEmpty = !Utils.isStripEmpty(currentName); 471 boolean exist = !currentName.equals(nameToEdit) && 472 items.containsKey(currentName); 473 474 return notEmpty && !exist; 465 475 } 466 476 }; … … 478 488 panel.add(queryScrollPane, constraint); 479 489 480 setDefaultButton(SUCCESS_BTN );481 setCancelButton(CANCEL_BTN );490 setDefaultButton(SUCCESS_BTN + 1); 491 setCancelButton(CANCEL_BTN + 1); 482 492 setPreferredSize(new Dimension(400, 400)); 483 493 setContent(panel, false); … … 501 511 tr("Warning"), 502 512 JOptionPane.WARNING_MESSAGE); 513 514 return; 503 515 } else if (!this.queryValidator.isValid()) { 504 516 JOptionPane.showMessageDialog( … … 507 519 tr("Warning"), 508 520 JOptionPane.WARNING_MESSAGE); 509 } else { 510 this.outputItem = Optional.of(new SelectorItem(this.name.getText(), this.query.getText())); 511 super.buttonAction(buttonIndex, evt); 512 } 513 } else { 514 super.buttonAction(buttonIndex, evt); 515 } 521 522 return; 523 } else if (this.itemToEdit != null) { // editing the item 524 String newKey = this.name.getText(); 525 String newQuery = this.query.getText(); 526 527 String itemKey = this.itemToEdit.getKey(); 528 String itemQuery = this.itemToEdit.getQuery(); 529 530 this.outputItem = Optional.of(new SelectorItem( 531 this.name.getText(), 532 this.query.getText(), 533 !newKey.equals(itemKey) || !newQuery.equals(itemQuery) 534 ? LocalDateTime.now() 535 : this.itemToEdit.getLastEdit())); 536 537 } else { // creating new 538 this.outputItem = Optional.of(new SelectorItem( 539 this.name.getText(), 540 this.query.getText())); 541 } 542 } 543 544 super.buttonAction(buttonIndex, evt); 516 545 } 517 546 } … … 524 553 private final String itemKey; 525 554 private final String query; 526 private int usageCount;555 private final LocalDateTime lastEdit; 527 556 528 557 /** … … 534 563 */ 535 564 public SelectorItem(String key, String query) { 536 this(key, query, 1);565 this(key, query, LocalDateTime.now()); 537 566 } 538 567 … … 541 570 * @param key The key of this item. 542 571 * @param query The query of the item. 543 * @param usageCount The number of times this query was used.572 * @param lastEdit The latest when the item was 544 573 * @exception NullPointerException if any parameter is {@code null}. 545 574 * @exception IllegalArgumentException if any parameter is empty. 546 575 */ 547 public SelectorItem(String key, String query, int usageCount) { 548 Objects.requireNonNull(key); 549 Objects.requireNonNull(query); 576 public SelectorItem(String key, String query, LocalDateTime lastEdit) { 577 Objects.requireNonNull(key, "The name of the item cannot be null"); 578 Objects.requireNonNull(query, "The query of the item cannot be null"); 579 Objects.requireNonNull(lastEdit, "The last edit date time cannot be null"); 550 580 551 581 if (Utils.isStripEmpty(key)) { … … 558 588 this.itemKey = key; 559 589 this.query = query; 560 this. usageCount = usageCount;590 this.lastEdit = lastEdit; 561 591 } 562 592 … … 578 608 579 609 /** 580 * Gets the number of times the query was used by the user. 581 * @return The usage count of this item. 582 */ 583 public int getUsageCount() { 584 return this.usageCount; 585 } 586 587 /** 588 * Increments the {@link SelectorItem#usageCount} by one till 589 * it reaches {@link Integer#MAX_VALUE}. 590 */ 591 public void increaseUsageCount() { 592 if (this.usageCount < Integer.MAX_VALUE) { 593 this.usageCount++; 594 } 595 } 596 597 /** 598 * Decrements the {@link SelectorItem#usageCount} ny one till 599 * it reaches 0. 600 */ 601 public void decreaseUsageCount() { 602 if (this.usageCount > 0) { 603 this.usageCount--; 604 } 610 * Gets the latest date time when the item was created/changed. 611 * @return The latest date time when the item was created/changed. 612 */ 613 public LocalDateTime getLastEdit() { 614 return lastEdit; 605 615 } 606 616 -
trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java
r12580 r12609 37 37 public final class OverpassQueryWizardDialog extends ExtendedDialog { 38 38 39 private final HistoryComboBox queryWizard; 39 40 private static final String HEADLINE_START = "<h3>"; 40 41 private static final String HEADLINE_END = "</h3>"; … … 43 44 private static final String TD_START = "<td>"; 44 45 private static final String TD_END = "</td>"; 45 private final HistoryComboBox queryWizard;46 private final OverpassTurboQueryWizard overpassQueryBuilder;46 private static final String SPAN_START = "<span>"; 47 private static final String SPAN_END = "</span>"; 47 48 private static final CollectionProperty OVERPASS_WIZARD_HISTORY = 48 49 new CollectionProperty("download.overpass.wizard", new ArrayList<String>()); 50 private final transient OverpassTurboQueryWizard overpassQueryBuilder; 49 51 50 52 // dialog buttons … … 200 202 .append(Utils.joinAsHtmlUnorderedList(Arrays.asList("<i>type:node</i>", "<i>type:relation</i>", "<i>type:way</i>"))) 201 203 .append(TD_END).append(TD_START) 202 .append( "<span>").append(tr("Download objects of a certain type.")).append("</span>")204 .append(SPAN_START).append(tr("Download objects of a certain type.")).append(SPAN_END) 203 205 .append(TD_END).append(TR_END) 204 206 .append(TR_START).append(TD_START) … … 215 217 tr("{0} all objects within the current selection that have {1} as attribute.", "<i>tourism=hotel in bbox</i> -", 216 218 "'tourism=hotel'")))) 217 .append( "<span>")219 .append(SPAN_START) 218 220 .append(tr("Instead of <i>location</i> any valid place name can be used like address, city, etc.")) 219 .append( "</span>")221 .append(SPAN_END) 220 222 .append(TD_END).append(TR_END) 221 223 .append(TR_START).append(TD_START) … … 231 233 tr("<i>expression1 {0} expression2</i>", "and")))) 232 234 .append(TD_END).append(TD_START) 233 .append( "<span>")235 .append(SPAN_START) 234 236 .append(tr("Basic logical operators can be used to create more sophisticated queries. Instead of \"or\" - \"|\", \"||\" " + 235 237 "can be used, and instead of \"and\" - \"&\", \"&&\".")) 236 .append( "</span>")238 .append(SPAN_END) 237 239 .append(TD_END).append(TR_END).append("</table>") 238 240 .append("</body>")
Note:
See TracChangeset
for help on using the changeset viewer.