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

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

fixed #3090: New relation cause exception

File size: 7.1 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 if (root == null) {
139 root = new Relation();
140 }
141 this.root = root;
142 fireRootReplacedEvent();
143 }
144
145 /**
146 * Populates the model with a list of relation members
147 *
148 * @param members the relation members
149 */
150 public void populate(List<RelationMember> members) {
151 if (members == null) return;
152 Relation r = new Relation();
153 r.members.addAll(members);
154 this.root = r;
155 fireRootReplacedEvent();
156 }
157
158 /**
159 * Notifies tree model listeners about a replacement of the
160 * root.
161 */
162 protected void fireRootReplacedEvent() {
163 TreeModelEvent e = new TreeModelEvent(this, new TreePath(root));
164 for (TreeModelListener l : listeners) {
165 l.treeStructureChanged(e);
166 }
167 }
168
169 /**
170 * Notifies tree model listeners about an update of the
171 * trees nodes.
172 *
173 * @param path the tree path to the node
174 */
175 protected void fireRefreshNode(TreePath path) {
176 TreeModelEvent e = new TreeModelEvent(this, path);
177 for (TreeModelListener l : listeners) {
178 l.treeStructureChanged(e);
179 }
180
181 }
182
183 /**
184 * Invoke to notify all listeners about an update of a particular node
185 *
186 * @param pathToNode the tree path to the node
187 */
188 public void refreshNode(TreePath pathToNode) {
189 fireRefreshNode(pathToNode);
190 }
191
192 /* ----------------------------------------------------------------------- */
193 /* interface TreeModel */
194 /* ----------------------------------------------------------------------- */
195 public Object getChild(Object parent, int index) {
196 return getRelationChildByIdx((Relation)parent, index);
197 }
198
199 public int getChildCount(Object parent) {
200 return getNumRelationChildren((Relation)parent);
201 }
202
203 public int getIndexOfChild(Object parent, Object child) {
204 return getIndexForRelationChild((Relation)parent, (Relation)child);
205 }
206
207 public Object getRoot() {
208 return root;
209 }
210
211 public boolean isLeaf(Object node) {
212 Relation r = (Relation)node;
213 if (r.incomplete) return false;
214 return getNumRelationChildren(r) == 0;
215 }
216
217 public void addTreeModelListener(TreeModelListener l) {
218 synchronized (listeners) {
219 if (l != null && !listeners.contains(l)) {
220 listeners.add(l);
221 }
222 }
223 }
224
225 public void removeTreeModelListener(TreeModelListener l) {
226 synchronized (listeners) {
227 if (l != null && listeners.contains(l)) {
228 listeners.remove(l);
229 }
230 }
231 }
232
233 public void valueForPathChanged(TreePath path, Object newValue) {
234 // do nothing
235 }
236}
Note: See TracBrowser for help on using the repository browser.