source: josm/trunk/src/org/openstreetmap/josm/actions/DownloadPrimitiveAction.java@ 5508

Last change on this file since 5508 was 5373, checked in by Don-vip, 12 years ago

fix indentation from previous commit

  • Property svn:eol-style set to native
File size: 14.4 KB
Line 
1// License: GPL. See LICENSE file for details.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trc;
7import static org.openstreetmap.josm.tools.I18n.trn;
8
9import java.awt.Font;
10import java.awt.GridBagLayout;
11import java.awt.event.ActionEvent;
12import java.awt.event.ItemEvent;
13import java.awt.event.ItemListener;
14import java.awt.event.KeyEvent;
15import java.lang.reflect.InvocationTargetException;
16import java.util.Collections;
17import java.util.LinkedList;
18import java.util.List;
19import java.util.Set;
20import java.util.TreeSet;
21import javax.swing.BorderFactory;
22import javax.swing.GroupLayout;
23
24import javax.swing.JCheckBox;
25import javax.swing.JLabel;
26import javax.swing.JOptionPane;
27import javax.swing.JPanel;
28import javax.swing.JScrollPane;
29import javax.swing.JTextArea;
30import javax.swing.JTextField;
31import javax.swing.KeyStroke;
32import javax.swing.SwingUtilities;
33import javax.swing.border.EtchedBorder;
34import javax.swing.plaf.basic.BasicComboBoxEditor;
35
36import org.openstreetmap.josm.Main;
37import org.openstreetmap.josm.actions.downloadtasks.DownloadReferrersTask;
38import org.openstreetmap.josm.data.osm.DataSet;
39import org.openstreetmap.josm.data.osm.OsmPrimitive;
40import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
41import org.openstreetmap.josm.data.osm.PrimitiveId;
42import org.openstreetmap.josm.gui.ExtendedDialog;
43import org.openstreetmap.josm.gui.io.DownloadPrimitivesTask;
44import org.openstreetmap.josm.gui.layer.OsmDataLayer;
45import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
46import org.openstreetmap.josm.gui.widgets.HtmlPanel;
47import org.openstreetmap.josm.gui.widgets.OsmIdTextField;
48import org.openstreetmap.josm.gui.widgets.OsmPrimitiveTypesComboBox;
49import org.openstreetmap.josm.tools.GBC;
50import org.openstreetmap.josm.tools.Shortcut;
51import org.openstreetmap.josm.tools.Utils;
52
53/**
54 * Download an OsmPrimitive by specifying type and ID
55 *
56 * @author Matthias Julius
57 */
58public class DownloadPrimitiveAction extends JosmAction {
59
60 public DownloadPrimitiveAction() {
61 super(tr("Download object..."), "downloadprimitive", tr("Download OSM object by ID."),
62 Shortcut.registerShortcut("system:download_primitive", tr("File: {0}", tr("Download object...")), KeyEvent.VK_O, Shortcut.CTRL_SHIFT), true);
63 putValue("help", ht("/Action/DownloadObject"));
64 }
65
66 /**
67 * Restore the current history from the preferences
68 *
69 * @param cbHistory
70 */
71 protected void restorePrimitivesHistory(HistoryComboBox cbHistory) {
72 List<String> cmtHistory = new LinkedList<String>(Main.pref.getCollection(getClass().getName() + ".primitivesHistory", new LinkedList<String>()));
73 // we have to reverse the history, because ComboBoxHistory will reverse it again
74 // in addElement()
75 //
76 Collections.reverse(cmtHistory);
77 cbHistory.setPossibleItems(cmtHistory);
78 }
79
80 /**
81 * Remind the current history in the preferences
82 * @param cbHistory
83 */
84 protected void remindPrimitivesHistory(HistoryComboBox cbHistory) {
85 cbHistory.addCurrentItemToHistory();
86 Main.pref.putCollection(getClass().getName() + ".primitivesHistory", cbHistory.getHistory());
87 }
88
89 public void actionPerformed(ActionEvent e) {
90
91 JPanel all = new JPanel();
92 GroupLayout layout = new GroupLayout(all);
93 all.setLayout(layout);
94 layout.setAutoCreateGaps(true);
95 layout.setAutoCreateContainerGaps(true);
96
97 JLabel lbl1 = new JLabel(tr("Object type:"));
98 final OsmPrimitiveTypesComboBox cbType = new OsmPrimitiveTypesComboBox();
99 cbType.addItem(trc("osm object types", "mixed"));
100 cbType.setToolTipText(tr("Choose the OSM object type"));
101 JLabel lbl2 = new JLabel(tr("Object ID:"));
102 final OsmIdTextField tfId = new OsmIdTextField();
103 HistoryComboBox cbId = new HistoryComboBox();
104 cbId.setEditor(new BasicComboBoxEditor() {
105 @Override
106 protected JTextField createEditorComponent() {
107 return tfId;
108 }
109 });
110 cbId.setToolTipText(tr("Enter the ID of the object that should be downloaded"));
111 restorePrimitivesHistory(cbId);
112 // forward the enter key stroke to the download button
113 tfId.getKeymap().removeKeyStrokeBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false));
114 JCheckBox layer = new JCheckBox(tr("Separate Layer"));
115 layer.setToolTipText(tr("Select if the data should be downloaded into a new layer"));
116 layer.setSelected(Main.pref.getBoolean("download.newlayer"));
117 final JCheckBox referrers = new JCheckBox(tr("Download referrers (parent relations)"));
118 referrers.setToolTipText(tr("Select if the referrers of the object should be downloaded as well, i.e.,"
119 + "parent relations and for nodes, additionally, parent ways"));
120 referrers.setSelected(Main.pref.getBoolean("downloadprimitive.referrers", true));
121 JCheckBox full = new JCheckBox(tr("Download relation members"));
122 full.setToolTipText(tr("Select if the members of a relation should be downloaded as well"));
123 full.setSelected(Main.pref.getBoolean("downloadprimitive.full", true));
124 HtmlPanel help = new HtmlPanel(tr("Object IDs can be separated by comma or space.<br/>"
125 + " Examples: <b><ul><li>1 2 5</li><li>1,2,5</li></ul><br/></b>"
126 + " In mixed mode, specify objects like this: <b>w123, n110, w12, r15</b><br/>"));
127 help.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
128
129 layout.setVerticalGroup(layout.createSequentialGroup()
130 .addGroup(layout.createParallelGroup()
131 .addComponent(lbl1)
132 .addComponent(cbType, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
133 .addGroup(layout.createParallelGroup()
134 .addComponent(lbl2)
135 .addComponent(cbId, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE))
136 .addComponent(referrers)
137 .addComponent(full)
138 .addComponent(layer)
139 .addComponent(help)
140 );
141
142 cbType.addItemListener(new ItemListener() {
143
144 @Override
145 public void itemStateChanged(ItemEvent e) {
146 tfId.setType(cbType.getType());
147 tfId.performValidation();
148 referrers.setText(cbType.getType() == OsmPrimitiveType.NODE
149 ? tr("Download referrers (parent relations and ways)")
150 : tr("Download referrers (parent relations)"));
151 }
152 });
153
154 layout.setHorizontalGroup(layout.createParallelGroup()
155 .addGroup(layout.createSequentialGroup()
156 .addGroup(layout.createParallelGroup()
157 .addComponent(lbl1)
158 .addComponent(lbl2)
159 )
160 .addGroup(layout.createParallelGroup()
161 .addComponent(cbType)
162 .addComponent(cbId))
163 )
164 .addComponent(referrers)
165 .addComponent(full)
166 .addComponent(layer)
167 .addComponent(help)
168 );
169
170 ExtendedDialog dialog = new ExtendedDialog(Main.parent,
171 tr("Download object"),
172 new String[] {tr("Download object"), tr("Cancel")}
173 );
174 dialog.setContent(all, false);
175 dialog.setButtonIcons(new String[] {"download.png", "cancel.png"});
176 dialog.setToolTipTexts(new String[] {
177 tr("Start downloading"),
178 tr("Close dialog and cancel downloading")
179 });
180 dialog.setDefaultButton(1);
181 dialog.configureContextsensitiveHelp("/Action/DownloadObject", true /* show help button */);
182 cbType.setSelectedIndex(Main.pref.getInteger("downloadprimitive.lasttype", 0));
183 tfId.setType(cbType.getType());
184 if (Main.pref.getBoolean("downloadprimitive.autopaste", true)) {
185 tryToPasteFromClipboard(tfId, cbType);
186 }
187
188 dialog.showDialog();
189 if (dialog.getValue() != 1) return;
190 Main.pref.putInteger("downloadprimitive.lasttype", cbType.getSelectedIndex());
191 Main.pref.put("downloadprimitive.referrers", referrers.isSelected());
192 Main.pref.put("downloadprimitive.full", full.isSelected());
193 Main.pref.put("download.newlayer", layer.isSelected());
194
195 tfId.setType(cbType.getType());
196 if(!tfId.readOsmIds()) {
197 JOptionPane.showMessageDialog(
198 Main.parent,
199 tr("Invalid ID list specified\n"
200 + "Cannot download object."),
201 tr("Information"),
202 JOptionPane.INFORMATION_MESSAGE
203 );
204 return;
205 }
206 remindPrimitivesHistory(cbId);
207 processItems(layer.isSelected(), tfId.getIds(), referrers.isSelected(), full.isSelected());
208 }
209
210 /**
211 * @param newLayer if the data should be downloaded into a new layer
212 * @param ids
213 * @param downloadReferrers if the referrers of the object should be downloaded as well, i.e., parent relations, and for nodes, additionally, parent ways
214 * @param full if the members of a relation should be downloaded as well
215 */
216 public static void processItems(boolean newLayer, final List<PrimitiveId> ids, boolean downloadReferrers, boolean full) {
217 OsmDataLayer layer = getEditLayer();
218 if ((layer == null) || newLayer) {
219 layer = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null);
220 Main.main.addLayer(layer);
221 }
222 final DownloadPrimitivesTask task = new DownloadPrimitivesTask(layer, ids, full);
223 Main.worker.submit(task);
224
225 if (downloadReferrers) {
226 for (PrimitiveId id : ids) {
227 Main.worker.submit(new DownloadReferrersTask(layer, id));
228 }
229 }
230
231 Runnable showErrorsAndWarnings = new Runnable() {
232 @Override
233 public void run() {
234 Set<PrimitiveId> errs = task.getMissingPrimitives();
235 if (errs != null && !errs.isEmpty()) {
236 final ExtendedDialog dlg = reportProblemDialog(errs,
237 trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()),
238 trn("One object could not be downloaded.<br>",
239 "{0} objects could not be downloaded.<br>",
240 errs.size(),
241 errs.size())
242 + tr("The server replied with response code 404.<br>"
243 + "This usually means, the server does not know an object with the requested id."),
244 tr("missing objects:"),
245 JOptionPane.ERROR_MESSAGE
246 );
247 try {
248 SwingUtilities.invokeAndWait(new Runnable() {
249 @Override
250 public void run() {
251 dlg.showDialog();
252 }
253 });
254 } catch (InterruptedException ex) {
255 } catch (InvocationTargetException ex) {
256 }
257 }
258
259 Set<PrimitiveId> del = new TreeSet<PrimitiveId>();
260 DataSet ds = getCurrentDataSet();
261 for (PrimitiveId id : ids) {
262 OsmPrimitive osm = ds.getPrimitiveById(id);
263 if (osm != null && osm.isDeleted()) {
264 del.add(id);
265 }
266 }
267 if (!del.isEmpty()) {
268 final ExtendedDialog dlg = reportProblemDialog(del,
269 trn("Object deleted", "Objects deleted", del.size()),
270 trn(
271 "One downloaded object is deleted.",
272 "{0} downloaded objects are deleted.",
273 del.size(),
274 del.size()),
275 null,
276 JOptionPane.WARNING_MESSAGE
277 );
278 SwingUtilities.invokeLater(new Runnable() {
279 @Override
280 public void run() {
281 dlg.showDialog();
282 }
283 });
284 }
285 }
286 };
287 Main.worker.submit(showErrorsAndWarnings);
288 }
289
290 private static ExtendedDialog reportProblemDialog(Set<PrimitiveId> errs,
291 String TITLE, String TEXT, String LIST_LABEL, int msgType) {
292 JPanel p = new JPanel(new GridBagLayout());
293 p.add(new HtmlPanel(TEXT), GBC.eop());
294 if (LIST_LABEL != null) {
295 JLabel missing = new JLabel(LIST_LABEL);
296 missing.setFont(missing.getFont().deriveFont(Font.PLAIN));
297 p.add(missing, GBC.eol());
298 }
299 JTextArea txt = new JTextArea();
300 txt.setFont(new Font("Monospaced", txt.getFont().getStyle(), txt.getFont().getSize()));
301 txt.setEditable(false);
302 txt.setBackground(p.getBackground());
303 txt.setColumns(40);
304 txt.setRows(1);
305 txt.setText(Utils.join(", ", errs));
306 JScrollPane scroll = new JScrollPane(txt);
307 p.add(scroll, GBC.eop().weight(1.0, 0.0).fill(GBC.HORIZONTAL));
308
309 return new ExtendedDialog(
310 Main.parent,
311 TITLE,
312 new String[] { tr("Ok") })
313 .setButtonIcons(new String[] { "ok" })
314 .setIcon(msgType)
315 .setContent(p, false);
316 }
317
318 private void tryToPasteFromClipboard(OsmIdTextField tfId, OsmPrimitiveTypesComboBox cbType) {
319 String buf = Utils.getClipboardContent();
320 if (buf != null) {
321 if (buf.contains("node")) cbType.setSelectedIndex(0);
322 if (buf.contains("way")) cbType.setSelectedIndex(1);
323 if (buf.contains("relation")) cbType.setSelectedIndex(2);
324 String[] res = buf.split("/");
325 String txt;
326 if (res.length>0) {
327 txt = res[res.length-1];
328 if (txt.isEmpty() && txt.length()>1) txt=res[res.length-2];
329 } else {
330 txt=buf;
331 }
332 tfId.setText(txt);
333 tfId.clearTextIfInvalid();
334 }
335 }
336}
Note: See TracBrowser for help on using the repository browser.