source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/ReferringRelationsBrowser.java@ 1806

Last change on this file since 1806 was 1806, checked in by Gubaer, 15 years ago

added OsmServerBackreferenceReader - reads primitives referring to a particular primitive (ways including a node, relations referring to a relation)
Extended relation dialog - now supports querying for parent relation(s)

File size: 10.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.EventQueue;
8import java.awt.FlowLayout;
9import java.awt.event.ActionEvent;
10import java.awt.event.MouseAdapter;
11import java.awt.event.MouseEvent;
12import java.io.IOException;
13import java.util.ArrayList;
14
15import javax.swing.AbstractAction;
16import javax.swing.JButton;
17import javax.swing.JCheckBox;
18import javax.swing.JDialog;
19import javax.swing.JLabel;
20import javax.swing.JList;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
23import javax.swing.ListSelectionModel;
24import javax.swing.SwingUtilities;
25import javax.swing.event.ListDataEvent;
26import javax.swing.event.ListDataListener;
27import javax.swing.event.ListSelectionEvent;
28import javax.swing.event.ListSelectionListener;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.data.osm.DataSet;
32import org.openstreetmap.josm.data.osm.DataSource;
33import org.openstreetmap.josm.data.osm.Relation;
34import org.openstreetmap.josm.data.osm.visitor.MergeVisitor;
35import org.openstreetmap.josm.gui.OsmPrimitivRenderer;
36import org.openstreetmap.josm.gui.PleaseWaitRunnable;
37import org.openstreetmap.josm.gui.SideButton;
38import org.openstreetmap.josm.gui.layer.OsmDataLayer;
39import org.openstreetmap.josm.io.OsmApi;
40import org.openstreetmap.josm.io.OsmServerBackreferenceReader;
41import org.openstreetmap.josm.io.OsmTransferException;
42import org.openstreetmap.josm.tools.ImageProvider;
43import org.xml.sax.SAXException;
44
45/**
46 * This is browser for a list of relations which refer to another relations
47 *
48 *
49 */
50public class ReferringRelationsBrowser extends JPanel {
51
52 /** the list of relations */
53 private JList referrers;
54 private ReferringRelationsBrowserModel model;
55 private OsmDataLayer layer;
56 private JCheckBox cbReadFull;
57 private EditAction editAction;
58
59 /**
60 * build the GUI
61 */
62 protected void build() {
63 setLayout(new BorderLayout());
64 referrers = new JList(model);
65 referrers.setCellRenderer(new OsmPrimitivRenderer());
66 add(referrers, BorderLayout.CENTER);
67 referrers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
68 referrers.addMouseListener(new DblClickMouseAdapter());
69
70 JPanel pnl = new JPanel();
71 pnl.setLayout(new FlowLayout(FlowLayout.LEFT));
72
73 ReloadAction reloadAction = new ReloadAction();
74 referrers.getModel().addListDataListener(reloadAction);
75 pnl.add(new SideButton(reloadAction));
76 pnl.add(new JLabel(tr("including immediate children of parent relations")));
77 pnl.add(cbReadFull = new JCheckBox());
78
79 editAction = new EditAction();
80 referrers.getSelectionModel().addListSelectionListener(editAction);
81 pnl.add(new SideButton(editAction));
82 add(pnl, BorderLayout.SOUTH);
83 }
84
85 public ReferringRelationsBrowser(OsmDataLayer layer, ReferringRelationsBrowserModel model) {
86 this.model = model;
87 this.layer = layer;
88 build();
89 }
90
91 protected OsmDataLayer getLayer() {
92 return layer;
93 }
94
95 /**
96 * Action for loading the parent relations of a relation
97 *
98 */
99 class ReloadAction extends AbstractAction implements ListDataListener {
100 public ReloadAction() {
101 putValue(SHORT_DESCRIPTION, tr("Load parent relations"));
102 putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
103 putValue(NAME, tr("Reload"));
104 refreshEnabled();
105 }
106
107 protected void refreshEnabled() {
108 setEnabled(model.canReload());
109 }
110
111 public void actionPerformed(ActionEvent e) {
112 boolean full = cbReadFull.isSelected();
113 ReloadTask task = new ReloadTask(full);
114 Main.worker.submit(task);
115 }
116
117 public void contentsChanged(ListDataEvent e) {
118 refreshEnabled();
119 }
120
121 public void intervalAdded(ListDataEvent e) {
122 refreshEnabled();
123 }
124
125 public void intervalRemoved(ListDataEvent e) {
126 refreshEnabled();
127 }
128 }
129
130 /**
131 * Action for editing the currently selected relation
132 *
133 */
134 class EditAction extends AbstractAction implements ListSelectionListener {
135 public EditAction() {
136 putValue(SHORT_DESCRIPTION, tr("Edit the currently selected relation"));
137 putValue(SMALL_ICON, ImageProvider.get("dialogs", "edit"));
138 putValue(NAME, tr("Edit"));
139 refreshEnabled();
140 }
141
142 protected void refreshEnabled() {
143 setEnabled(referrers.getSelectionModel().getMinSelectionIndex() >=0);
144 }
145
146 public void actionPerformed(ActionEvent e) {
147 run();
148 }
149
150 public void run() {
151 int idx = referrers.getSelectedIndex();
152 if (idx < 0) return;
153 Relation r = model.get(idx);
154 if (r == null) return;
155 RelationEditor editor = RelationEditor.getEditor(getLayer(), r, null);
156 editor.setVisible(true);
157 }
158
159 public void valueChanged(ListSelectionEvent e) {
160 refreshEnabled();
161 }
162 }
163
164 class DblClickMouseAdapter extends MouseAdapter {
165 @Override
166 public void mouseClicked(MouseEvent e) {
167 if (e.getClickCount() == 2) {
168 editAction.run();
169 }
170 }
171 }
172
173 /**
174 * Asynchronous task for loading the parent relations
175 *
176 */
177 class ReloadTask extends PleaseWaitRunnable {
178 private boolean cancelled;
179 private Exception lastException;
180 private DataSet referrers;
181 private boolean full;
182
183 protected void setIndeterminateEnabled(final boolean enabled) {
184 EventQueue.invokeLater(
185 new Runnable() {
186 public void run() {
187 Main.pleaseWaitDlg.setIndeterminate(enabled);
188 }
189 }
190 );
191 }
192
193 public ReloadTask(boolean full) {
194 super(tr("Download referring relations"), false /* don't ignore exception */);
195 referrers = null;
196 }
197 @Override
198 protected void cancel() {
199 cancelled = true;
200 OsmApi.getOsmApi().cancel();
201 }
202
203 protected void showLastException() {
204 String msg = lastException.getMessage();
205 if (msg == null) {
206 msg = lastException.toString();
207 }
208 JOptionPane.showMessageDialog(
209 null,
210 msg,
211 tr("Error"),
212 JOptionPane.ERROR_MESSAGE
213 );
214 }
215
216 @Override
217 protected void finish() {
218 if (cancelled) return;
219 if (lastException != null) {
220 showLastException();
221 return;
222 }
223 final ArrayList<Relation> parents = new ArrayList<Relation>();
224 for (Relation parent : referrers.relations) {
225 parents.add((Relation)getLayer().data.getPrimitiveById(parent.id));
226 }
227 SwingUtilities.invokeLater(
228 new Runnable() {
229 public void run() {
230 model.populate(parents);
231 }
232 }
233 );
234 }
235
236 @Override
237 protected void realRun() throws SAXException, IOException, OsmTransferException {
238 try {
239 Main.pleaseWaitDlg.setAlwaysOnTop(true);
240 Main.pleaseWaitDlg.toFront();
241 setIndeterminateEnabled(true);
242 OsmServerBackreferenceReader reader = new OsmServerBackreferenceReader(model.getRelation(), full);
243 referrers = reader.parseOsm();
244 if (referrers != null) {
245 final MergeVisitor visitor = new MergeVisitor(getLayer().data, referrers);
246 visitor.merge();
247
248 // copy the merged layer's data source info
249 for (DataSource src : referrers.dataSources) {
250 getLayer().data.dataSources.add(src);
251 }
252 // FIXME: this is necessary because there are dialogs listening
253 // for DataChangeEvents which manipulate Swing components on this
254 // thread.
255 //
256 SwingUtilities.invokeLater(
257 new Runnable() {
258 public void run() {
259 getLayer().fireDataChange();
260 }
261 }
262 );
263
264 if (visitor.getConflicts().isEmpty())
265 return;
266 getLayer().getConflicts().add(visitor.getConflicts());
267 JOptionPane op = new JOptionPane(
268 tr("There were {0} conflicts during import.",
269 visitor.getConflicts().size()),
270 JOptionPane.WARNING_MESSAGE
271 );
272 JDialog dialog = op.createDialog(Main.pleaseWaitDlg, tr("Conflicts in data"));
273 dialog.setAlwaysOnTop(true);
274 dialog.setModal(true);
275 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
276 dialog.setVisible(true);
277 }
278 } catch(Exception e) {
279 if (cancelled) {
280 System.out.println(tr("Warning: ignoring exception because task is cancelled. Exception: {0}", e.toString()));
281 return;
282 }
283 lastException = e;
284 } finally {
285 Main.pleaseWaitDlg.setAlwaysOnTop(false);
286 setIndeterminateEnabled(false);
287 }
288 }
289 }
290}
Note: See TracBrowser for help on using the repository browser.