package textbender.o.rhinohide.ranges; // Copyright 2006-2007, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Textbender Software"), to deal in the Textbender Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Textbender Software, and to permit persons to whom the Textbender Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Textbender Software. THE TEXTBENDER SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE TEXTBENDER SOFTWARE OR THE USE OR OTHER DEALINGS IN THE TEXTBENDER SOFTWARE. import netscape.javascript.JSObject; import org.w3c.dom.*; import org.w3c.dom.ranges.Range; import textbender.g.lang.ThreadSafe; import textbender.g.util.logging.LoggerX; import textbender.o.rhinohide.*; import textbender.o.rhinohide.core.*; /** A range implemented as an overlay of a JavaScript range. */ public @ThreadSafe final class RhiRange extends Rhinohide implements Range { /** Constructs a RhiRange. * * @param window global object * @param jsObject bridge to underlying JavaScript range, * per {@linkplain Rhinohide#jsObject() jsObject}() * * @return range, or null if jsObject is null * * @see RhiDocument#createRange() * @see RhiSelection#getRangeAt(int) */ public static RhiRange wrapRange( RhiWindow window, JSObject jsObject ) { if( jsObject == null ) return null; return new RhiRange( window, jsObject ); } RhiRange( RhiWindow window, JSObject jsObject ) { super( window, jsObject ); } // - O b j e c t ---------------------------------------------------------------------- public @Override String toString() { return (String)callV( "toString" ); } // implemented for both Object and Range // - R a n g e ------------------------------------------------------------------------ /** Not yet coded. * * @throws UnsupportedOperationException */ public DocumentFragment cloneContents() { throw new UnsupportedOperationException(); } public Range cloneRange() { return RhiRange.wrapRange( window, (JSObject)callV( "cloneRange" )); } public void collapse( boolean toStart ) { call( "collapse", toStart ); } public short compareBoundaryPoints( short how, Range sourceRange ) { return ((Number)callV( "compareBoundaryPoints", how, ((RhiRange)sourceRange).jsObject() )) .shortValue(); } /** Not yet coded. * * @throws UnsupportedOperationException */ public void deleteContents() { throw new UnsupportedOperationException(); } /** Not yet coded. * * @throws UnsupportedOperationException */ public void detach() { throw new UnsupportedOperationException(); } /** Not yet coded. * * @throws UnsupportedOperationException */ public DocumentFragment extractContents() { throw new UnsupportedOperationException(); } public boolean getCollapsed() { return (Boolean)getMemberV( "collapsed" ); } public Node getCommonAncestorContainer() { return RhiNode.wrapNode( window, (JSObject)getMemberV( "commonAncestorContainer" )); } public Node getEndContainer() { return RhiNode.wrapNode( window, (JSObject)getMemberV( "endContainer" )); } public int getEndOffset() { return ((Number)getMemberV( "endOffset" )).intValue(); } public void setEnd( Node refNode, int offset ) { call( "setEnd", ((RhiNode)refNode).jsObject(), offset ); // if( !refNode.isSameNode( getEndContainer() )) ensureEndCollapsed(); // because call had no effect ///// no, it's not a collapse problem in this case if( !refNode.isSameNode( getEndContainer() )) // call had no effect { if( getCollapsed() ) return; // OK assert refNode instanceof Comment : refNode.toString(); throw new IllegalStateException( "cannot set end to node: " + refNode ); // Firefox/1.5.0.8 } } public void setEndAfter( Node refNode ) { call( "setEndAfter", ((RhiNode)refNode).jsObject() ); } public void setEndBefore( Node refNode ) { call( "setEndBefore", ((RhiNode)refNode).jsObject() ); if( refNode.isSameNode( getEndContainer() )) ensureEndCollapsed(); // because call had no effect } private void ensureEndCollapsed() { if( getCollapsed() ) return; // OK LoggerX.i(getClass()).config( "correcting collapse failure, Firefox" ); // Firefox 1.5, 2 collapse( /*toStart*/true ); } public Node getStartContainer() { return RhiNode.wrapNode( window, (JSObject)getMemberV( "startContainer" )); } public int getStartOffset() { return ((Number)getMemberV( "startOffset" )).intValue(); } public void setStart( Node refNode, int offset ) { call( "setStart", ((RhiNode)refNode).jsObject(), offset ); } public void setStartAfter( Node refNode ) { call( "setStartAfter", ((RhiNode)refNode).jsObject() ); } public void setStartBefore( Node refNode ) { call( "setStartBefore", ((RhiNode)refNode).jsObject() ); } /** Not yet coded. * * @throws UnsupportedOperationException */ public void insertNode( Node newNode ) { throw new UnsupportedOperationException(); } public void selectNode( Node refNode ) { call( "selectNode", ((RhiNode)refNode).jsObject() ); } /** Not yet coded. * * @throws UnsupportedOperationException */ public void selectNodeContents( Node refNode ) { throw new UnsupportedOperationException(); } /** Not yet coded. * * @throws UnsupportedOperationException */ public void surroundContents( Node newParent ) { throw new UnsupportedOperationException(); } }