package simtools.shapes;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import simtools.diagram.gate.Connection;
import simtools.diagram.gate.Gate;
import simtools.diagram.gate.GatedComponent;
/**
* An AbstractShape that contains gates can delegate their management to this GatesHolder
* @author zxpletran007
*
*/
public class GatesHolder implements Serializable, Cloneable, GatedComponent{
private static final long serialVersionUID = 7904506247464011058L;
/**
* The component that holds gates
*/
protected GatedComponent gateComponent;
/**
* Gates contained in the component
*/
protected List gates;
private int nbGatesOnNorthSide = 0;
private int nbGatesOnSouthSide = 0;
private int nbGatesOnEastSide = 0;
private int nbGatesOnWestSide = 0;
/**
* @param nbGatesPerSide
*/
public GatesHolder(GatedComponent gateComponent) {
this.gateComponent = gateComponent;
this.gates = new ArrayList();
}
/**
* Clone the GateHolder for the given shape
* @param newShape
* @return
*/
public GatesHolder cloneGateHolder(GatedComponent newShape){
GatesHolder res = null;
try {
res = (GatesHolder) super.clone();
res.gateComponent = newShape;
res.gates = new ArrayList();
res.nbGatesOnNorthSide = 0;
res.nbGatesOnSouthSide = 0;
res.nbGatesOnEastSide = 0;
res.nbGatesOnWestSide = 0;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return res;
}
/* (non-Javadoc)
* @see simtools.diagram.gate.GatedComponent#getGates()
*/
public List getGates(){
return gates;
}
/* (non-Javadoc)
* @see simtools.diagram.gate.GatedComponent#getGateAnchor(simtools.diagram.gate.Gate)
*/
public Point getGateAnchor(Gate gate){
Point res = null;
if (gates.contains(gate) && gateComponent instanceof Shape){
Rectangle r = gateComponent.getGateBounds();
int width = r.width -2;
int height = r.height -2;
res = new Point(r.x, r.y + height);
// Gate offset
int nbGateOnGateSide;
if (gate.getSide()== Gate.NORTH){
nbGateOnGateSide = nbGatesOnNorthSide;
} else if (gate.getSide()== Gate.EAST){
nbGateOnGateSide = nbGatesOnEastSide;
} else if (gate.getSide()== Gate.SOUTH){
nbGateOnGateSide = nbGatesOnSouthSide;
} else {
nbGateOnGateSide = nbGatesOnWestSide;
}
double offsetUnitY = height / (double)(nbGateOnGateSide + 1);
double offsetUnitX = width / (double)(nbGateOnGateSide+ 1);
int offsetY = (int)( offsetUnitY + getIndex(gate) * offsetUnitY);
int offsetX = (int)(offsetUnitX + getIndex(gate) * offsetUnitX);
if (gate.getSide() == Gate.WEST){
res.y += offsetY - height;
} else if (gate.getSide() == Gate.EAST){
res.y += offsetY -height;
res.x += width;
} else if (gate.getSide() == Gate.NORTH){
res.x += offsetX;
res.y -= height;
} else if (gate.getSide() == Gate.SOUTH){
res.x += offsetX;
}
if (gateComponent instanceof AbstractShape){
AffineTransform at = (( AbstractShape)gateComponent).getTransform();
if (at != null){
at.transform(res, res);
}
}
}
return res;
}
/**
* @param gate
* @return the gate index position on the component side, or -1 if the gate does not belong to the component
*/
private int getIndex(Gate gate){
int res = -1;
if (gates.contains(gate)) {
Gate g = null;
for(int i=0;i<gates.size() && !gate.equals(g) ;i++){
g = (Gate)gates.get(i);
if (g.getSide() == gate.getSide()){
res++;
}
}
}
return res;
}
/* (non-Javadoc)
* @see simtools.diagram.gate.GatedComponent#addGate(simtools.diagram.gate.Gate)
*/
public void addGate(Gate gate){
if (!gates.contains(gate)){
gates.add(gate);
if (gate.getSide() == Gate.NORTH){
nbGatesOnNorthSide++;
} else if (gate.getSide() == Gate.EAST){
nbGatesOnEastSide++;
} else if (gate.getSide() == Gate.SOUTH){
nbGatesOnSouthSide++;
} else if (gate.getSide() == Gate.WEST){
nbGatesOnWestSide++;
}
}
}
/* (non-Javadoc)
* @see simtools.diagram.gate.GatedComponent#removeGate(simtools.diagram.gate.Gate)
*/
public void removeGate(Gate gate){
if (!gates.contains(gate)){
gates.remove(gate);
if (gate.getSide() == Gate.NORTH){
nbGatesOnNorthSide--;
} else if (gate.getSide() == Gate.EAST){
nbGatesOnEastSide--;
} else if (gate.getSide() == Gate.SOUTH){
nbGatesOnSouthSide--;
} else if (gate.getSide() == Gate.WEST){
nbGatesOnWestSide--;
}
}
}
public void removeAllGate(){
gates.clear();
nbGatesOnNorthSide = 0;
nbGatesOnEastSide = 0;
nbGatesOnSouthSide = 0;
nbGatesOnWestSide = 0;
}
/* (non-Javadoc)
* @see simtools.diagram.gate.GatedComponent#getGateAt(int, int)
*/
public Gate getGateAt(int ox, int oy){
Gate res = null;
Point p = new Point(ox, oy);
List gates = getGates();
for(int i=0;i<gates.size() && res==null; i++){
Gate g = (Gate)gates.get(i);
if ( g.canBeHanged(p)){
res = g;
}
}
return res;
}
public void connectionAddedAt(Gate gate, Connection connection) {
// TODO Auto-generated method stub
}
public void connectionRemovedAt(Gate gate, Connection connection) {
// TODO Auto-generated method stub
}
public Rectangle getGateBounds() {
return gateComponent.getGateBounds();
}
}