📄 elementtreepanel.java
字号:
// TreeSelectionListener /** * Called whenever the value of the selection changes. * @param e the event that characterizes the change. */ public void valueChanged(TreeSelectionEvent e) { JTree tree = getTree(); if(!updatingSelection && tree.getSelectionCount() == 1) { TreePath selPath = tree.getSelectionPath(); Object lastPathComponent = selPath.getLastPathComponent(); if(!(lastPathComponent instanceof DefaultMutableTreeNode)) { Element selElement = (Element)lastPathComponent; updatingSelection = true; try { getEditor().select(selElement.getStartOffset(), selElement.getEndOffset()); } finally { updatingSelection = false; } } } } // Local methods /** * @return tree showing elements. */ protected JTree getTree() { return tree; } /** * @return JTextComponent showing elements for. */ protected JTextComponent getEditor() { return editor; } /** * @return TreeModel implementation used to represent the elements. */ public DefaultTreeModel getTreeModel() { return treeModel; } /** * Updates the tree based on the event type. This will invoke either * updateTree with the root element, or handleChange. */ protected void updateTree(DocumentEvent event) { updatingSelection = true; try { TreeModel model = getTreeModel(); Object root = model.getRoot(); for(int counter = model.getChildCount(root) - 1; counter >= 0; counter--) { updateTree(event, (Element)model.getChild(root, counter)); } } finally { updatingSelection = false; } } /** * Creates TreeModelEvents based on the DocumentEvent and messages * the treemodel. This recursively invokes this method with children * elements. * @param event indicates what elements in the tree hierarchy have * changed. * @param element Current element to check for changes against. */ protected void updateTree(DocumentEvent event, Element element) { DocumentEvent.ElementChange ec = event.getChange(element); if (ec != null) { Element[] removed = ec.getChildrenRemoved(); Element[] added = ec.getChildrenAdded(); int startIndex = ec.getIndex(); // Check for removed. if(removed != null && removed.length > 0) { int[] indices = new int[removed.length]; for(int counter = 0; counter < removed.length; counter++) { indices[counter] = startIndex + counter; } getTreeModel().nodesWereRemoved((TreeNode)element, indices, removed); } // check for added if(added != null && added.length > 0) { int[] indices = new int[added.length]; for(int counter = 0; counter < added.length; counter++) { indices[counter] = startIndex + counter; } getTreeModel().nodesWereInserted((TreeNode)element, indices); } } if(!element.isLeaf()) { int startIndex = element.getElementIndex (event.getOffset()); int elementCount = element.getElementCount(); int endIndex = Math.min(elementCount - 1, element.getElementIndex (event.getOffset() + event.getLength())); if(startIndex > 0 && startIndex < elementCount && element.getElement(startIndex).getStartOffset() == event.getOffset()) { // Force checking the previous element. startIndex--; } if(startIndex != -1 && endIndex != -1) { for(int counter = startIndex; counter <= endIndex; counter++) { updateTree(event, element.getElement(counter)); } } } else { // Element is a leaf, assume it changed getTreeModel().nodeChanged((TreeNode)element); } } /** * Returns a TreePath to the element at <code>position</code>. */ protected TreePath getPathForIndex(int position, Object root, Element rootElement) { TreePath path = new TreePath(root); Element child = rootElement.getElement (rootElement.getElementIndex(position)); path = path.pathByAddingChild(rootElement); path = path.pathByAddingChild(child); while(!child.isLeaf()) { child = child.getElement(child.getElementIndex(position)); path = path.pathByAddingChild(child); } return path; } /** * ElementTreeModel is an implementation of TreeModel to handle displaying * the Elements from a Document. AbstractDocument.AbstractElement is * the default implementation used by the swing text package to implement * Element, and it implements TreeNode. This makes it trivial to create * a DefaultTreeModel rooted at a particular Element from the Document. * Unfortunately each Document can have more than one root Element. * Implying that to display all the root elements as a child of another * root a fake node has be created. This class creates a fake node as * the root with the children being the root elements of the Document * (getRootElements). * <p>This subclasses DefaultTreeModel. The majority of the TreeModel * methods have been subclassed, primarily to special case the root. */ public static class ElementTreeModel extends DefaultTreeModel { protected Element[] rootElements; public ElementTreeModel(Document document) { super(new DefaultMutableTreeNode("root"), false); rootElements = document.getRootElements(); } /** * Returns the child of <I>parent</I> at index <I>index</I> in * the parent's child array. <I>parent</I> must be a node * previously obtained from this data source. This should * not return null if <i>index</i> is a valid index for * <i>parent</i> (that is <i>index</i> >= 0 && <i>index</i> * < getChildCount(<i>parent</i>)). * * @param parent a node in the tree, obtained from this data source * @return the child of <I>parent</I> at index <I>index</I> */ public Object getChild(Object parent, int index) { if(parent == root) return rootElements[index]; return super.getChild(parent, index); } /** * Returns the number of children of <I>parent</I>. Returns 0 * if the node is a leaf or if it has no children. * <I>parent</I> must be a node previously obtained from this * data source. * * @param parent a node in the tree, obtained from this data source * @return the number of children of the node <I>parent</I> */ public int getChildCount(Object parent) { if(parent == root) return rootElements.length; return super.getChildCount(parent); } /** * Returns true if <I>node</I> is a leaf. It is possible for * this method to return false even if <I>node</I> has no * children. A directory in a filesystem, for example, may * contain no files; the node representing the directory is * not a leaf, but it also has no children. * * @param node a node in the tree, obtained from this data source * @return true if <I>node</I> is a leaf */ public boolean isLeaf(Object node) { if(node == root) return false; return super.isLeaf(node); } /** * Returns the index of child in parent. */ public int getIndexOfChild(Object parent, Object child) { if(parent == root) { for(int counter = rootElements.length - 1; counter >= 0; counter--) { if(rootElements[counter] == child) return counter; } return -1; } return super.getIndexOfChild(parent, child); } /** * Invoke this method after you've changed how node is to be * represented in the tree. */ public void nodeChanged(TreeNode node) { if(listenerList != null && node != null) { TreeNode parent = node.getParent(); if(parent == null && node != root) { parent = root; } if(parent != null) { int anIndex = getIndexOfChild(parent, node); if(anIndex != -1) { int[] cIndexs = new int[1]; cIndexs[0] = anIndex; nodesChanged(parent, cIndexs); } } } } /** * Returns the path to a particluar node. This is recursive. */ protected TreeNode[] getPathToRoot(TreeNode aNode, int depth) { TreeNode[] retNodes; /* Check for null, in case someone passed in a null node, or they passed in an element that isn't rooted at root. */ if(aNode == null) { if(depth == 0) return null; else retNodes = new TreeNode[depth]; } else { depth++; if(aNode == root) retNodes = new TreeNode[depth]; else { TreeNode parent = aNode.getParent(); if(parent == null) parent = root; retNodes = getPathToRoot(parent, depth); } retNodes[retNodes.length - depth] = aNode; } return retNodes; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -