rangeimpl.java
来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,767 行 · 第 1/5 页
JAVA
1,767 行
* Traverses the "right boundary" of this range and * operates on each "boundary node" according to the * <code>how</code> parameter. It is a-priori assumed * by this method that the right boundary does * not contain the range's start container. * <p> * A "right boundary" is best visualized by thinking * of a sample tree:<pre> * A * /|\ * / | \ * / | \ * B C D * /|\ /|\ * E F G H I J * </pre> * Imagine first a range that begins between the * "E" and "F" nodes and ends between the * "I" and "J" nodes. The start container is * "B" and the end container is "D". Given this setup, * the following applies: * <p> * Partially Selected Nodes: B, D<br> * Fully Selected Nodes: F, G, C, H, I * <p> * The "right boundary" is the highest subtree node * that contains the ending container. The root of * this subtree is always partially selected. * <p> * In this example, the nodes that are traversed * as "right boundary" nodes are: H, I, and D. * * @param root The node that is the root of the "right boundary" subtree. * * @param how Specifies what type of traversal is being * requested (extract, clone, or delete). * Legal values for this argument are: * * <ol> * <li><code>EXTRACT_CONTENTS</code> - will produce * a node containing the boundaries content. * Partially selected nodes are copied, but fully * selected nodes are moved. * * <li><code>CLONE_CONTENTS</code> - will leave the * context tree of the range undisturbed, but will * produced cloned content. * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes within the boundary. * </ol> * * @return Returns a node that is the result of visiting nodes. * If the traversal operation is * <code>DELETE_CONTENTS</code> the return value is null. */ private Node traverseRightBoundary( Node root, int how ) { Node next = getSelectedNode( fEndContainer, fEndOffset-1 ); boolean isFullySelected = ( next!=fEndContainer ); if ( next==root ) return traverseNode( next, isFullySelected, false, how ); Node parent = next.getParentNode(); Node clonedParent = traverseNode( parent, false, false, how ); while( parent!=null ) { while( next!=null ) { Node prevSibling = next.getPreviousSibling(); Node clonedChild = traverseNode( next, isFullySelected, false, how ); if ( how!=DELETE_CONTENTS ) { clonedParent.insertBefore( clonedChild, clonedParent.getFirstChild() ); } isFullySelected = true; next = prevSibling; } if ( parent==root ) return clonedParent; next = parent.getPreviousSibling(); parent = parent.getParentNode(); Node clonedGrandParent = traverseNode( parent, false, false, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null; } /** * Traverses the "left boundary" of this range and * operates on each "boundary node" according to the * <code>how</code> parameter. It is a-priori assumed * by this method that the left boundary does * not contain the range's end container. * <p> * A "left boundary" is best visualized by thinking * of a sample tree:<pre> * * A * /|\ * / | \ * / | \ * B C D * /|\ /|\ * E F G H I J * </pre> * Imagine first a range that begins between the * "E" and "F" nodes and ends between the * "I" and "J" nodes. The start container is * "B" and the end container is "D". Given this setup, * the following applies: * <p> * Partially Selected Nodes: B, D<br> * Fully Selected Nodes: F, G, C, H, I * <p> * The "left boundary" is the highest subtree node * that contains the starting container. The root of * this subtree is always partially selected. * <p> * In this example, the nodes that are traversed * as "left boundary" nodes are: F, G, and B. * * @param root The node that is the root of the "left boundary" subtree. * * @param how Specifies what type of traversal is being * requested (extract, clone, or delete). * Legal values for this argument are: * * <ol> * <li><code>EXTRACT_CONTENTS</code> - will produce * a node containing the boundaries content. * Partially selected nodes are copied, but fully * selected nodes are moved. * * <li><code>CLONE_CONTENTS</code> - will leave the * context tree of the range undisturbed, but will * produced cloned content. * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes within the boundary. * </ol> * * @return Returns a node that is the result of visiting nodes. * If the traversal operation is * <code>DELETE_CONTENTS</code> the return value is null. */ private Node traverseLeftBoundary( Node root, int how ) { Node next = getSelectedNode( getStartContainer(), getStartOffset() ); boolean isFullySelected = ( next!=getStartContainer() ); if ( next==root ) return traverseNode( next, isFullySelected, true, how ); Node parent = next.getParentNode(); Node clonedParent = traverseNode( parent, false, true, how ); while( parent!=null ) { while( next!=null ) { Node nextSibling = next.getNextSibling(); Node clonedChild = traverseNode( next, isFullySelected, true, how ); if ( how!=DELETE_CONTENTS ) clonedParent.appendChild(clonedChild); isFullySelected = true; next = nextSibling; } if ( parent==root ) return clonedParent; next = parent.getNextSibling(); parent = parent.getParentNode(); Node clonedGrandParent = traverseNode( parent, false, true, how ); if ( how!=DELETE_CONTENTS ) clonedGrandParent.appendChild( clonedParent ); clonedParent = clonedGrandParent; } // should never occur return null; } /** * Utility method for traversing a single node. * Does not properly handle a text node containing both the * start and end offsets. Such nodes should * have been previously detected and been routed to traverseTextNode. * * @param n The node to be traversed. * * @param isFullySelected * Set to true if the node is fully selected. Should be * false otherwise. * Note that although the DOM 2 specification says that a * text node that is boththe start and end container is not * selected, we treat it here as if it were partially * selected. * * @param isLeft Is true if we are traversing the node as part of navigating * the "left boundary" of the range. If this value is false, * it implies we are navigating the "right boundary" of the * range. * * @param how Specifies what type of traversal is being * requested (extract, clone, or delete). * Legal values for this argument are: * * <ol> * <li><code>EXTRACT_CONTENTS</code> - will simply * return the original node. * * <li><code>CLONE_CONTENTS</code> - will leave the * context tree of the range undisturbed, but will * return a cloned node. * * <li><code>DELETE_CONTENTS</code> - will delete the * node from it's parent, but will return null. * </ol> * * @return Returns a node that is the result of visiting the node. * If the traversal operation is * <code>DELETE_CONTENTS</code> the return value is null. */ private Node traverseNode( Node n, boolean isFullySelected, boolean isLeft, int how ) { if ( isFullySelected ) return traverseFullySelected( n, how ); if ( n.getNodeType()==Node.TEXT_NODE ) return traverseTextNode( n, isLeft, how ); return traversePartiallySelected( n, how ); } /** * Utility method for traversing a single node when * we know a-priori that the node if fully * selected. * * @param n The node to be traversed. * * @param how Specifies what type of traversal is being * requested (extract, clone, or delete). * Legal values for this argument are: * * <ol> * <li><code>EXTRACT_CONTENTS</code> - will simply * return the original node. * * <li><code>CLONE_CONTENTS</code> - will leave the * context tree of the range undisturbed, but will * return a cloned node. * * <li><code>DELETE_CONTENTS</code> - will delete the * node from it's parent, but will return null. * </ol> * * @return Returns a node that is the result of visiting the node. * If the traversal operation is * <code>DELETE_CONTENTS</code> the return value is null. */ private Node traverseFullySelected( Node n, int how ) { switch( how ) { case CLONE_CONTENTS: return n.cloneNode( true ); case EXTRACT_CONTENTS: if ( n.getNodeType()==Node.DOCUMENT_TYPE_NODE ) { // TBD: This should be a HIERARCHY_REQUEST_ERR throw new RangeExceptionImpl( RangeException.INVALID_NODE_TYPE_ERR, DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_NODE_TYPE_ERR", null)); } return n; case DELETE_CONTENTS: n.getParentNode().removeChild(n); return null; } return null; } /** * Utility method for traversing a single node when * we know a-priori that the node if partially * selected and is not a text node. * * @param n The node to be traversed. * * @param how Specifies what type of traversal is being * requested (extract, clone, or delete). * Legal values for this argument are: * * <ol> * <li><code>EXTRACT_CONTENTS</code> - will simply * return the original node. * * <li><code>CLONE_CONTENTS</code> - will leave the * context tree of the range undisturbed, but will * return a cloned node. * * <li><code>DELETE_CONTENTS</code> - will delete the * node from it's parent, but will return null. * </ol> * * @return Returns a node that is the result of visiting the node. * If the traversal operation is * <code>DELETE_CONTENTS</code> the return value is null. */ private Node traversePartiallySelected( Node n, int how ) { switch( how ) { case DELETE_CONTENTS: return null; case CLONE_CONTENTS: case EXTRACT_CONTENTS: return n.cloneNode( false ); } return null; } /** * Utility method for traversing a text node that we know * a-priori to be on a left or right boundary of the range. * This method does not properly handle text nodes that contain * both the start and end points of the range. * * @param n The node to be traversed. * * @param isLeft Is true if we are traversing the node as part of navigating * the "left boundary" of the range. If this value is false, * it implies we are navigating the "right boundary" of the *
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?