rangeimpl.java
来自「JAVA的一些源码 JAVA2 STANDARD EDITION DEVELO」· Java 代码 · 共 1,767 行 · 第 1/5 页
JAVA
1,767 行
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 ) { setStartAfter( startAncestor ); 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, and we also know that neither the start * nor end container is an ancestor of the other. * This method is invoked by * the generic <code>traverse</code> method. * * @param startAncestor * Given a common ancestor of the start and end containers, * this parameter is the ancestor (or self) of the start * container that is a direct child of the common ancestor. * * @param endAncestor * Given a common ancestor of the start and end containers, * this parameter is the ancestor (or self) of the end * container that is a direct child of the common ancestor. * * @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 traverseCommonAncestors( Node startAncestor, Node endAncestor, int how ) { DocumentFragment frag = null; if ( how!=DELETE_CONTENTS) frag = fDocument.createDocumentFragment(); Node n = traverseLeftBoundary( startAncestor, how ); if ( frag!=null ) frag.appendChild( n ); Node commonParent = startAncestor.getParentNode(); int startOffset = indexOf( startAncestor, commonParent ); int endOffset = indexOf( endAncestor, commonParent ); ++startOffset; int cnt = endOffset - startOffset; Node sibling = startAncestor.getNextSibling(); while( cnt > 0 ) { Node nextSibling = sibling.getNextSibling(); n = traverseFullySelected( sibling, how ); if ( frag!=null ) frag.appendChild( n ); sibling = nextSibling; --cnt; } n = traverseRightBoundary( endAncestor, how ); if ( frag!=null ) frag.appendChild( n ); if ( how != CLONE_CONTENTS ) { setStartAfter( startAncestor ); collapse( true ); } return frag; } /**
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?