1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 // *** HideableTreeModel ***
24 import java.awt.*;
25 import java.awt.event.*;
26 import java.util.ArrayList;
27 import java.util.Enumeration;
28 import java.util.Vector;
29 import javax.swing.*;
30 import javax.swing.event.*;
31 import javax.swing.tree.*;
32 
33 
34 public class HideableTreeModel implements TreeModel {
35 
36 	private Vector modelListeners = new Vector();
37 	private Object root = null;
38 
39 
HideableTreeModel(TreeNode _root)40         public HideableTreeModel(TreeNode _root) {
41             super();
42             setRoot(_root);
43 	}
44 
45 
getRoot()46 	public Object getRoot() {
47 		return this.root;
48 	}
49 
50 
setRoot(Object r)51         protected void setRoot(Object r) {
52             this.root = r;
53 	}
54 
55 
getPathToRoot(Object node)56         public Object[] getPathToRoot(Object node) {
57             return getPathToRoot(node, 0);
58 	}
59 
60 
getPathToRoot(Object node, int i)61         private Object[] getPathToRoot(Object node, int i) {
62             Object anode[];
63             if(node == null) {
64                 if(i == 0) {
65                     return null;
66                 }
67                 anode = new Object[i];
68             } else {
69                 i++;
70                 if(node == getRoot()) {
71                     anode = new Object[i];
72                 } else {
73                     anode = getPathToRoot(getParent(node), i);
74                 }
75                 anode[anode.length - i] = node;
76             }
77             return anode;
78 	}
79 
80 
addTreeModelListener(TreeModelListener l)81         public void addTreeModelListener(TreeModelListener l) {
82             modelListeners.addElement(l);
83 	}
84 
85 
removeTreeModelListener(TreeModelListener l)86         public void removeTreeModelListener(TreeModelListener l) {
87             modelListeners.removeElement(l);
88 	}
89 
90 
reload()91 	public void reload() {
92             reload(getRoot());
93 	}
94 
95 
reload(Object node)96         public void reload(Object node) {
97             if(node != null) {
98                 TreePath tp = new TreePath(getPathToRoot(node));
99                 fireTreeStructureChanged(new TreeModelEvent(this, tp));
100             }
101 	}
102 
103 
valueForPathChanged(TreePath path, Object newValue)104         public void valueForPathChanged(TreePath path, Object newValue) {
105             nodeChanged(path.getLastPathComponent());
106 	}
107 
nodeInserted(Object node, Object child)108 	public void nodeInserted(Object node, Object child) {
109             nodeInserted(node, child, -1);
110 	}
111 
112 
nodeInserted(Object node, Object child, int index)113         public void nodeInserted(Object node, Object child, int index) {
114             if(index < 0) {
115                 index = getIndexOfChild(node, child);
116             }
117             if(node != null && child != null && index >= 0) {
118                 TreePath tp = new TreePath(getPathToRoot(node));
119                 int[] ai = { index };
120                 Object[] ac = { child };
121                 fireTreeNodesInserted(new TreeModelEvent(this, tp, ai, ac));
122             }
123 	}
124 
125 
nodeRemoved(Object node, Object child, int index)126         public void nodeRemoved(Object node, Object child, int index) {
127             if(node != null && child != null && index >= 0) {
128                 TreePath tp = new TreePath(getPathToRoot(node));
129                 int[] ai = { index };
130                 Object[] ac = { child };
131                 fireTreeNodesRemoved(new TreeModelEvent(this, tp, ai, ac));
132             }
133 	}
134 
135 
nodeChanged(Object node)136         public void nodeChanged(Object node) {
137             if(node != null) {
138                 TreePath tp = new TreePath(getPathToRoot(node));
139                 fireTreeNodesChanged(new TreeModelEvent(this, tp, null, null));
140             }
141 	}
142 
143 
fireTreeNodesChanged(TreeModelEvent event)144         protected void fireTreeNodesChanged(TreeModelEvent event) {
145             for(int i = 0; i < modelListeners.size(); i++) {
146                 ((TreeModelListener)modelListeners.elementAt(i)).treeNodesChanged(event);
147             }
148 	}
149 
150 
fireTreeNodesInserted(TreeModelEvent event)151         protected void fireTreeNodesInserted(TreeModelEvent event) {
152             for(int i = 0; i < modelListeners.size(); i++) {
153                 ((TreeModelListener)modelListeners.elementAt(i)).treeNodesInserted(event);
154             }
155 	}
156 
157 
fireTreeNodesRemoved(TreeModelEvent event)158         protected void fireTreeNodesRemoved(TreeModelEvent event) {
159             for(int i = 0; i < modelListeners.size(); i++) {
160                 ((TreeModelListener)modelListeners.elementAt(i)).treeNodesRemoved(event);
161             }
162 	}
163 
fireTreeStructureChanged(TreeModelEvent event)164 	protected void fireTreeStructureChanged(TreeModelEvent event) {
165             for(int i = 0; i < modelListeners.size(); i++) {
166                 ((TreeModelListener)modelListeners.elementAt(i)).treeStructureChanged(event);
167             }
168 	}
169 
170 
getExpandedPaths(JTree tree)171         public ArrayList getExpandedPaths(JTree tree) {
172 		ArrayList expandedPaths = new ArrayList();
173 		addExpandedPaths(tree, tree.getPathForRow(0), expandedPaths);
174 		return expandedPaths;
175 	}
176 
177 
addExpandedPaths(JTree tree, TreePath path, ArrayList pathlist)178         private void addExpandedPaths(JTree tree, TreePath path, ArrayList pathlist) {
179             Enumeration aEnum = tree.getExpandedDescendants(path);
180             while(aEnum.hasMoreElements()) {
181                 TreePath tp = (TreePath) aEnum.nextElement();
182                 pathlist.add(tp);
183                 addExpandedPaths(tree, tp, pathlist);
184             }
185 	}
186 
187 
expandPaths(JTree tree, ArrayList pathlist)188         public void expandPaths(JTree tree, ArrayList pathlist) {
189             for(int i = 0; i < pathlist.size(); i++) {
190                 tree.expandPath((TreePath)pathlist.get(i));
191             }
192 	}
193 
194 
isLeaf(Object _oNode)195         public boolean isLeaf(Object _oNode) {
196             if(_oNode instanceof TreeNode) {
197                 return ((TreeNode) _oNode).isLeaf();
198             }
199             return true;
200 	}
201 
202 
203 
getParent(Object node)204 	public Object getParent(Object node) {
205             if(node != getRoot() && (node instanceof TreeNode)) {
206                 return ((TreeNode)node).getParent();
207             }
208             return null;
209 	}
210 
211 
isNodeVisible(Object node)212         public boolean isNodeVisible(Object node) {
213             if(node != getRoot()) {
214                 if(node instanceof HideableMutableTreeNode) {
215                         return ((HideableMutableTreeNode)node).isVisible();
216                 }
217             }
218             return true;
219 	}
220 
221 
setNodeVisible(Object node, boolean v)222         public boolean setNodeVisible(Object node, boolean v) {
223             // can't hide root
224             if(node != getRoot()) {
225                 if(node instanceof HideableMutableTreeNode) {
226                     HideableMutableTreeNode n = (HideableMutableTreeNode)node;
227                     if(v != n.isVisible()) {
228                         TreeNode parent = n.getParent();
229                         if(v) {
230                             // need to get index after showing...
231                             n.setVisible(v);
232                             int index = getIndexOfChild(parent, n);
233                             nodeInserted(parent, n, index);
234                         } else {
235                             // need to get index before hiding...
236                             int index = getIndexOfChild(parent, n);
237                             n.setVisible(v);
238                             nodeRemoved(parent, n, index);
239                         }
240                     }
241                     return true;
242                 }
243             }
244             return false;
245 	}
246 
247 
isPathToNodeVisible(Object node)248         public boolean isPathToNodeVisible(Object node) {
249             Object[] path = getPathToRoot(node);
250             for(int i = 0; i < path.length; i++) {
251                 if(!isNodeVisible(path[i])) {
252                     return false;
253                 }
254             }
255             return true;
256 	}
257 
258 
ensurePathToNodeVisible(Object node)259         public void ensurePathToNodeVisible(Object node) {
260             Object[] path = getPathToRoot(node);
261             for(int i = 0; i < path.length; i++) {
262                 setNodeVisible(path[i], true);
263             }
264 	}
265 
266 
getChild(Object parent, int index)267         public Object getChild(Object parent, int index) {
268             if(parent instanceof TreeNode) {
269                 TreeNode p = (TreeNode) parent;
270                 for(int i = 0, j = -1; i < p.getChildCount(); i++) {
271                     TreeNode pc = (TreeNode)p.getChildAt(i);
272                     if(isNodeVisible(pc)) {
273                         j++;
274                     }
275                     if(j == index) {
276                         return pc;
277                     }
278                 }
279             }
280             return null;
281 	}
282 
283 
getChildCount(Object parent)284         public int getChildCount(Object parent) {
285             int count = 0;
286             if(parent instanceof TreeNode) {
287                 TreeNode p = (TreeNode) parent;
288                 for(int i = 0; i < p.getChildCount(); i++) {
289                     TreeNode pc = (TreeNode)p.getChildAt(i);
290                     if(isNodeVisible(pc)) {
291                         count++;
292                     }
293                 }
294             }
295             return count;
296 	}
297 
298 
getIndexOfChild(Object parent, Object child)299         public int getIndexOfChild(Object parent, Object child) {
300             int index = -1;
301             if(parent instanceof TreeNode && child instanceof TreeNode) {
302                 TreeNode p = (TreeNode)parent;
303                 TreeNode c = (TreeNode)child;
304                 if(isNodeVisible(c)) {
305                     index = 0;
306                     for(int i = 0; i < p.getChildCount(); i++) {
307                         TreeNode pc = (TreeNode)p.getChildAt(i);
308                         if(pc.equals(c)) {
309                             return index;
310                         }
311                         if(isNodeVisible(pc)) {
312                             index++;
313                         }
314                     }
315                 }
316             }
317             return index;
318 	}
319 }