package votorola.s.gwt.scene.vote; // Copyright 2011, 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.core.client.*; import com.google.gwt.dom.client.*; import com.google.web.bindery.event.shared.HandlerRegistration; import com.google.gwt.view.client.*; import org.vectomatic.dom.svg.*; import votorola.a.count.gwt.*; import votorola.g.hold.*; import votorola.g.web.gwt.event.*; import votorola.g.web.gwt.svg.*; import static votorola.a.count.CountNode.DART_SECTOR_MAX; /** A circular view of peer nodes in votespace, ordered clockwise by dart sector. */ abstract class Circle
> extends SVGParaNest
{ /** Constructs a Circle. * * @see #inCircle() * @see #level() */ Circle( Circle> _inCircle, int _level, VotespaceV _votespaceV ) { inCircle = _inCircle; level = _level; votespaceV = _votespaceV; svgView = votespaceV.document().createSVGGElement(); svgView.addClassNameBaseVal( "circle" ); registerPainter = new RegisterPainter(); } // ------------------------------------------------------------------------------------ /** The current candidate view for all nodes of this circle, or null if there is none. */ abstract NodeV candidateV(); /** The number of count node views, or the maximum number of peer nodes that can be * shown in this circle. */ static int capacity() { return DART_SECTOR_MAX; } /** Returns the node view at the specified dart sector offset. * * @param offset the dart sector offset, which is zero based. * @throws ArrayIndexOutOfBoundsException if the offset is not less than the * capacity of this circle. * * @see #setCountNodeV(NodeV,int) */ final NodeV nodeV( final int offset ) { return nodeV[offset]; } private final NodeV[] nodeV = new NodeV[DART_SECTOR_MAX]; /** Sets a node view. * * @see #nodeV(int) */ final void setCountNodeV( final NodeV v, final int offset ) { nodeV[offset] = v; } /** Answers whether the SVG component is nominally visible. Returns false if the * display style is "none", true otherwise. * * @see #svgView() * @see #setVisible(boolean) */ final boolean isVisible() { return !"none".equals( svgView().getStyle().getDisplay() ); } /** Sets the visibility of the SVG component. * * @see #isVisible() */ final void setVisible( final boolean toBe ) { final Style style = svgView.getStyle(); if( toBe ) style.clearDisplay(); else style.setDisplay( Style.Display.NONE ); } /** The circle at the next level inward, or null if there is none. */ final Circle> inCircle() { return inCircle; } private final Circle> inCircle; /** The periperal level of this circle, where zero is the center circle. */ final int level() { return level; } private final int level; /** The volume of votes below which a node is to be shown as a "mosquito". * * @see NodeV#isMosquito() * @see #setMosquitoBar(long) */ final long mosquitoBar() { return mosquitoBar; } private long mosquitoBar; /** Sets the mosquito bar. * * @see #mosquitoBar() */ final void setMosquitoBar( long _mosquitoBar ) { mosquitoBar = _mosquitoBar; } /** The radius of clear space surrounding each count node of this circle. The * standoff is generally free of voteflow radials and other graphics. */ abstract float nodularStandOff(); /** Returns the circle at the next level outward, creating a new circle if necessary. */ final VoterCircle outCircle() { if( outCircle == null ) outCircle = new VoterCircle( Circle.this, level + 1, votespaceV ); return outCircle; } private VoterCircle outCircle; /** The register painter for this circle. */ RegisterPainter registerPainter() { return registerPainter; } private final RegisterPainter registerPainter; /** The scene view of which this view is a component. */ final VotespaceV votespaceV() { return votespaceV; } private final VotespaceV votespaceV; // - S V G - W r a p p e r ---------------------------------------------------------- public final OMSVGGElement svgView() { return svgView; } private final OMSVGGElement svgView; // ==================================================================================== /** A painter of the superaccount register views in each node of the circle. */ final class RegisterPainter implements Scheduler.ScheduledCommand, SelectionChangeEvent.Handler { RegisterPainter() { votespaceV.spool().add( new Hold() { final HandlerRegistration hR = votespaceV.model().addSelectionChangeHandler( RegisterPainter.this ); public void release() { hR.removeHandler(); } }); } private final CoalescingSchedulerS cScheduler = new CoalescingSchedulerS( CoalescingSchedulerS.FINALLY, RegisterPainter.this ); public void execute() { if( !isVisible() ) return; final SacJS sac = votespaceV.model().getSac(); if( sac == null ) return; // register view invisible, no need to repaint final CountingMethodJS.SwitchMnemonic mCM = sac.countingMethodMnemonic(); if( mCM == CountingMethodJS.SwitchMnemonic.nul ) return; // " final String accountName = sac.accountName(); for( int n = 0, nN = capacity(); n < nN; ++n ) { final NodeV v = nodeV( n ); v.repaintRegister( mCM, accountName ); } } public void onSelectionChange( SelectionChangeEvent _e ) { repaintLater(); } /** Schedules a repaint. */ void repaintLater() { cScheduler.schedule(); } } }