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}