001package votorola.s.gwt.stage.vote; // Copyright 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.
002
003import org.vectomatic.dom.svg.*;
004import votorola.g.web.gwt.svg.*;
005
006import static com.google.gwt.dom.client.Style.Display.INLINE;
007
008
009/** A view of a count node that may appear in "broken" form.<pre>
010  *
011  *    +---------------------+  +-------------------+
012  *     \                     \  \                   \
013  *      \                     +  +                   \
014  *       +                   /  /                     +
015  *      /                   +  +                     /
016  *     /                     \  \                   /
017  *    +-----------------------+  +-----------------+</pre>
018  *
019  *     @see <a href='CandidateV.html#ackT'>Acknowledgement to Thomas von der Elbe</a>
020  */
021final class BreakableNodeV extends NodeV
022{
023
024
025    /** Constructs a BreakableNodeV.
026      *
027      *     @see #box()
028      *     @see #dartSector()
029      */
030    BreakableNodeV( Box _box, int _dartSector, VoteTrack _track )
031    {
032        super( _box, _dartSector, _track );
033        insertBefore( new BreakLine(), getLastChild() );
034    }
035
036
037
038   // ------------------------------------------------------------------------------------
039
040
041    /** @throws UnsupportedOperationException because you should instead use the other
042      *   repaint method.
043      */
044    @Override void repaint( float _x, float _length, float _protrusion, int _y,
045      float _halfThickness )
046    {
047        throw new UnsupportedOperationException();
048    }
049
050
051
052    /** Redraws this view according to the provided parameters.  The view never
053      * automatically initiates a repaint, but depends entirely on its MajorV ancestor for
054      * this.
055      *
056      *     @param lengthMax the maximum allowable length.  If the requested length is
057      *       greater, then the view is truncated and painted in broken form.
058      */
059    void repaint( final float x, float length, final float protrusion, final int y,
060      final float halfThickness, final float lengthMax )
061    {
062        if( length > lengthMax )
063        {
064            length = lengthMax;
065            setBroken();
066            breakLine().repaint( x, length, protrusion, y, halfThickness );
067        }
068        else clearBroken();
069        super.repaint( x, length, protrusion, y, halfThickness );
070    }
071
072
073
074//// P r i v a t e ///////////////////////////////////////////////////////////////////////
075
076
077    private BreakLine breakLine() { return (BreakLine)getFirstChild().getNextSibling(); }
078
079
080
081    /** Answers whether the view is to appear in broken form.
082      */
083    private boolean isBroken;
084
085
086        private void clearBroken()
087        {
088            if( !isBroken ) return;
089
090            breakLine().getStyle().clearDisplay(); // default to "none" as set in vote/track.css
091            isBroken = false;
092        }
093
094
095        private void setBroken()
096        {
097            if( isBroken ) return;
098
099            breakLine().getStyle().setDisplay( INLINE ); // as cycler
100            isBroken = true;
101        }
102
103
104
105   // ====================================================================================
106
107
108    private final class BreakLine extends OMSVGPathElement
109    {
110
111        BreakLine()
112        {
113            addClassNameBaseVal( "BreakLine" );
114            final OMSVGPathSegList sL = getPathSegList();
115       /*0*/sL.appendItem( createSVGPathSegMovetoAbs( 0,0 ));
116       /*1*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 ));
117       /*2*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 ));
118       /*3*/sL.appendItem( createSVGPathSegLinetoRel( 0,0 ));
119        }
120
121
122        void repaint( final float x, final float length, final float protrusion, final int y,
123          float halfThickness )
124        {
125            final OMSVGPathSegList sL = getPathSegList();
126            final int xMid = Math.round( x + length - length/4 );
127            final int halfProtrusion = Math.round( protrusion / 2 );
128            final int smallDrop = Math.round( halfThickness / 2 );
129         // final float bigDrop = /*full*/halfThickness * 2 - /*used*/smallDrop * 2;
130         /// or eqivalently:
131            final float bigDrop = 2 * (halfThickness - smallDrop);
132
133              //                     0
134              //    +---------------+  +-------------+
135              //     \               \  \             \
136              //      \               +  + 1           \
137              //       +             /  /               +
138              //      /          2  +  +               /
139              //     /               \  \             /
140              //    +-----------------+  +-----------+
141              //                        3
142
143            PathSeg.movetoAbs( sL, 0,  xMid, y );
144            PathSeg.lineToRel( sL, 1, -halfProtrusion, smallDrop );
145            PathSeg.lineToRel( sL, 2,      protrusion, smallDrop );
146            PathSeg.lineToRel( sL, 3, -halfProtrusion, bigDrop );
147        }
148
149    }
150
151
152}