package votorola.s.gwt.stage.vote; // Copyright 2012, 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.Scheduler; import votorola.a.diff.*; import votorola.g.lang.*; import votorola.g.web.gwt.*; import votorola.g.web.gwt.event.*; import votorola.s.gwt.stage.*; import votorola.s.gwt.stage.link.*; import static votorola.s.gwt.stage.link.NominalDifferenceTargeter.NOMINAL_DIFF; /** The stager of differences for the {@linkplain DifferenceLight difference light}. * Whenever the staged actor and poll match a lighted difference, the stager sets the * {@linkplain Stage#getDifference() difference on the stage}. If the difference cannot * be staged and {@linkplain NominalDifferenceLight nominal targeting} is enabled, then * any incompatible difference on stage is cleared to allow the difference link to be set * to the nominal target. */ final class DifferenceStager implements PropertyChangeHandler { /** Constructs a DifferenceStager. */ DifferenceStager( final DifferenceLight light, final Stage stage ) { keyLight = light.hasDiffLooks()? light: null; GWTX.i().bus().addHandlerToSource( PropertyChange.TYPE, /*source*/stage, DifferenceStager.this ); // no need to unregister, registry does not outlive this listener restage( stage, stage.getActorName(), /*toClobber*/false ); } // - P r o p e r t y - C h a n g e - H a n d l e r ------------------------------------ public void onPropertyChange( final PropertyChange e ) { final String name = e.propertyName(); // if( name.equals( "difference" )) clean( (Stage)e.getSource() ); else if( name.equals( "actorName" )) { final Stage stage = (Stage)e.getSource(); final String actorName = stage.getActorName(); restage( stage, actorName, // /*toClobber*/!ObjectX.nullEquals(actorName,stage.getDefaultActorName()) ); // // allow clobber for non-default actor under assumption he/she was // // deliberately staged by user in order to light difference /////// but then cannot deselect other author to clear the inverted DiffLook1 below, /////// so allow all author de-selections to clobber, which also makes sense: /*toClobber*/true ); } else if( name.equals( "pollName" )) { final Stage stage = (Stage)e.getSource(); restage( stage, stage.getActorName(), /*toClobber*/false ); } } //// P r i v a t e /////////////////////////////////////////////////////////////////////// private final boolean isTargetingNominal = NominalDifferenceTargeter.isEnabled(); private final DifferenceLight keyLight; // or null if !hasDiffLooks private final @Warning("init call") void restage( final Stage stage, final String actorName, final boolean toClobber ) { final DiffLook dOld = stage.getDifference(); final String pollName = stage.getPollName(); if( dOld != null ) { if( LightableDifference.TYPIFIER.isInstance( dOld )) { final LightableDifference dOldL = (LightableDifference)dOld; if( dOldL.personName().equals(actorName) && dOldL.pollName().equals(pollName) ) return; // diff already staged } else if( !toClobber ) return; // diff set by another controller, do not clobber } final DiffLook dNew; dNew: if( keyLight != null ) dNew = (DiffLook)keyLight.differenceFor( actorName, pollName ); else { if( sceneName != null && sceneName.equals( actorName )) // other author of scene diff staged { final DiffLook d = stage.getDefaultDifference(); if( d != null ) { // Stage the same diff as scene, but with selectand inverted. So diff // link will simply switch selectand even if diff is old. Nominal // targeting (below) would instead link to latest diff. dNew = new DiffLook1( d.key(), /*selectand, other*/"a".equals(d.selectand())?"b":"a", /*toPersist*/true ); break dNew; } } if( isTargetingNominal ) dNew = NOMINAL_DIFF; // cannot stage, so clear instead else return; // nothing helpful to do, so do nothing } stage.setDifference( dNew ); } private final String sceneName = DifferenceLight.sceneName(); }