//Copyright (c)2005 Holobloc Inc.
//Contributed to the OOONEIDA FBench project under the Common Public License.
//Copyright (c) 2007 University of Auckland
//Contributed to the FBench extension of the OOONEIDA Workbench project under the Common Public License
package fbench.graph;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import fbench.LibraryElementView;
import fbench.graph.popup.ContextMenu;
import fbench.graph.popup.ECCDialog;
import org.w3c.dom.Element;
/**
* A GraphEdge encsapsulating an IEC 61499 <TT>ECTransition</TT> element.
*
* @author JHC, JP
*
* @version 20070301/JP - Linked with ContextMenu and ECCDialog for adding, modifying and
* removing the selected ECTransition through GUI
* @version 20070130/JP - Drag function added
* @version 20051028/JHC
*/
public class ECTransition extends GraphEdge {
private ECTransition me;
private static GeneralPath arrow = null;
private Rectangle lblbox = new Rectangle();
private String cond = "";
private float scaleFactor = Float.parseFloat(
""+((getFontMetrics(getFont()).getHeight() + 4.0) / 100.0));
private Point currentMousePoint;
private Element elem;
private int curMouseButton;
public ECTransition() {
super();
pathx = new int[3];
pathy = new int[3];
me = this;
addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent evt){
processMousePressed(evt);
}
public void mouseClicked(MouseEvent evt){
processMouseClicked(evt);
}
});
//TODO Drag works, but sometimes, a random offset occurs. It needs to be fixed.
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent evt){
if(curMouseButton == MouseEvent.BUTTON1){
processMouseDragged(evt);
}
}
});
}
private void processMousePressed(MouseEvent evt){
if(getParent().getMousePosition() != null){
elem = getElement();
currentMousePoint = getParent().getMousePosition();
curMouseButton = evt.getButton();
}
}
private void processMouseDragged(MouseEvent evt){
Point parentMousePosition = getParent().getMousePosition();
if(parentMousePosition != null){
int xTransition = parentMousePosition.x - currentMousePoint.x;
int yTransition = parentMousePosition.y - currentMousePoint.y;
pathx[1] += xTransition;
pathy[1] += yTransition;
lblbox.x = pathx[1] - lblbox.width/2 - Math.min(getX(), pathx[1] - lblbox.width/2);
lblbox.y = pathy[1] - lblbox.height/2 - Math.min(getY(), pathy[1] - lblbox.height/2);
resizeBounds();
currentMousePoint = parentMousePosition;
elem.setAttribute("x", ""+(pathx[1] / scaleFactor));
elem.setAttribute("y", ""+(pathy[1] / scaleFactor));
setElement(elem);
repaint();
}
}
private void processMouseClicked(MouseEvent evt) {
if(isInFBench()){
if(evt.getButton() == MouseEvent.BUTTON1 && evt.getClickCount() == 2){
ECCDialog eccDialog = new ECCDialog(elem, evt);
eccDialog.create("Edit Transition");
}
else if(evt.getButton() == MouseEvent.BUTTON3){
ContextMenu contextMenu = new ContextMenu(getElement(), evt);
contextMenu.create(getElement().getNodeName());
}
}
}
private void resizeBounds(){
Rectangle r = new Rectangle();
r.x = Math.min(Math.min(pathx[0], pathx[1] - lblbox.width / 2), pathx[2]);
r.y = Math.min(Math.min(pathy[0], pathy[1] - lblbox.height / 2), pathy[2]);
r.width = Math.max(Math.max(pathx[0], pathx[1] + lblbox.width / 2), pathx[2]) ;
r.height = Math.max(Math.max(pathy[0], pathy[1] + lblbox.height / 2), pathx[2]);
setBounds(r);
}
protected Component getEndPtComponent(boolean findSource) {
String compname = getElement().getAttribute(
findSource ? "Source" : "Destination");
Component comp = GraphNode.getComponentNamed(compname, getParent());
return (comp == null) ? null : ((Container) comp).getComponent(0);
}
Color selectedColor = new Color(119, 190, 255);
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color oldcolor = g.getColor();
g.setColor(isSelected() ? selectedColor : Color.white);
g.fillRect(lblbox.x, lblbox.y, lblbox.width, lblbox.height);
g.setColor(Color.black);
double theta = Math.atan2(pathy[2] - pathy[1], pathx[2] - pathx[1]);
double dx = (pathx[1] + 2 * pathx[2]) / 3.0 - getX();
double dy = (pathy[1] + 2 * pathy[2]) / 3.0 - getY();
AffineTransform at = AffineTransform.getTranslateInstance(dx, dy);
at.rotate(theta);
((Graphics2D) g).fill(at.createTransformedShape(getArrow()));
g.drawString(cond, lblbox.x, lblbox.y
+ getFontMetrics(getFont()).getAscent());
g.setColor(oldcolor);
}
public Rectangle getPreferredBounds() {
Rectangle r = super.getPreferredBounds();
FontMetrics fm = getFontMetrics(getFont());
lblbox.height = fm.getHeight() + fm.getDescent();
lblbox.width = fm.stringWidth(cond);
int x = Math.round(getScaledAtt("x"));
pathx[1] = x;
int y = Math.round(getScaledAtt("y"));
pathy[1] = y;
x -= lblbox.width / 2;
y -= lblbox.height / 2;
r.x = Math.min(r.x, x);
r.y = Math.min(r.y, y);
lblbox.x = x - r.x;
lblbox.y = y - r.y;
r.width = Math.max(r.width, lblbox.x + lblbox.width);
r.height = Math.max(r.height, lblbox.y + lblbox.height);
return r;
}
public void setElement(Element el) {
super.setElement(el);
cond = el.getAttribute("Condition");
}
public boolean contains(int x, int y) {
return lblbox.contains(x, y) || super.contains(x, y);
}
/** Returns an arrowhead Shape with lazy initialization. */
public static final Shape getArrow() {
if (arrow == null) {
arrow = new GeneralPath();
arrow.moveTo(0, 0);
arrow.lineTo(-14, 5);
arrow.lineTo(-10, 0);
arrow.lineTo(-14, -5);
arrow.closePath();
}
return arrow;
}
}