rangeimpl.java
来自「JAVA 所有包」· Java 代码 · 共 1,729 行 · 第 1/5 页
JAVA
1,729 行
if (isAncestorOf(node, fEndContainer)) { fEndContainer = parent; fEndOffset = indexOf( node, parent); } } } // // Utility functions. // // parameters for traverseContents(int) //REVIST: use boolean, since there are only 2 now... static final int EXTRACT_CONTENTS = 1; static final int CLONE_CONTENTS = 2; static final int DELETE_CONTENTS = 3; /** * This is the master routine invoked to visit the nodes * selected by this range. For each such node, different * actions are taken depending on the value of the * <code>how</code> argument. * * @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 document fragment containing the range's 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 sill * produced cloned content in a document fragment * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes. * </ol> * * @return Returns a document fragment containing any * copied or extracted nodes. If the <code>how</code> * parameter was <code>DELETE_CONTENTS</code>, the * return value is null. */ private DocumentFragment traverseContents( int how ) throws DOMException { if (fStartContainer == null || fEndContainer == null) { return null; // REVIST: Throw exception? } //Check for a detached range. if( fDetach) { throw new DOMException( DOMException.INVALID_STATE_ERR, DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_STATE_ERR", null)); } /* Traversal is accomplished by first determining the relationship between the endpoints of the range. For each of four significant relationships, we will delegate the traversal call to a method that can make appropriate assumptions. */ // case 1: same container if ( fStartContainer == fEndContainer ) return traverseSameContainer( how ); // case 2: Child C of start container is ancestor of end container // This can be quickly tested by walking the parent chain of // end container int endContainerDepth = 0; for ( Node c = fEndContainer, p = c.getParentNode(); p != null; c = p, p = p.getParentNode()) { if (p == fStartContainer) return traverseCommonStartContainer( c, how ); ++endContainerDepth; } // case 3: Child C of container B is ancestor of A // This can be quickly tested by walking the parent chain of A int startContainerDepth = 0; for ( Node c = fStartContainer, p = c.getParentNode(); p != null; c = p, p = p.getParentNode()) { if (p == fEndContainer) return traverseCommonEndContainer( c, how ); ++startContainerDepth; } // case 4: There is a common ancestor container. Find the // ancestor siblings that are children of that container. int depthDiff = startContainerDepth - endContainerDepth; Node startNode = fStartContainer; while (depthDiff > 0) { startNode = startNode.getParentNode(); depthDiff--; } Node endNode = fEndContainer; while (depthDiff < 0) { endNode = endNode.getParentNode(); depthDiff++; } // ascend the ancestor hierarchy until we have a common parent. for( Node sp = startNode.getParentNode(), ep = endNode.getParentNode(); sp!=ep; sp = sp.getParentNode(), ep = ep.getParentNode() ) { startNode = sp; endNode = ep; } return traverseCommonAncestors( startNode, endNode, how ); } /** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are the same. * This method is invoked by the generic <code>traverse</code> * method. * * @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 document fragment containing the range's 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 sill * produced cloned content in a document fragment * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes. * </ol> * * @return Returns a document fragment containing any * copied or extracted nodes. If the <code>how</code> * parameter was <code>DELETE_CONTENTS</code>, the * return value is null. */ private DocumentFragment traverseSameContainer( int how ) { DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); // If selection is empty, just return the fragment if ( fStartOffset==fEndOffset ) return frag; // Text node needs special case handling if ( fStartContainer.getNodeType()==Node.TEXT_NODE ) { // get the substring String s = fStartContainer.getNodeValue(); String sub = s.substring( fStartOffset, fEndOffset ); // set the original text node to its new value if ( how != CLONE_CONTENTS ) { ((TextImpl)fStartContainer).deleteData(fStartOffset, fEndOffset-fStartOffset) ; // Nothing is partially selected, so collapse to start point collapse( true ); } if ( how==DELETE_CONTENTS) return null; frag.appendChild( fDocument.createTextNode(sub) ); return frag; } // Copy nodes between the start/end offsets. Node n = getSelectedNode( fStartContainer, fStartOffset ); int cnt = fEndOffset - fStartOffset; while( cnt > 0 ) { Node sibling = n.getNextSibling(); Node xferNode = traverseFullySelected( n, how ); if ( frag!=null ) frag.appendChild( xferNode ); --cnt; n = sibling; } // Nothing is partially selected, so collapse to start point if ( how != CLONE_CONTENTS ) collapse( true ); return frag; } /** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are not the * same, but the start container is an ancestor of the * end container. This method is invoked by the generic * <code>traverse</code> method. * * @param endAncestor * The ancestor of the end container that is a direct child * of the start container. * * @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 document fragment containing the range's 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 sill * produced cloned content in a document fragment * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes. * </ol> * * @return Returns a document fragment containing any * copied or extracted nodes. If the <code>how</code> * parameter was <code>DELETE_CONTENTS</code>, the * return value is null. */ private DocumentFragment traverseCommonStartContainer( Node endAncestor, int how ) { DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); Node n = traverseRightBoundary( endAncestor, how ); if ( frag!=null ) frag.appendChild( n ); int endIdx = indexOf( endAncestor, fStartContainer ); int cnt = endIdx - fStartOffset; if ( cnt <=0 ) { // Collapse to just before the endAncestor, which // is partially selected. if ( how != CLONE_CONTENTS ) { setEndBefore( endAncestor ); collapse( false ); } return frag; } n = endAncestor.getPreviousSibling(); while( cnt > 0 ) { Node sibling = n.getPreviousSibling(); Node xferNode = traverseFullySelected( n, how ); if ( frag!=null ) frag.insertBefore( xferNode, frag.getFirstChild() ); --cnt; n = sibling; } // Collapse to just before the endAncestor, which // is partially selected. if ( how != CLONE_CONTENTS ) { setEndBefore( endAncestor ); collapse( false ); } return frag; } /** * Visits the nodes selected by this range when we know * a-priori that the start and end containers are not the * same, but the end container is an ancestor of the * start container. This method is invoked by the generic * <code>traverse</code> method. * * @param startAncestor * The ancestor of the start container that is a direct * child of the end container. * * @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 document fragment containing the range's 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 sill * produced cloned content in a document fragment * * <li><code>DELETE_CONTENTS</code> - will delete from * the context tree of the range, all fully selected * nodes. * </ol> * * @return Returns a document fragment containing any * copied or extracted nodes. If the <code>how</code> * parameter was <code>DELETE_CONTENTS</code>, the * return value is null. */ private DocumentFragment traverseCommonEndContainer( Node startAncestor, int how ) { DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); Node n = traverseLeftBoundary( startAncestor, how ); if ( frag!=null ) frag.appendChild( n ); int startIdx = indexOf( startAncestor, fEndContainer ); ++startIdx; // Because we already traversed it.... int cnt = fEndOffset - startIdx; n = startAncestor.getNextSibling(); while( cnt > 0 ) { Node sibling = n.getNextSibling(); Node xferNode = traverseFullySelected( n, how ); if ( frag!=null ) frag.appendChild( xferNode ); --cnt; n = sibling; } if ( how != CLONE_CONTENTS )
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?