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 + -
显示快捷键?