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

Last change on this file since 4497 was 4497, checked in by simon04, 13 years ago

fix #6542 - option to download relation without its members for "Download object" dialog

  • Property svn:eol-style set to native
File size: 13.1 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"));
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 void processItems(boolean newLayer, final List<PrimitiveId> ids, boolean downloadReferrers, boolean full) {
203 OsmDataLayer layer = getEditLayer();
204 if ((layer == null) || newLayer) {
205 layer = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null);
206 Main.main.addLayer(layer);
207 }
208 final DownloadPrimitivesTask task = new DownloadPrimitivesTask(layer, ids, full);
209 Main.worker.submit(task);
210
211 if (downloadReferrers) {
212 for (PrimitiveId id : ids) {
213 Main.worker.submit(new DownloadReferrersTask(layer, id));
214 }
215 }
216
217 Runnable showErrorsAndWarnings = new Runnable() {
218 @Override
219 public void run() {
220 Set<PrimitiveId> errs = task.getMissingPrimitives();
221 if (errs != null && !errs.isEmpty()) {
222 final ExtendedDialog dlg = reportProblemDialog(errs,
223 trn("Object could not be downloaded", "Some objects could not be downloaded", errs.size()),
224 trn("One object could not be downloaded.<br>",
225 "{0} objects could not be downloaded.<br>",
226 errs.size(),
227 errs.size())
228 + tr("The server replied with response code 404.<br>"
229 + "This usually means, the server does not know an object with the requested id."),
230 tr("missing objects:"),
231 JOptionPane.ERROR_MESSAGE
232 );
233 try {
234 SwingUtilities.invokeAndWait(new Runnable() {
235 @Override
236 public void run() {
237 dlg.showDialog();
238 }
239 });
240 } catch (InterruptedException ex) {
241 } catch (InvocationTargetException ex) {
242 }
243 }
244
245 Set<PrimitiveId> del = new TreeSet<PrimitiveId>();
246 DataSet ds = getCurrentDataSet();
247 for (PrimitiveId id : ids) {
248 OsmPrimitive osm = ds.getPrimitiveById(id);
249 if (osm != null && osm.isDeleted()) {
250 del.add(id);
251 }
252 }
253 if (!del.isEmpty()) {
254 final ExtendedDialog dlg = reportProblemDialog(del,
255 trn("Object deleted", "Objects deleted", del.size()),
256 trn(
257 "One downloaded object is deleted.",
258 "{0} downloaded objects are deleted.",
259 del.size(),
260 del.size()),
261 null,
262 JOptionPane.WARNING_MESSAGE
263 );
264 SwingUtilities.invokeLater(new Runnable() {
265 @Override
266 public void run() {
267 dlg.showDialog();
268 }
269 });
270 }
271 }
272 };
273 Main.worker.submit(showErrorsAndWarnings);
274 }
275
276 private ExtendedDialog reportProblemDialog(Set<PrimitiveId> errs,
277 String TITLE, String TEXT, String LIST_LABEL, int msgType) {
278 JPanel p = new JPanel(new GridBagLayout());
279 p.add(new HtmlPanel(TEXT), GBC.eop());
280 if (LIST_LABEL != null) {
281 JLabel missing = new JLabel(LIST_LABEL);
282 missing.setFont(missing.getFont().deriveFont(Font.PLAIN));
283 p.add(missing, GBC.eol());
284 }
285 JTextArea txt = new JTextArea();
286 txt.setFont(new Font("Monospaced", txt.getFont().getStyle(), txt.getFont().getSize()));
287 txt.setEditable(false);
288 txt.setBackground(p.getBackground());
289 txt.setColumns(40);
290 txt.setRows(1);
291 txt.setText(Utils.join(", ", errs));
292 JScrollPane scroll = new JScrollPane(txt);
293 p.add(scroll, GBC.eop().weight(1.0, 0.0).fill(GBC.HORIZONTAL));
294
295 return new ExtendedDialog(
296 Main.parent,
297 TITLE,
298 new String[] { tr("Ok") })
299 .setButtonIcons(new String[] { "ok" })
300 .setIcon(msgType)
301 .setContent(p, false);
302 }
303}
Note: See TracBrowser for help on using the repository browser.