source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/relation/RelationTreeModel.java@ 1843

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

new: tree-like browser for child relations
new: action/task for recursively downloading all child relations. Use case: download a complete network with cycle routes in one step
applied #2953: patch by cjw - Sorting a relation adds new members or crashes

File size: 7.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.relation;
3
4import java.util.List;
5import java.util.concurrent.CopyOnWriteArrayList;
6import java.util.logging.Logger;
7
8import javax.swing.event.TreeModelEvent;
9import javax.swing.event.TreeModelListener;
10import javax.swing.tree.TreeModel;
11import javax.swing.tree.TreePath;
12
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.RelationMember;
15
16/**
17 * This is a {@see TreeModel} which provides the hierarchical structure of {@see Relation}s
18 * to a {@see JTree}.
19 *
20 * The model is initialized with a root relation or with a list of {@see RelationMember}s, see
21 * {@see #populate(Relation)} and {@see #populate(List)} respectively.
22 *
23 *
24 */
25public class RelationTreeModel implements TreeModel {
26 private static final Logger logger = Logger.getLogger(RelationTreeModel.class.getName());
27
28 /** the root relation */
29 private Relation root;
30
31 /** the tree model listeners */
32 private CopyOnWriteArrayList<TreeModelListener> listeners;
33
34 /**
35 * constructor
36 */
37 public RelationTreeModel() {
38 this.root = null;
39 listeners = new CopyOnWriteArrayList<TreeModelListener>();
40 }
41
42 /**
43 * constructor
44 * @param root the root relation
45 */
46 public RelationTreeModel(Relation root) {
47 this.root = root;
48 listeners = new CopyOnWriteArrayList<TreeModelListener>();
49 }
50
51 /**
52 * constructor
53 *
54 * @param members a list of members
55 */
56 public RelationTreeModel(List<RelationMember> members) {
57 if (members == null) return;
58 Relation root = new Relation();
59 root.members.addAll(members);
60 this.root = root;
61 listeners = new CopyOnWriteArrayList<TreeModelListener>();
62 }
63
64 /**
65 * Replies the number of children of type relation for a particular
66 * relation <code>parent</code>
67 *
68 * @param parent the parent relation
69 * @return the number of children of type relation
70 */
71 protected int getNumRelationChildren(Relation parent) {
72 if (parent == null) return 0;
73 if (parent.members == null) return 0;
74 int count = 0;
75 for(RelationMember member : parent.members) {
76 if (member.member instanceof Relation) {
77 count++;
78 }
79 }
80 return count;
81 }
82
83 /**
84 * Replies the i-th child of type relation for a particular relation
85 * <code>parent</code>.
86 *
87 * @param parent the parent relation
88 * @param idx the index
89 * @return the i-th child of type relation for a particular relation
90 * <code>parent</code>; null, if no such child exists
91 */
92 protected Relation getRelationChildByIdx(Relation parent, int idx) {
93 if (parent == null) return null;
94 int count=0;
95 for (RelationMember member : parent.members) {
96 if (!(member.member instanceof Relation)) {
97 continue;
98 }
99 if (count == idx)
100 return (Relation)member.member;
101 count++;
102 }
103 return null;
104 }
105
106 /**
107 * Replies the index of a particular <code>child</code> with respect to its
108 * <code>parent</code>.
109 *
110 * @param parent the parent relation
111 * @param child the child relation
112 * @return the index of a particular <code>child</code> with respect to its
113 * <code>parent</code>; -1 if either parent or child are null or if <code>child</code>
114 * isn't a child of <code>parent</code>.
115 *
116 */
117 protected int getIndexForRelationChild(Relation parent, Relation child) {
118 if (parent == null || child == null) return -1;
119 int idx = 0;
120 for (RelationMember member : parent.members) {
121 if (!(member.member instanceof Relation)) {
122 continue;
123 }
124 if (member.member == child) return idx;
125 idx++;
126 }
127 return -1;
128 }
129
130 /**
131 * Populates the model with a root relation
132 *
133 * @param root the root relation
134 * @see #populate(List)
135 *
136 */
137 public void populate(Relation root) {
138 this.root = root;
139 fireRootReplacedEvent();
140 }
141
142 /**
143 * Populates the model with a list of relation members
144 *
145 * @param members the relation members
146 */
147 public void populate(List<RelationMember> members) {
148 if (members == null) return;
149 Relation r = new Relation();
150 r.members.addAll(members);
151 this.root = r;
152 fireRootReplacedEvent();
153 }
154
155 /**
156 * Notifies tree model listeners about a replacement of the
157 * root.
158 */
159 protected void fireRootReplacedEvent() {
160 TreeModelEvent e = new TreeModelEvent(this, new TreePath(root));
161 for (TreeModelListener l : listeners) {
162 l.treeStructureChanged(e);
163 }
164 }
165
166 /**
167 * Notifies tree model listeners about an update of the
168 * trees nodes.
169 *
170 * @param path the tree path to the node
171 */
172 protected void fireRefreshNode(TreePath path) {
173 TreeModelEvent e = new TreeModelEvent(this, path);
174 for (TreeModelListener l : listeners) {
175 l.treeStructureChanged(e);
176 }
177
178 }
179
180 /**
181 * Invoke to notify all listeners about an update of a particular node
182 *
183 * @param pathToNode the tree path to the node
184 */
185 public void refreshNode(TreePath pathToNode) {
186 fireRefreshNode(pathToNode);
187 }
188
189 /* ----------------------------------------------------------------------- */
190 /* interface TreeModel */
191 /* ----------------------------------------------------------------------- */
192 public Object getChild(Object parent, int index) {
193 return getRelationChildByIdx((Relation)parent, index);
194 }
195
196 public int getChildCount(Object parent) {
197 return getNumRelationChildren((Relation)parent);
198 }
199
200 public int getIndexOfChild(Object parent, Object child) {
201 return getIndexForRelationChild((Relation)parent, (Relation)child);
202 }
203
204 public Object getRoot() {
205 return root;
206 }
207
208 public boolean isLeaf(Object node) {
209 Relation r = (Relation)node;
210 if (r.incomplete) return false;
211 return getNumRelationChildren(r) == 0;
212 }
213
214 public void addTreeModelListener(TreeModelListener l) {
215 synchronized (listeners) {
216 if (l != null && !listeners.contains(l)) {
217 listeners.add(l);
218 }
219 }
220 }
221
222 public void removeTreeModelListener(TreeModelListener l) {
223 synchronized (listeners) {
224 if (l != null && listeners.contains(l)) {
225 listeners.remove(l);
226 }
227 }
228 }
229
230 public void valueForPathChanged(TreePath path, Object newValue) {
231 // do nothing
232 }
233}
Note: See TracBrowser for help on using the repository browser.