package votorola.s.gwt.wic; // Copyright 2012-2013, Michael Allan. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola 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 Votorola Software. THE VOTOROLA 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 VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE. import com.google.gwt.dom.client.*; import org.vectomatic.dom.svg.*; import votorola.g.web.gwt.*; import votorola.g.web.gwt.event.*; import votorola.g.web.gwt.svg.*; import votorola.s.gwt.stage.vote.*; /** A component of the bridge/stage {@linkplain DIn connector overlay} that shows the * position in the vote track of the other (non-anchor) drafter of the difference * pair.
  *
  *    - - ---+-----+---+----------+---+----------------+---+
  *            \     \   \          \   \                \   \
  *             +     +   +          +   +                +   +  vote track
  *            /     /   /          /   /                /   /
  *    - - ---+-----+---+----------+---+----------------+---+
  *
  *                                 p0 +                  +   -
  *                                    |                  |   | depth
  *                                    +------------------+   -
  *
  *                                    |----- length -----|
*/ final class AlterBracket extends OMSVGPathElement { // A simple underline would be preferable if the eye could easily resolve it. But it // gets lost in the extreme contrast at the bottom edge of the stage. /** Partially creates an AlterBracket, which an initial call to {@linkplain #repaint() * repaint} will finish. Create at most one for the entire life of the document as * currently it does not unregister its listeners or otherwise clean up after itself. */ AlterBracket( final NodeV.Box nodeBox, NodeV _nodeV, AlterLine _alterLine ) { nodeV = _nodeV; alterLine = _alterLine; addClassNameBaseVal( "AlterBracket" ); final OMSVGPathSegList sL = getPathSegList(); /*0*/sL.appendItem( createSVGPathSegMovetoAbs( 0,0 )); /*1*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 )); /*2*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 )); /*3*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 )); new Painter( nodeBox ); } private static AlterBracket instance; { if( instance != null ) throw new IllegalStateException(); instance = AlterBracket.this; } // ------------------------------------------------------------------------------------ private final Element bridgeTopE = NodeX.nextElement( Document.get().getElementById("stageTopHolder"), /*name, any*/null, /*deeply*/false ); // element marking top edge of overall bridge content, just below stage /** The vertical depth of the drawing as currently drawn in the SVG viewport. */ float depth() { final OMSVGPathSegLinetoRel seg = (OMSVGPathSegLinetoRel)getPathSegList().getItem( 1 ); return seg.getY(); } /** The horizontal length of the drawing as currently drawn in the SVG viewport. */ float length() { final OMSVGPathSegLinetoRel seg = (OMSVGPathSegLinetoRel)getPathSegList().getItem( 2 ); return seg.getX(); } /** The point at the top left of the drawing as currently drawn in the SVG viewport. */ OMSVGPathSegMovetoAbs p0() { return (OMSVGPathSegMovetoAbs)getPathSegList().getItem( 0 ); } /** Redraws this bracket and calls AlterLine.{@linkplain * AlterLine#repaint(AlterBracket) repaint}, or does nothing if the parent tie is * invisible. */ void repaint() { if( !getParentNode().isVisible() ) return; final OMSVGPathSegList sL = getPathSegList(); final float protrusion = nodeV.protrusion(); final int protrudedLength = (int)( nodeV.length() + protrusion ); // rounds zeroward // protrusion // / // |---- length ----|-| | // | // - - ---+-----+---+----------+---+----------------+---+ | // \ \ \ \ \ \ \ | // + + + + + nodeV + + | stageTopHolder // / / / / / / / | // - - ---+-----+---+----------+---+----------------+---+ -- // gap | | // - 0 + + 3 | bridgeTopE // depth | | | | // - 1 +------------------+ 2 | final int gap = (int)Math.ceil( protrusion / 2 ); PathSeg.movetoAbs( sL, 0, /*x*/nodeV.getViewportElement().getElement().getParentElement().getAbsoluteLeft() + nodeV.p0().getX(), /* measure from parent (div) of viewport (svg) to avoid SVG_STROKE_BUF distortion owing to path.ArrowSegment stroke */ /*y*/bridgeTopE.getAbsoluteTop() + gap ); final int depth = (int)protrusion; PathSeg.lineToRel( sL, 1, /*x*/0, /*y*/depth ); PathSeg.lineToRel( sL, 2, /*x*/protrudedLength, /*y*/0 ); PathSeg.lineToRel( sL, 3, /*x*/0, /*y*/-depth ); alterLine.repaint( AlterBracket.this ); } // - O M - N o d e ------------------------------------------------------------------- public @Override AlterTie getParentNode() { return (AlterTie)super.getParentNode(); } //// P r i v a t e /////////////////////////////////////////////////////////////////////// private final AlterLine alterLine; private final NodeV nodeV; // ==================================================================================== private final class Painter implements ChangeHandler { Painter( final NodeV.Box nodeBox ) { GWTX.i().bus().addHandlerToSource( Change.TYPE, /*source*/nodeBox.painter(), Painter.this ); // no need to unregister, registry does not outlive this listener } public final void onChange( Change _e ) { repaint(); } } }