package es.iiia.shapegrammar.rule;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import org.eclipse.ui.views.properties.IPropertySource;
import org.w3c.dom.Element;
import es.iiia.shapegrammar.model.GeometryModel;
import es.iiia.shapegrammar.shape.ShapeModel;
public class RuleShapeModel extends GeometryModel implements PropertyChangeListener {
private boolean left;
private ShapeModel shape;
private TransformModel transform;
// Ctor
public RuleShapeModel(RuleModel rule, ShapeModel shape, boolean isLeft) {
this(rule, shape, new TransformModel(), isLeft);
}
public RuleShapeModel(RuleModel rule, ShapeModel shape,
TransformModel transform, boolean isLeft) {
this.shape = shape;
this.transform = transform;
this.left = isLeft;
this.setParent(rule);
this.addChild(shape);
this.shape.addPropertyChangeListener(this);
}
// Gs / Ss
public ShapeModel getTransformedShape() {
return this.getTransformedShape(true);
}
private ShapeModel getTransformedShape(boolean moveToScreenCenter) {
ShapeModel model = this.getCenteredShape();
// transform based on stored transformation
model.transform(this.transform.getTransform());
//System.out.println("RuleShapeModel(45): " + this.transform.getTransform());
// center model
// if (moveToScreenCenter) {
// PointModel center = ((RuleModel) this.getParent()).getCenter();
// model.translate(center.x, center.y);
// }
return model;
}
public ShapeModel getCenteredTransformedShape() {
ShapeModel model = this.getCenteredShape();
// transform based on stored transformation
model.transform(this.transform.getTransform());
return model;
}
public ShapeModel getCenteredShape() {
ShapeModel clonedShape = this.shape.clone();
// center the shape, send it to [0,0]
clonedShape.moveToCenter();
return clonedShape;
}
public ShapeModel getShape() {
return this.shape;
}
public TransformModel getTransform() {
return transform;
}
public void setTransform(TransformModel transform) {
this.transform = transform;
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, null, transform);
}
public void setTransform(AffineTransform transform) {
AffineTransform originalTransform = this.transform.getTransform();
this.transform.setTransform(transform);
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, originalTransform,
transform);
}
public void appendTransform(AffineTransform transform) {
AffineTransform originalTransform = new AffineTransform(this.transform
.getTransform());
this.transform.appendTransform(transform);
//this.transform.concatenate(transform);
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, originalTransform,
transform);
}
private AffineTransform createTransform(AffineTransform transform) {
// find center of current shape
ShapeModel transfShape = this.getTransformedShape(false);
double centerX = transfShape.getBounds().getCenterX();
double centerY = transfShape.getBounds().getCenterY();
//System.out.println("Center: " + centerX + "," + centerY);
// now recreate this transform
AffineTransform resultTransform = AffineTransform.getTranslateInstance(centerX, centerY);
resultTransform.concatenate(transform);
resultTransform.concatenate(AffineTransform.getTranslateInstance(-centerX, -centerY));
//System.out.println("Temp: " + resultTransform);
return resultTransform;
}
public void translate(double x, double y) {
this.transform.setTranslate(x, y);
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, 1, 0);
}
public void scale(double sx, double sy, double diffWidth, double diffHeight) {
// create scale transform
AffineTransform transform = AffineTransform.getScaleInstance(sx, sy);
transform.preConcatenate(AffineTransform.getTranslateInstance(diffWidth, diffHeight));
this.transform(transform);
}
public void rotate(double theta) {
this.transform(AffineTransform.getRotateInstance(theta));
}
public void transform(AffineTransform transform) {
// create scale transform
AffineTransform resultTransform = this.createTransform(transform);
// create final transform
resultTransform.concatenate(this.transform.getTransform());
// now set this transform
this.setTransform(resultTransform);
// notify listeners
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, null, transform);
}
public void transformSimple(AffineTransform transform) {
// create final transform
transform.concatenate(this.transform.getTransform());
// now set this transform
this.setTransform(transform);
// notify listeners
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, null, transform);
}
public boolean isLeft() {
return left;
}
public int getId() {
return this.shape.getId();
}
// used for bubbling events to the top
public void propertyChange(PropertyChangeEvent evt) {
this.getListeners().firePropertyChange(evt);
}
private static AffineTransform flipHorizontal = new AffineTransform(-1, 0,
0, 1, 0, 0);
private static AffineTransform flipVertical = new AffineTransform(1, 0, 0,
-1, 0, 0);
public void flipHorizontal() {
this.appendTransform(flipHorizontal);
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, null, flipHorizontal);
}
public void flipVertical() {
this.appendTransform(flipVertical);
getListeners().firePropertyChange(RuleModel.RULE_SHAPE_CHANGED, null, flipVertical);
}
@Override
public Object getAdapter(Class adapter) {
if (adapter == IPropertySource.class) {
if (propertySource == null)
propertySource = new RuleShapePropertySource(this);
return propertySource;
}
return null;
}
@Override
public GeometryModel clone() {
// TODO Auto-generated method stub
return null;
}
@Override
public Element getXml() {
// TODO Auto-generated method stub
return null;
}
@Override
public ArrayList<Point2D> getPoints() {
return null;
}
}