//(c) Copyright 2007, Scott Vorthmann. All rights reserved. package org.vorthmann.zome.app.impl; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import org.vorthmann.ui.Controller; import org.vorthmann.ui.DefaultController; import com.vzome.core.algebra.AlgebraicVector; import com.vzome.core.editor.SymmetrySystem; import com.vzome.core.math.symmetry.Axis; import com.vzome.core.math.symmetry.Direction; import com.vzome.core.math.symmetry.OrbitSet; import com.vzome.core.math.symmetry.Symmetry; import com.vzome.core.render.Color; import com.vzome.core.render.RenderedModel.OrbitSource; import com.vzome.core.render.Shapes; import com.vzome.desktop.controller.CameraController; public class SymmetryController extends DefaultController// implements RenderedModel.OrbitSource { @Override public String getProperty( String string ) { if ( "renderingStyle" .equals( string ) ) { return this .symmetrySystem .getStyle() .getName(); } else if ( string .startsWith( "orbitColor." ) ) { String name = string .substring( "orbitColor." .length() ); Direction dir = buildOrbits .getDirection( name ); Color color = getColor( dir ); return color .toString(); } return super.getProperty( string ); } private SymmetrySystem symmetrySystem; public OrbitSet availableOrbits; public OrbitSet snapOrbits; public OrbitSet buildOrbits; public OrbitSet renderOrbits; private final CameraController.Snapper snapper; public OrbitSetController availableController; public OrbitSetController snapController; public OrbitSetController buildController; public OrbitSetController renderController; public Map<Direction, LengthController> orbitLengths = new HashMap<>(); public Symmetry getSymmetry() { return this .symmetrySystem .getSymmetry(); } public CameraController.Snapper getSnapper() { return snapper; } public SymmetryController( Controller parent, SymmetrySystem model ) { this .setNextController( parent ); this.symmetrySystem = model; Symmetry symmetry = model .getSymmetry(); availableOrbits = new OrbitSet( symmetry ); snapOrbits = new OrbitSet( symmetry ); buildOrbits = new OrbitSet( symmetry ); renderOrbits = new OrbitSet( symmetry ); snapper = new SymmetrySnapper( snapOrbits ); for (Direction dir : symmetry .getOrbitSet()) { if ( dir .isStandard() ) { availableOrbits .add( dir ); snapOrbits .add( dir ); Axis zone = dir .getAxis( 0, 0 ); if ( zone .getRotationPermutation() != null ) { buildOrbits .add( dir ); } } renderOrbits .add( dir ); orbitLengths .put( dir, new LengthController( dir ) ); } availableController = new OrbitSetController( availableOrbits, this .symmetrySystem .getOrbits(), this .symmetrySystem, false ); availableController .setNextController( this ); snapController = new OrbitSetController( snapOrbits, availableOrbits, this .symmetrySystem, false ); snapController .setNextController( this ); buildController = new OrbitSetController( buildOrbits, availableOrbits, this .symmetrySystem, true ); buildController .setNextController( this ); renderController = new OrbitSetController( renderOrbits, this .symmetrySystem .getOrbits(), this .symmetrySystem, false ); renderController .setNextController( this ); for (Direction dir : this .symmetrySystem .getOrbits()) { LengthController lengthModel = new LengthController( dir ); lengthModel .setNextController( buildController ); orbitLengths .put( dir, lengthModel ); } if ( parent .propertyIsTrue( "disable.known.directions" ) ) this .symmetrySystem .disableKnownDirection(); availableController .addPropertyListener( new PropertyChangeListener() { @Override public void propertyChange( PropertyChangeEvent event ) { if ( "orbits" .equals( event .getPropertyName() ) ) { // properties() .firePropertyChange( event ); // just forwarding } } } ); } @Override public Controller getSubController( String name ) { if ( name .equals( "availableOrbits" ) ) return availableController; if ( name .equals( "snapOrbits" ) ) return snapController; if ( name .equals( "buildOrbits" ) ) return buildController; if ( name .equals( "renderOrbits" ) ) return renderController; if ( name .startsWith( "length." ) ) { String dirName = name .substring( "length." .length() ); Direction dir = this .symmetrySystem .getOrbits() .getDirection( dirName ); return getLengthController( dir ); } return null; } @Override public String[] getCommandList( String listName ) { if ( "styles" .equals( listName ) ) { return this .symmetrySystem .getStyleNames(); } if ( listName .equals( "orbits" ) ) { String[] result = new String[ this .symmetrySystem .getOrbits() .size() ]; int i = 0; for (Direction orbit : this .symmetrySystem .getOrbits()) { result[ i ] = orbit .getName(); i++; } return result; } if ( "tool.templates" .equals( listName ) ) { return new String[]{ "icosahedral", "octahedral", "tetrahedral", "rotation", "mirror" }; } return new String[0]; } @Override public void doAction( String action, ActionEvent e ) throws Exception { if ( action .equals( "rZomeOrbits" ) || action .equals( "predefinedOrbits" ) || action .equals( "setAllDirections" ) ) { availableController .doAction( action, e ); } else if ( action .startsWith( "setStyle." ) ) { String styleName = action .substring( "setStyle." .length() ); this .symmetrySystem .setStyle( styleName ); super .doAction( action, e ); // falling through so that rendering gets adjusted } } private LengthController getLengthController( Direction dir ) { LengthController result = orbitLengths .get( dir ); if ( result == null && dir != null ) { result = new LengthController( dir ); result .setNextController( buildController ); orbitLengths .put( dir, result ); renderOrbits .add( dir ); availableOrbits .add( dir ); } return result; } public OrbitSet getOrbits() { return this .symmetrySystem .getOrbits(); } public OrbitSource getOrbitSource() { return this .symmetrySystem; } // TODO this should take over all functions of symmetry.getAxis() public Axis getZone( AlgebraicVector offset ) { return this .symmetrySystem .getAxis( offset ); } public Color getColor( Direction orbit ) { return this .symmetrySystem .getColor( orbit ); } public OrbitSet getBuildOrbits() { return this .buildOrbits; } public Shapes getRenderingStyle() { return this .symmetrySystem .getRenderingStyle(); } }