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

Last change on this file since 8855 was 8756, checked in by simon04, 9 years ago

fix #10023 - Add history of Overpass queries

File size: 10.5 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.GridLayout;
10import java.awt.Rectangle;
11import java.awt.event.ActionEvent;
12import java.awt.event.ActionListener;
13import java.awt.event.KeyEvent;
14import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.Deque;
19import java.util.LinkedList;
20import java.util.concurrent.Future;
21
22import javax.swing.AbstractAction;
23import javax.swing.JButton;
24import javax.swing.JComponent;
25import javax.swing.JLabel;
26import javax.swing.JMenuItem;
27import javax.swing.JOptionPane;
28import javax.swing.JPanel;
29import javax.swing.JPopupMenu;
30import javax.swing.JScrollPane;
31import javax.swing.plaf.basic.BasicArrowButton;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
35import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
36import org.openstreetmap.josm.data.Bounds;
37import org.openstreetmap.josm.data.preferences.CollectionProperty;
38import org.openstreetmap.josm.data.preferences.IntegerProperty;
39import org.openstreetmap.josm.data.preferences.StringProperty;
40import org.openstreetmap.josm.gui.HelpAwareOptionPane;
41import org.openstreetmap.josm.gui.download.DownloadDialog;
42import org.openstreetmap.josm.gui.util.GuiHelper;
43import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
44import org.openstreetmap.josm.gui.widgets.JosmTextArea;
45import org.openstreetmap.josm.io.OverpassDownloadReader;
46import org.openstreetmap.josm.tools.GBC;
47import org.openstreetmap.josm.tools.OverpassTurboQueryWizard;
48import org.openstreetmap.josm.tools.Shortcut;
49import org.openstreetmap.josm.tools.Utils;
50
51/**
52 * Download map data from Overpass API server.
53 * @since 8684
54 */
55public class OverpassDownloadAction extends JosmAction {
56
57 /**
58 * Constructs a new {@code OverpassDownloadAction}.
59 */
60 public OverpassDownloadAction() {
61 super(tr("Download from Overpass API ..."), "download-overpass", tr("Download map data from Overpass API server."),
62 // CHECKSTYLE.OFF: LineLength
63 Shortcut.registerShortcut("file:download-overpass", tr("File: {0}", tr("Download from Overpass API ...")), KeyEvent.VK_DOWN, Shortcut.ALT_SHIFT),
64 // CHECKSTYLE.ON: LineLength
65 true, "overpassdownload/download", true);
66 putValue("help", ht("/Action/OverpassDownload"));
67 }
68
69 @Override
70 public void actionPerformed(ActionEvent e) {
71 OverpassDownloadDialog dialog = OverpassDownloadDialog.getInstance();
72 dialog.restoreSettings();
73 dialog.setVisible(true);
74 if (!dialog.isCanceled()) {
75 dialog.rememberSettings();
76 Bounds area = dialog.getSelectedDownloadArea();
77 DownloadOsmTask task = new DownloadOsmTask();
78 Future<?> future = task.download(
79 new OverpassDownloadReader(area, dialog.getOverpassServer(), dialog.getOverpassQuery()),
80 dialog.isNewLayerRequired(), area, null);
81 Main.worker.submit(new PostDownloadHandler(task, future));
82 }
83 }
84
85 static final class OverpassDownloadDialog extends DownloadDialog {
86
87 protected HistoryComboBox overpassServer;
88 protected HistoryComboBox overpassWizard;
89 protected JosmTextArea overpassQuery;
90 private static OverpassDownloadDialog instance;
91 static final StringProperty OVERPASS_SERVER = new StringProperty("download.overpass.server", "http://overpass-api.de/api/");
92 static final CollectionProperty OVERPASS_SERVER_HISTORY = new CollectionProperty("download.overpass.servers",
93 Arrays.asList("http://overpass-api.de/api/", "http://overpass.osm.rambler.ru/cgi/"));
94 static final CollectionProperty OVERPASS_WIZARD_HISTORY = new CollectionProperty("download.overpass.wizard", new ArrayList<String>());
95
96 private OverpassDownloadDialog(Component parent) {
97 super(parent, ht("/Action/OverpassDownload"));
98 cbDownloadOsmData.setEnabled(false);
99 cbDownloadOsmData.setSelected(false);
100 cbDownloadGpxData.setVisible(false);
101 cbDownloadNotes.setVisible(false);
102 cbStartup.setVisible(false);
103 }
104
105 public static OverpassDownloadDialog getInstance() {
106 if (instance == null) {
107 instance = new OverpassDownloadDialog(Main.parent);
108 }
109 return instance;
110 }
111
112 @Override
113 protected void buildMainPanelAboveDownloadSelections(JPanel pnl) {
114
115 pnl.add(new JLabel(), GBC.eol()); // needed for the invisible checkboxes cbDownloadGpxData, cbDownloadNotes
116
117 final String tooltip = tr("Builds an Overpass query using the Overpass Turbo query wizard");
118 overpassWizard = new HistoryComboBox();
119 overpassWizard.setToolTipText(tooltip);
120 final JButton buildQuery = new JButton(tr("Build query"));
121 buildQuery.addActionListener(new AbstractAction() {
122 @Override
123 public void actionPerformed(ActionEvent e) {
124 final String overpassWizardText = overpassWizard.getText();
125 try {
126 overpassQuery.setText(OverpassTurboQueryWizard.getInstance().constructQuery(overpassWizardText));
127 } catch (OverpassTurboQueryWizard.ParseException ex) {
128 HelpAwareOptionPane.showOptionDialog(
129 Main.parent,
130 tr("<html>The Overpass wizard could not parse the following query:"
131 + Utils.joinAsHtmlUnorderedList(Collections.singleton(overpassWizardText))),
132 tr("Parse error"),
133 JOptionPane.ERROR_MESSAGE,
134 null
135 );
136 }
137 }
138 });
139 buildQuery.setToolTipText(tooltip);
140 pnl.add(buildQuery, GBC.std().insets(5, 5, 5, 5));
141 pnl.add(overpassWizard, GBC.eol().fill(GBC.HORIZONTAL));
142
143 overpassQuery = new JosmTextArea("", 8, 80);
144 overpassQuery.setFont(GuiHelper.getMonospacedFont(overpassQuery));
145 JScrollPane scrollPane = new JScrollPane(overpassQuery);
146 final JPanel pane = new JPanel(new BorderLayout());
147 final BasicArrowButton arrowButton = new BasicArrowButton(BasicArrowButton.SOUTH);
148 arrowButton.addActionListener(new AbstractAction() {
149 @Override
150 public void actionPerformed(ActionEvent e) {
151 OverpassQueryHistoryPopup.show(arrowButton, OverpassDownloadDialog.this);
152 }
153 });
154 pane.add(scrollPane, BorderLayout.CENTER);
155 pane.add(arrowButton, BorderLayout.EAST);
156 pnl.add(new JLabel(tr("Overpass query: ")), GBC.std().insets(5, 5, 5, 5));
157 GBC gbc = GBC.eol().fill(GBC.HORIZONTAL);
158 gbc.ipady = 200;
159 pnl.add(pane, gbc);
160
161 overpassServer = new HistoryComboBox();
162 pnl.add(new JLabel(tr("Overpass server: ")), GBC.std().insets(5, 5, 5, 5));
163 pnl.add(overpassServer, GBC.eol().fill(GBC.HORIZONTAL));
164
165 }
166
167 public String getOverpassServer() {
168 return overpassServer.getText();
169 }
170
171 public String getOverpassQuery() {
172 return overpassQuery.getText();
173 }
174
175 public void setOverpassQuery(String text) {
176 overpassQuery.setText(text);
177 }
178
179 @Override
180 public void restoreSettings() {
181 super.restoreSettings();
182 overpassServer.setPossibleItems(OVERPASS_SERVER_HISTORY.get());
183 overpassServer.setText(OVERPASS_SERVER.get());
184 overpassWizard.setPossibleItems(OVERPASS_WIZARD_HISTORY.get());
185 }
186
187 @Override
188 public void rememberSettings() {
189 super.rememberSettings();
190 overpassWizard.addCurrentItemToHistory();
191 OVERPASS_SERVER.put(getOverpassServer());
192 OVERPASS_SERVER_HISTORY.put(overpassServer.getHistory());
193 OVERPASS_WIZARD_HISTORY.put(overpassWizard.getHistory());
194 OverpassQueryHistoryPopup.addToHistory(getOverpassQuery());
195 }
196
197 }
198
199 static class OverpassQueryHistoryPopup extends JPopupMenu {
200
201 static final CollectionProperty OVERPASS_QUERY_HISTORY = new CollectionProperty("download.overpass.query", new ArrayList<String>());
202 static final IntegerProperty OVERPASS_QUERY_HISTORY_SIZE = new IntegerProperty("download.overpass.query.size", 12);
203
204 OverpassQueryHistoryPopup(final OverpassDownloadDialog dialog) {
205 final Collection<String> history = OVERPASS_QUERY_HISTORY.get();
206 setLayout(new GridLayout((int) Math.ceil(history.size() / 2.), 2));
207 for (final String i : history) {
208 add(new OverpassQueryHistoryItem(i, dialog));
209 }
210 }
211
212 static void show(final JComponent parent, final OverpassDownloadDialog dialog) {
213 final OverpassQueryHistoryPopup menu = new OverpassQueryHistoryPopup(dialog);
214 final Rectangle r = parent.getBounds();
215 menu.show(parent.getParent(), r.x + r.width - (int) menu.getPreferredSize().getWidth(), r.y + r.height);
216 }
217
218 static void addToHistory(final String query) {
219 final Deque<String> history = new LinkedList<>(OVERPASS_QUERY_HISTORY.get());
220 if (!history.contains(query)) {
221 history.add(query);
222 }
223 while (history.size() > OVERPASS_QUERY_HISTORY_SIZE.get()) {
224 history.removeFirst();
225 }
226 OVERPASS_QUERY_HISTORY.put(history);
227 }
228 }
229
230 static class OverpassQueryHistoryItem extends JMenuItem implements ActionListener {
231
232 final String query;
233 final OverpassDownloadDialog dialog;
234
235 OverpassQueryHistoryItem(final String query, final OverpassDownloadDialog dialog) {
236 this.query = query;
237 this.dialog = dialog;
238 setText("<html><pre style='width:300px;'>" +
239 Utils.escapeReservedCharactersHTML(Utils.restrictStringLines(query, 7)));
240 addActionListener(this);
241 }
242
243 @Override
244 public void actionPerformed(ActionEvent e) {
245 dialog.setOverpassQuery(query);
246 }
247 }
248
249}
Note: See TracBrowser for help on using the repository browser.