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