source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationTree.java@ 14027

Last change on this file since 14027 was 12675, checked in by Don-vip, 7 years ago

see #15182 - move the Swing-based ProgressMonitor implementations from gui.progress to gui.progress.swing. Progress monitor concept is used in very large parts of JOSM, a console-based implementation could be added later

  • Property svn:eol-style set to native
File size: 5.2 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.Component;
7import java.awt.Dialog;
8import java.io.IOException;
9
10import javax.swing.JTree;
11import javax.swing.SwingUtilities;
12import javax.swing.event.TreeExpansionEvent;
13import javax.swing.event.TreeWillExpandListener;
14import javax.swing.tree.ExpandVetoException;
15import javax.swing.tree.TreePath;
16
17import org.openstreetmap.josm.data.osm.DataSet;
18import org.openstreetmap.josm.data.osm.DataSetMerger;
19import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
20import org.openstreetmap.josm.data.osm.Relation;
21import org.openstreetmap.josm.gui.MainApplication;
22import org.openstreetmap.josm.gui.PleaseWaitRunnable;
23import org.openstreetmap.josm.gui.progress.ProgressMonitor;
24import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
25import org.openstreetmap.josm.io.OsmApi;
26import org.openstreetmap.josm.io.OsmServerObjectReader;
27import org.openstreetmap.josm.io.OsmTransferException;
28import org.openstreetmap.josm.tools.Logging;
29import org.xml.sax.SAXException;
30
31/**
32 * This is a {@link JTree} rendering the hierarchical structure of {@link Relation}s.
33 *
34 * @see RelationTreeModel
35 */
36public class RelationTree extends JTree {
37 /**
38 * builds the UI
39 */
40 protected void build() {
41 setRootVisible(false);
42 setCellRenderer(new RelationTreeCellRenderer());
43 addTreeWillExpandListener(new LazyRelationLoader());
44 }
45
46 /**
47 * constructor
48 */
49 public RelationTree() {
50 super();
51 build();
52 }
53
54 /**
55 * constructor
56 * @param model the tree model
57 */
58 public RelationTree(RelationTreeModel model) {
59 super(model);
60 build();
61 }
62
63 /**
64 * replies the parent dialog this tree is embedded in.
65 *
66 * @return the parent dialog; null, if there is no parent dialog
67 */
68 protected Dialog getParentDialog() {
69 Component c = this;
70 while (c != null && !(c instanceof Dialog)) {
71 c = c.getParent();
72 }
73 return (Dialog) c;
74 }
75
76 /**
77 * An adapter for TreeWillExpand-events. If a node is to be expanded which is
78 * not loaded yet this will trigger asynchronous loading of the respective
79 * relation.
80 *
81 */
82 class LazyRelationLoader implements TreeWillExpandListener {
83
84 @Override
85 public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException {
86 // do nothing
87 }
88
89 @Override
90 public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException {
91 TreePath path = event.getPath();
92 Relation parent = (Relation) event.getPath().getLastPathComponent();
93 if (!parent.isIncomplete() || parent.isNew())
94 // we don't load complete or new relations
95 return;
96 // launch the download task
97 MainApplication.worker.submit(new RelationLoader(getParentDialog(), parent, path));
98 }
99 }
100
101 /**
102 * Asynchronous download task for a specific relation
103 *
104 */
105 class RelationLoader extends PleaseWaitRunnable {
106 private boolean canceled;
107 private Exception lastException;
108 private final Relation relation;
109 private DataSet ds;
110 private final TreePath path;
111
112 RelationLoader(Dialog dialog, Relation relation, TreePath path) {
113 super(
114 tr("Load relation"),
115 new PleaseWaitProgressMonitor(
116 dialog
117 ),
118 false /* don't ignore exceptions */
119 );
120 this.relation = relation;
121 this.path = path;
122 }
123
124 @Override
125 protected void cancel() {
126 OsmApi.getOsmApi().cancel();
127 this.canceled = true;
128 }
129
130 @Override
131 protected void finish() {
132 if (canceled)
133 return;
134 if (lastException != null) {
135 Logging.error(lastException);
136 return;
137 }
138 DataSet editData = MainApplication.getLayerManager().getEditDataSet();
139 DataSetMerger visitor = new DataSetMerger(editData, ds);
140 visitor.merge();
141 if (!visitor.getConflicts().isEmpty()) {
142 editData.getConflicts().add(visitor.getConflicts());
143 }
144 final RelationTreeModel model = (RelationTreeModel) getModel();
145 SwingUtilities.invokeLater(() -> model.refreshNode(path));
146 }
147
148 @Override
149 protected void realRun() throws SAXException, IOException, OsmTransferException {
150 try {
151 OsmServerObjectReader reader = new OsmServerObjectReader(relation.getId(), OsmPrimitiveType.from(relation), true);
152 ds = reader.parseOsm(progressMonitor
153 .createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
154 } catch (OsmTransferException e) {
155 if (canceled) {
156 Logging.warn(tr("Ignoring exception because task was canceled. Exception: {0}", e.toString()));
157 return;
158 }
159 this.lastException = e;
160 }
161 }
162 }
163}
Note: See TracBrowser for help on using the repository browser.