package votorola.s.gwt.scene.axial; // Copyright 2010-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.event.logical.shared.*;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.google.gwt.user.client.*;
import votorola.s.gwt.scene.*;
import votorola.g.hold.*;
import votorola.g.lang.*;
import votorola.g.web.gwt.*;
/** A scoping model based on three orthogonal axes (x,y,z). Each axis may be set to its
* own independent range of values, such that all three ranges together specify a cubic
* sub-volume. The scoping state is exposed in the 's' scoping switch, as follows:
*
*
*
* Switch |
* Controlled state |
* Default |
*
* s |
*
* The scope control. 6 continguous numbers all padded to the same digit
* length, together representing the ranges of all three axes (x,y,z). Each
* number is translated to a decimal by adding a leading decimal. An exception
* is made for numbers beginning with the letter N, which are always translated
* as 1.0. For example "s=00NN103055NN" is taken as x in the range 0.00 to 1.00,
* y 0.10 to 0.30, and z 0.55 to 1.0. |
*
* "0N0N0N" which specifies the full range on all three axes. |
*
*
*
*
* @see Scoping
*/
public final class TriaxialScoping implements Scoping
{
// cf. DiaxialScoping
/** Constructs a TriaxialScoping.
*
* @param spool for release of internal holds. When unwound, this instance will
* release its internal holds and become disabled.
*/
public TriaxialScoping( final Spool spool )
{
spool.add( new Hold()
{
final HandlerRegistration hR = Scenes.i().sScopingSwitch().addHandler(
new ValueChangeHandler()
{
public void onValueChange( final ValueChangeEvent e )
{
rescope( e.getValue() );
GWTX.i().bus().fireEventFromSource( new ScopeChangeEvent(), TriaxialScoping.this );
}
});
public void release() { hR.removeHandler(); }
});
rescope( Scenes.i().sScopingSwitch().get() ); // init state
}
// ------------------------------------------------------------------------------------
/** The x-axis minimum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float xMin() { return xMin; }
private float xMin = 0f;
/** The x-axis maximum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float xMax() { return xMax; }
private float xMax = 1f;
/** The y-axis minimum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float yMin() { return yMin; }
private float yMin = 0f;
/** The y-axis maximum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float yMax() { return yMax; }
private float yMax = 1f;
/** The z-axis minimum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float zMin() { return zMin; }
private float zMin = 0f;
/** The z-axis maximum value, inclusive.
*
* @return a number between 0.0 and 1.0 inclusive.
*/
public float zMax() { return zMax; }
private float zMax = 1f;
// - O b j e c t ----------------------------------------------------------------------
public @Override String toString()
{
return "triaxial scope = x(" + xMin + ", " + xMax + ") y(" + yMin + ", " + yMax
+ ") z(" + zMin + ", " + zMax + ")";
}
// - S c o p i n g --------------------------------------------------------------------
public HandlerRegistration addHandler( final ScopeChangeHandler handler )
{
return GWTX.i().bus().addHandlerToSource( ScopeChangeEvent.TYPE,
/*source*/TriaxialScoping.this, handler );
}
//// P r i v a t e ///////////////////////////////////////////////////////////////////////
private void rescopeToDefault()
{
xMin = 0f; xMax = 1f;
yMin = 0f; yMax = 1f;
zMin = 0f; zMax = 1f;
}
private @Warning("init call") void rescope( final String s )
{
if( s == null )
{
rescopeToDefault();
return;
}
final int sLength = s.length();
if( sLength % 6 > 0 )
{
Window.alert( "Length of switch s not a multiple of 6: " + s );
rescopeToDefault();
return;
}
final int digitLength = sLength / 6;
final StringBuilder buf = new StringBuilder(
/*initial capacity*/DiaxialScoping.assumedNumericPrefix.length() + digitLength );
buf.append( DiaxialScoping.assumedNumericPrefix );
int digitOffset = 0;
try
{
xMin = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf ); digitOffset += digitLength;
xMax = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf ); digitOffset += digitLength;
yMin = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf ); digitOffset += digitLength;
yMax = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf ); digitOffset += digitLength;
zMin = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf ); digitOffset += digitLength;
zMax = DiaxialScoping.floatFrom( s, digitOffset, digitLength, buf );
}
catch( NumberFormatException x )
{
Window.alert( "Unable to parse switch s=" + s + ": " + x.toString() );
rescopeToDefault();
}
}
}