1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.grinder.console.swingui;
23
24 import java.util.ArrayList;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29
30 import javax.swing.event.EventListenerList;
31 import javax.swing.event.TreeModelEvent;
32 import javax.swing.event.TreeModelListener;
33 import javax.swing.tree.TreeModel;
34 import javax.swing.tree.TreePath;
35
36
37
38
39
40
41
42
43
44
45
46 final class CompositeTreeModel implements TreeModel {
47
48 private final List<DelegateWrapper> m_wrappers =
49 new ArrayList<DelegateWrapper>();
50
51 private final EventListenerList m_listeners = new EventListenerList();
52
53 private final Object m_rootNode = new Object();
54
55 CompositeTreeModel() {
56 }
57
58 void addTreeModel(TreeModel treeModel, boolean includeRoot) {
59
60 final DelegateWrapper wrapper;
61
62 if (includeRoot) {
63 wrapper = new RootWrapper(treeModel);
64 }
65 else {
66 wrapper = new FirstLevelWrapper(treeModel);
67 }
68
69 final EventListener[] eventListeners =
70 m_listeners.getListeners(TreeModelListener.class);
71
72 for (int i = 0; i < eventListeners.length; ++i) {
73 wrapper.addTreeModelListener((TreeModelListener)eventListeners[i]);
74 }
75
76 m_wrappers.add(wrapper);
77 }
78
79 public Object getRoot() {
80 return m_rootNode;
81 }
82
83 public Object getChild(Object parent, int index) {
84 if (index < 0) {
85 return null;
86 }
87 else if (parent.equals(getRoot())) {
88 int base = 0;
89
90 for (DelegateWrapper wrapper : m_wrappers) {
91 final int numberOfTopLevelNodes = wrapper.getNumberOfTopLevelNodes();
92
93 if (index - base < numberOfTopLevelNodes) {
94 return wrapper.getTopLevelNode(index - base);
95 }
96
97 base += numberOfTopLevelNodes;
98 }
99 }
100 else {
101 for (DelegateWrapper wrapper : m_wrappers) {
102 final Object delegateAnswer = wrapper.getChild(parent, index);
103
104 if (delegateAnswer != null) {
105 return delegateAnswer;
106 }
107 }
108 }
109
110 return null;
111 }
112
113 public int getChildCount(Object parent) {
114 if (parent.equals(getRoot())) {
115 int answer = 0;
116
117 for (DelegateWrapper wrapper : m_wrappers) {
118 answer += wrapper.getNumberOfTopLevelNodes();
119 }
120
121 return answer;
122 }
123 else {
124 for (DelegateWrapper wrapper : m_wrappers) {
125 final int delegateAnswer = wrapper.getChildCount(parent);
126
127 if (delegateAnswer != 0) {
128 return delegateAnswer;
129 }
130 }
131 }
132
133 return 0;
134 }
135
136 public int getIndexOfChild(Object parent, Object child) {
137
138 if (parent == null || child == null) {
139
140 return -1;
141 }
142
143 if (parent.equals(getRoot())) {
144 int base = 0;
145
146 for (DelegateWrapper wrapper : m_wrappers) {
147 final int delegateAnswer = wrapper.getIndexOfTopLevelNode(child);
148
149 if (delegateAnswer != -1) {
150 return base + delegateAnswer;
151 }
152
153 base += wrapper.getNumberOfTopLevelNodes();
154 }
155 }
156 else {
157 for (DelegateWrapper wrapper : m_wrappers) {
158 final int delegateAnswer = wrapper.getIndexOfChild(parent, child);
159
160 if (delegateAnswer != -1) {
161 return delegateAnswer;
162 }
163 }
164 }
165
166 return -1;
167 }
168
169 public boolean isLeaf(Object node) {
170 for (DelegateWrapper wrapper : m_wrappers) {
171 if (wrapper.isLeaf(node)) {
172 return true;
173 }
174 }
175
176 return false;
177 }
178
179 public void addTreeModelListener(TreeModelListener listener) {
180 m_listeners.add(TreeModelListener.class, listener);
181
182 for (DelegateWrapper wrapper : m_wrappers) {
183 wrapper.addTreeModelListener(listener);
184 }
185 }
186
187 public void removeTreeModelListener(TreeModelListener listener) {
188 m_listeners.remove(TreeModelListener.class, listener);
189
190 for (DelegateWrapper wrapper : m_wrappers) {
191 wrapper.removeTreeModelListener(listener);
192 }
193 }
194
195 public void valueForPathChanged(TreePath path, Object newValue) {
196
197 }
198
199 private abstract static class DelegateWrapper {
200 private final TreeModel m_model;
201 private final
202 Map<TreeModelListener, TreeModelListener> m_delegateListenerMap =
203 new HashMap<TreeModelListener, TreeModelListener>();
204
205 protected DelegateWrapper(TreeModel model) {
206 m_model = model;
207 }
208
209 public abstract Object getTopLevelNode(int i);
210
211 public abstract int getNumberOfTopLevelNodes();
212
213 public abstract int getIndexOfTopLevelNode(Object node);
214
215 public final TreeModel getModel() {
216 return m_model;
217 }
218
219 public final Object getChild(Object parent, int index) {
220 try {
221 return getModel().getChild(parent, index);
222 }
223 catch (ClassCastException e) {
224 return null;
225 }
226 }
227
228 public int getChildCount(Object parent) {
229 try {
230 return getModel().getChildCount(parent);
231 }
232 catch (ClassCastException e) {
233 return 0;
234 }
235 }
236
237 public int getIndexOfChild(Object parent, Object child) {
238 try {
239 return getModel().getIndexOfChild(parent, child);
240 }
241 catch (ClassCastException e) {
242 return -1;
243 }
244 }
245
246 public final boolean isLeaf(Object node) {
247 try {
248 return getModel().isLeaf(node);
249 }
250 catch (ClassCastException e) {
251 return false;
252 }
253 }
254
255 protected abstract TreeModelEvent mapTreeModelEvent(TreeModelEvent e);
256
257 public void addTreeModelListener(final TreeModelListener listener) {
258
259 final TreeModelListener delegateListener = new TreeModelListener() {
260 public void treeNodesChanged(TreeModelEvent e) {
261 listener.treeNodesChanged(mapTreeModelEvent(e));
262 }
263
264 public void treeNodesInserted(TreeModelEvent e) {
265 listener.treeNodesInserted(mapTreeModelEvent(e));
266 }
267
268 public void treeNodesRemoved(TreeModelEvent e) {
269 listener.treeNodesRemoved(mapTreeModelEvent(e));
270 }
271
272 public void treeStructureChanged(TreeModelEvent e) {
273 listener.treeStructureChanged(mapTreeModelEvent(e));
274 }
275 };
276
277 m_delegateListenerMap.put(listener, delegateListener);
278 getModel().addTreeModelListener(delegateListener);
279 }
280
281 public void removeTreeModelListener(TreeModelListener listener) {
282 final TreeModelListener delegateListener =
283 m_delegateListenerMap.remove(listener);
284
285 if (delegateListener != null) {
286 getModel().removeTreeModelListener(delegateListener);
287 }
288 }
289 }
290
291 private final class RootWrapper extends DelegateWrapper {
292 public RootWrapper(TreeModel model) {
293 super(model);
294 }
295
296 public Object getTopLevelNode(int i) {
297 return i == 0 ? getModel().getRoot() : null;
298 }
299
300 public int getNumberOfTopLevelNodes() {
301 return 1;
302 }
303
304 public int getIndexOfTopLevelNode(Object node) {
305 return node.equals(getModel().getRoot()) ? 0 : -1;
306 }
307
308 protected TreeModelEvent mapTreeModelEvent(TreeModelEvent e) {
309
310 final Object[] path = e.getPath();
311
312 if (path.length > 0 && path[0].equals(getRoot())) {
313 return e;
314 }
315
316 final Object[] newPath = new Object[path.length + 1];
317 System.arraycopy(path, 0, newPath, 1, path.length);
318 newPath[0] = getRoot();
319
320 return new TreeModelEvent(this,
321 newPath,
322 e.getChildIndices(),
323 e.getChildren());
324 }
325 }
326
327 private final class FirstLevelWrapper extends DelegateWrapper {
328 public FirstLevelWrapper(TreeModel model) {
329 super(model);
330 }
331
332 public Object getTopLevelNode(int i) {
333 return super.getChild(getModel().getRoot(), i);
334 }
335
336 public int getNumberOfTopLevelNodes() {
337 return super.getChildCount(getModel().getRoot());
338 }
339
340 public int getIndexOfTopLevelNode(Object node) {
341 return super.getIndexOfChild(getModel().getRoot(), node);
342 }
343
344 protected TreeModelEvent mapTreeModelEvent(TreeModelEvent e) {
345
346 final Object[] path = e.getPath();
347
348 if (path.length > 0) {
349 path[0] = getRoot();
350 }
351
352 return
353 new TreeModelEvent(this, path, e.getChildIndices(), e.getChildren());
354 }
355 }
356 }