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

Last change on this file since 4796 was 4796, checked in by simon04, 12 years ago

fix #6425 - remotecontrol: make download objects available (e.g., /load_object?objects=n1,w2,r3[&new_layer=false&relation_members=true])

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