source: josm/trunk/src/org/openstreetmap/josm/actions/OverpassDownloadAction.java@ 12576

Last change on this file since 12576 was 12576, checked in by michael2402, 7 years ago

See #15057: Move the overpass query wizard dialog to a new file.

File size: 10.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.Dimension;
10import java.awt.event.ActionEvent;
11import java.awt.event.FocusEvent;
12import java.awt.event.FocusListener;
13import java.awt.event.KeyEvent;
14import java.util.Collection;
15import java.util.Optional;
16import java.util.concurrent.Future;
17import java.util.function.Consumer;
18
19import javax.swing.AbstractAction;
20import javax.swing.Action;
21import javax.swing.ActionMap;
22import javax.swing.JButton;
23import javax.swing.JLabel;
24import javax.swing.JOptionPane;
25import javax.swing.JPanel;
26import javax.swing.JScrollPane;
27import javax.swing.plaf.basic.BasicArrowButton;
28
29import org.openstreetmap.josm.Main;
30import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
31import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
32import org.openstreetmap.josm.data.Bounds;
33import org.openstreetmap.josm.data.preferences.BooleanProperty;
34import org.openstreetmap.josm.gui.download.DownloadDialog;
35import org.openstreetmap.josm.gui.download.OverpassQueryList;
36import org.openstreetmap.josm.gui.download.OverpassQueryWizardDialog;
37import org.openstreetmap.josm.gui.preferences.server.OverpassServerPreference;
38import org.openstreetmap.josm.gui.util.GuiHelper;
39import org.openstreetmap.josm.gui.widgets.JosmTextArea;
40import org.openstreetmap.josm.io.OverpassDownloadReader;
41import org.openstreetmap.josm.tools.GBC;
42import org.openstreetmap.josm.tools.Shortcut;
43
44/**
45 * Download map data from Overpass API server.
46 * @since 8684
47 */
48public class OverpassDownloadAction extends JosmAction {
49
50 /**
51 * Constructs a new {@code OverpassDownloadAction}.
52 */
53 public OverpassDownloadAction() {
54 super(tr("Download from Overpass API ..."), "download-overpass", tr("Download map data from Overpass API server."),
55 // CHECKSTYLE.OFF: LineLength
56 Shortcut.registerShortcut("file:download-overpass", tr("File: {0}", tr("Download from Overpass API ...")), KeyEvent.VK_DOWN, Shortcut.ALT_SHIFT),
57 // CHECKSTYLE.ON: LineLength
58 true, "overpassdownload/download", true);
59 putValue("help", ht("/Action/OverpassDownload"));
60 }
61
62 @Override
63 public void actionPerformed(ActionEvent e) {
64 OverpassDownloadDialog dialog = OverpassDownloadDialog.getInstance();
65 dialog.restoreSettings();
66 dialog.setVisible(true);
67
68 if (dialog.isCanceled()) {
69 return;
70 }
71
72 dialog.rememberSettings();
73 Optional<Bounds> selectedArea = dialog.getSelectedDownloadArea();
74 String overpassQuery = dialog.getOverpassQuery();
75
76 /*
77 * Absence of the selected area can be justified only if the overpass query
78 * is not restricted to bbox.
79 */
80 if (!selectedArea.isPresent() && overpassQuery.contains("{{bbox}}")) {
81 JOptionPane.showMessageDialog(
82 dialog,
83 tr("Please select a download area first."),
84 tr("Error"),
85 JOptionPane.ERROR_MESSAGE
86 );
87 return;
88 }
89
90 /*
91 * A callback that is passed to PostDownloadReporter that is called once the download task
92 * has finished. According to the number of errors happened, their type we decide whether we
93 * want to save the last query in OverpassQueryList.
94 */
95 Consumer<Collection<Object>> errorReporter = errors -> {
96
97 boolean onlyNoDataError = errors.size() == 1 &&
98 errors.contains("No data found in this area.");
99
100 if (errors.isEmpty() || onlyNoDataError) {
101 dialog.saveHistoricItemOnSuccess();
102 }
103 };
104
105 /*
106 * In order to support queries generated by the Overpass Turbo Query Wizard tool
107 * which do not require the area to be specified.
108 */
109 Bounds area = selectedArea.orElseGet(() -> new Bounds(0, 0, 0, 0));
110 DownloadOsmTask task = new DownloadOsmTask();
111 task.setZoomAfterDownload(dialog.isZoomToDownloadedDataRequired());
112 Future<?> future = task.download(
113 new OverpassDownloadReader(area, OverpassServerPreference.getOverpassServer(), dialog.getOverpassQuery()),
114 dialog.isNewLayerRequired(), area, null);
115 Main.worker.submit(new PostDownloadHandler(task, future, errorReporter));
116 }
117
118 private static final class DisableActionsFocusListener implements FocusListener {
119
120 private final ActionMap actionMap;
121
122 private DisableActionsFocusListener(ActionMap actionMap) {
123 this.actionMap = actionMap;
124 }
125
126 @Override
127 public void focusGained(FocusEvent e) {
128 enableActions(false);
129 }
130
131 @Override
132 public void focusLost(FocusEvent e) {
133 enableActions(true);
134 }
135
136 private void enableActions(boolean enabled) {
137 Object[] allKeys = actionMap.allKeys();
138 if (allKeys != null) {
139 for (Object key : allKeys) {
140 Action action = actionMap.get(key);
141 if (action != null) {
142 action.setEnabled(enabled);
143 }
144 }
145 }
146 }
147 }
148
149 /**
150 * The download dialog that overpass uses.
151 * @since 12576 public
152 */
153 public static final class OverpassDownloadDialog extends DownloadDialog {
154
155 private JosmTextArea overpassQuery;
156 private OverpassQueryList overpassQueryList;
157 private static OverpassDownloadDialog instance;
158 private static final BooleanProperty OVERPASS_QUERY_LIST_OPENED =
159 new BooleanProperty("download.overpass.query-list.opened", false);
160
161 private OverpassDownloadDialog(Component parent) {
162 super(parent, ht("/Action/OverpassDownload"));
163 cbDownloadOsmData.setEnabled(false);
164 cbDownloadOsmData.setSelected(false);
165 cbDownloadGpxData.setVisible(false);
166 cbDownloadNotes.setVisible(false);
167 cbStartup.setVisible(false);
168 }
169
170 public static OverpassDownloadDialog getInstance() {
171 if (instance == null) {
172 instance = new OverpassDownloadDialog(Main.parent);
173 }
174 return instance;
175 }
176
177 @Override
178 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
179 // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes
180 pnl.add(new JLabel(), GBC.eol());
181
182 DisableActionsFocusListener disableActionsFocusListener =
183 new DisableActionsFocusListener(slippyMapChooser.getNavigationComponentActionMap());
184
185 String tooltip = tr("Build an Overpass query using the Overpass Turbo Query Wizard tool");
186 Action queryWizardAction = new AbstractAction() {
187 @Override
188 public void actionPerformed(ActionEvent e) {
189 new OverpassQueryWizardDialog(instance).showDialog();
190 }
191 };
192
193 JButton openQueryWizard = new JButton("Query Wizard");
194 openQueryWizard.setToolTipText(tooltip);
195 openQueryWizard.addActionListener(queryWizardAction);
196
197 // CHECKSTYLE.OFF: LineLength
198 this.overpassQuery = new JosmTextArea(
199 "/*\n" +
200 tr("Place your Overpass query below or generate one using the Overpass Turbo Query Wizard")
201 + "\n*/",
202 8, 80);
203 // CHECKSTYLE.ON: LineLength
204 this.overpassQuery.setFont(GuiHelper.getMonospacedFont(overpassQuery));
205 this.overpassQuery.addFocusListener(disableActionsFocusListener);
206 this.overpassQuery.addFocusListener(new FocusListener() {
207 @Override
208 public void focusGained(FocusEvent e) {
209 overpassQuery.selectAll();
210 }
211
212 @Override
213 public void focusLost(FocusEvent e) {
214 // ignored
215 }
216 });
217
218 this.overpassQueryList = new OverpassQueryList(this, this.overpassQuery);
219 overpassQueryList.setToolTipText(tr("Show/hide Overpass snippet list"));
220 overpassQueryList.setVisible(OVERPASS_QUERY_LIST_OPENED.get());
221 overpassQueryList.setPreferredSize(new Dimension(350, 300));
222 JScrollPane scrollPane = new JScrollPane(overpassQuery);
223 BasicArrowButton arrowButton = new BasicArrowButton(overpassQueryList.isVisible()
224 ? BasicArrowButton.EAST
225 : BasicArrowButton.WEST);
226 arrowButton.addActionListener(e -> {
227 if (overpassQueryList.isVisible()) {
228 overpassQueryList.setVisible(false);
229 arrowButton.setDirection(BasicArrowButton.WEST);
230 OVERPASS_QUERY_LIST_OPENED.put(false);
231 } else {
232 overpassQueryList.setVisible(true);
233 arrowButton.setDirection(BasicArrowButton.EAST);
234 OVERPASS_QUERY_LIST_OPENED.put(false);
235 }
236 });
237
238 JPanel innerPanel = new JPanel(new BorderLayout());
239 innerPanel.add(scrollPane, BorderLayout.CENTER);
240 innerPanel.add(arrowButton, BorderLayout.EAST);
241
242 JPanel pane = new JPanel(new BorderLayout());
243 pane.add(innerPanel, BorderLayout.CENTER);
244 pane.add(overpassQueryList, BorderLayout.EAST);
245
246 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL); gbc.ipady = 200;
247 pnl.add(openQueryWizard, GBC.std().insets(5, 5, 5, 5));
248 pnl.add(pane, gbc);
249 }
250
251 String getOverpassQuery() {
252 return overpassQuery.getText();
253 }
254
255 /**
256 * Sets the query that is displayed
257 * @param text The multiline query text.
258 * @since 12576 public
259 */
260 public void setOverpassQuery(String text) {
261 overpassQuery.setText(text);
262 }
263
264 /**
265 * Adds the current query to {@link OverpassQueryList}.
266 */
267 void saveHistoricItemOnSuccess() {
268 overpassQueryList.saveHistoricItem(overpassQuery.getText());
269 }
270
271 @Override
272 protected void updateSizeCheck() {
273 displaySizeCheckResult(false);
274 }
275
276 /**
277 * Triggers the download action to fire.
278 * @since 12576 public
279 */
280 public void triggerDownload() {
281 super.btnDownload.doClick();
282 }
283 }
284}
Note: See TracBrowser for help on using the repository browser.