[3952] | 1 | package nu.fw.jeti.util; |
---|
| 2 | |
---|
| 3 | import java.util.ArrayList; |
---|
| 4 | import java.util.Hashtable; |
---|
| 5 | import java.util.LinkedList; |
---|
| 6 | |
---|
| 7 | import javax.swing.event.TreeModelEvent; |
---|
| 8 | import javax.swing.event.TreeModelListener; |
---|
| 9 | import javax.swing.tree.TreeModel; |
---|
| 10 | import javax.swing.tree.TreePath; |
---|
| 11 | |
---|
| 12 | /** |
---|
| 13 | * Used to filter some nodes from a tree. That is nodes which the |
---|
| 14 | * selector decides not to show does not seem to exist in the tree. |
---|
| 15 | * The selector is assumed to not change behavior over time. |
---|
| 16 | * |
---|
| 17 | * @author Martin Forssen |
---|
| 18 | */ |
---|
| 19 | |
---|
| 20 | public class TreeModelFilter implements TreeModel, TreeModelListener { |
---|
| 21 | private TreeModelSelector selector; |
---|
| 22 | private TreeModel model; |
---|
| 23 | private LinkedList listeners = new LinkedList(); |
---|
| 24 | private Hashtable nodes = new Hashtable(30); |
---|
| 25 | |
---|
| 26 | public TreeModelFilter(TreeModel model, TreeModelSelector selector) { |
---|
| 27 | this.model = model; |
---|
| 28 | this.selector = selector; |
---|
| 29 | |
---|
| 30 | model.addTreeModelListener(this); |
---|
| 31 | } |
---|
| 32 | |
---|
| 33 | /* |
---|
| 34 | * TreeModel interface |
---|
| 35 | */ |
---|
| 36 | public Object getRoot() { |
---|
| 37 | return model.getRoot(); |
---|
| 38 | } |
---|
| 39 | |
---|
| 40 | public Object getChild(Object parent, int index) { |
---|
| 41 | int max = model.getChildCount(parent); |
---|
| 42 | for (int i=0, v=0; i<max; i++) { |
---|
| 43 | Object child = model.getChild(parent, i); |
---|
| 44 | boolean isVisible = selector.isVisible(child); |
---|
| 45 | nodes.put(child, Boolean.valueOf(isVisible)); |
---|
| 46 | if (isVisible && index == v++) { |
---|
| 47 | return child; |
---|
| 48 | } |
---|
| 49 | } |
---|
| 50 | return null; |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | public int getChildCount(Object parent) { |
---|
| 54 | int max = model.getChildCount(parent); |
---|
| 55 | int count = 0; |
---|
| 56 | |
---|
| 57 | for (int i=0; i<max; i++) { |
---|
| 58 | Object child = model.getChild(parent, i); |
---|
| 59 | boolean isVisible = selector.isVisible(child); |
---|
| 60 | nodes.put(child,Boolean.valueOf(isVisible)); |
---|
| 61 | if (isVisible) { |
---|
| 62 | count++; |
---|
| 63 | } |
---|
| 64 | } |
---|
| 65 | return count; |
---|
| 66 | } |
---|
| 67 | |
---|
| 68 | public boolean isLeaf(Object node) { |
---|
| 69 | return model.isLeaf(node); |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | public void valueForPathChanged(TreePath path, Object newValue) { |
---|
| 73 | // TODO |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | public int getIndexOfChild(Object parent, Object child) { |
---|
| 77 | int max = model.getChildCount(parent); |
---|
| 78 | for (int i=0, v=0; i<max; i++) { |
---|
| 79 | Object mChild = model.getChild(parent, i); |
---|
| 80 | if (mChild.equals(child)) { |
---|
| 81 | return v; |
---|
| 82 | } |
---|
| 83 | if (selector.isVisible(child)) { |
---|
| 84 | v++; |
---|
| 85 | } |
---|
| 86 | } |
---|
| 87 | return -1; |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | public void addTreeModelListener(TreeModelListener l) { |
---|
| 91 | listeners.add(l); |
---|
| 92 | } |
---|
| 93 | |
---|
| 94 | public void removeTreeModelListener(TreeModelListener l) { |
---|
| 95 | listeners.remove(l); |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | /* |
---|
| 99 | * TreeModelListener interface |
---|
| 100 | */ |
---|
| 101 | public void treeNodesChanged(TreeModelEvent e) { |
---|
| 102 | int indices[] = e.getChildIndices(); |
---|
| 103 | Object children[] = e.getChildren(); |
---|
| 104 | |
---|
| 105 | if (indices == null || indices.length == 0) { |
---|
| 106 | TreeModelEvent e2 = new TreeModelEvent(this, e.getTreePath()); |
---|
| 107 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 108 | ((TreeModelListener)listeners.get(i)).treeNodesChanged(e2); |
---|
| 109 | } |
---|
| 110 | } else { |
---|
| 111 | for (int i=0, v=0; i < indices.length; i++) { |
---|
| 112 | nodeChanged(e.getTreePath(), indices[i], children[i]); |
---|
| 113 | } |
---|
| 114 | } |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | public void treeNodesInserted(TreeModelEvent e) { |
---|
| 118 | ArrayList newIndices = new ArrayList(); |
---|
| 119 | ArrayList newChildren = new ArrayList(); |
---|
| 120 | Object parent = e.getTreePath().getLastPathComponent(); |
---|
| 121 | int indices[] = e.getChildIndices(); |
---|
| 122 | Object children[] = e.getChildren(); |
---|
| 123 | |
---|
| 124 | for (int i=0, v=0; i < indices.length; i++) { |
---|
| 125 | boolean vis = selector.isVisible(children[i]); |
---|
| 126 | nodes.put(children[i], Boolean.valueOf(vis)); |
---|
| 127 | if (vis) { |
---|
| 128 | newIndices.add(new Integer(upperIndex(parent, indices[i]))); |
---|
| 129 | newChildren.add(children[i]); |
---|
| 130 | } |
---|
| 131 | } |
---|
| 132 | if (newIndices.size() > 0) { |
---|
| 133 | TreeModelEvent e2 = createEvent(e.getTreePath(), newIndices, |
---|
| 134 | newChildren); |
---|
| 135 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 136 | ((TreeModelListener)listeners.get(i)).treeNodesInserted(e2); |
---|
| 137 | } |
---|
| 138 | } |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | public void treeNodesRemoved(TreeModelEvent e) { |
---|
| 142 | ArrayList newIndices = new ArrayList(); |
---|
| 143 | ArrayList newChildren = new ArrayList(); |
---|
| 144 | Object parent = e.getTreePath().getLastPathComponent(); |
---|
| 145 | int indices[] = e.getChildIndices(); |
---|
| 146 | Object children[] = e.getChildren(); |
---|
| 147 | |
---|
| 148 | for (int i=0, v=0; i < indices.length; i++) { |
---|
| 149 | Boolean visible = (Boolean)nodes.get(children[i]); |
---|
| 150 | if (visible != null && visible.booleanValue()) { |
---|
| 151 | newIndices.add(new Integer(upperIndex(parent, indices[i]))); |
---|
| 152 | newChildren.add(children[i]); |
---|
| 153 | } |
---|
| 154 | nodes.remove(children[i]); |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | if (newIndices.size() > 0) { |
---|
| 158 | TreeModelEvent e2 = createEvent(e.getTreePath(), newIndices, |
---|
| 159 | newChildren); |
---|
| 160 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 161 | ((TreeModelListener)listeners.get(i)).treeNodesRemoved(e2); |
---|
| 162 | } |
---|
| 163 | } |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | public void treeStructureChanged(TreeModelEvent e) { |
---|
| 167 | TreePath path = e.getTreePath(); |
---|
| 168 | Object node = path.getLastPathComponent(); |
---|
| 169 | nodes.put(node, Boolean.valueOf(selector.isVisible(node))); |
---|
| 170 | if (path.getPathCount() > 1) { |
---|
| 171 | path = path.getParentPath(); |
---|
| 172 | } |
---|
| 173 | TreeModelEvent e2 = new TreeModelEvent(this, path); |
---|
| 174 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 175 | ((TreeModelListener)listeners.get(i)).treeStructureChanged(e2); |
---|
| 176 | } |
---|
| 177 | } |
---|
| 178 | |
---|
| 179 | private TreeModelEvent createEvent(TreePath path, |
---|
| 180 | ArrayList indices, |
---|
| 181 | ArrayList children) { |
---|
| 182 | int intIndices[] = new int[indices.size()]; |
---|
| 183 | for (int i=0; i<indices.size(); i++) { |
---|
| 184 | intIndices[i] = ((Integer)indices.get(i)).intValue(); |
---|
| 185 | } |
---|
| 186 | return new TreeModelEvent( |
---|
| 187 | this, path, intIndices, |
---|
| 188 | children.toArray(new Object[children.size()])); |
---|
| 189 | } |
---|
| 190 | |
---|
| 191 | private int upperIndex(Object parent, int index) { |
---|
| 192 | int vIndex = 0; |
---|
| 193 | for (int i=0; i < index; i++) { |
---|
| 194 | if (selector.isVisible(model.getChild(parent, i))) { |
---|
| 195 | vIndex++; |
---|
| 196 | } |
---|
| 197 | } |
---|
| 198 | return vIndex; |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | private void nodeChanged(TreePath path, int index, Object node) { |
---|
| 202 | Object parent = path.getLastPathComponent(); |
---|
| 203 | |
---|
| 204 | boolean newVis = selector.isVisible(node); |
---|
| 205 | Boolean oldVis = (Boolean)nodes.get(node); |
---|
| 206 | if (newVis && (oldVis == null || !oldVis.booleanValue())) { |
---|
| 207 | int indices[] = {upperIndex(parent, index)}; |
---|
| 208 | Object children[] = {node}; |
---|
| 209 | TreeModelEvent e = new TreeModelEvent(this, path,indices,children); |
---|
| 210 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 211 | ((TreeModelListener)listeners.get(i)).treeNodesInserted(e); |
---|
| 212 | } |
---|
| 213 | } else if (!newVis && oldVis != null && oldVis.booleanValue()) { |
---|
| 214 | int indices[] = {upperIndex(parent, index)}; |
---|
| 215 | Object children[] = {node}; |
---|
| 216 | TreeModelEvent e = new TreeModelEvent(this, path,indices,children); |
---|
| 217 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 218 | ((TreeModelListener)listeners.get(i)).treeNodesRemoved(e); |
---|
| 219 | } |
---|
| 220 | } else if (newVis && oldVis != null && oldVis.booleanValue()) { |
---|
| 221 | int vIndex = upperIndex(path.getLastPathComponent(), index); |
---|
| 222 | TreeModelEvent e = new TreeModelEvent(this, path, |
---|
| 223 | new int[] {vIndex}, |
---|
| 224 | new Object[] {node}); |
---|
| 225 | for (int i = 0; i < listeners.size(); i++) { |
---|
| 226 | ((TreeModelListener)listeners.get(i)).treeNodesChanged(e); |
---|
| 227 | } |
---|
| 228 | } |
---|
| 229 | nodes.put(node, Boolean.valueOf(newVis)); |
---|
| 230 | } |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | /* |
---|
| 234 | * Overrides for emacs |
---|
| 235 | * Local variables: |
---|
| 236 | * tab-width: 4 |
---|
| 237 | * End: |
---|
| 238 | */ |
---|