//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.BorderLayout;
import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import fbench.Library;
import fbench.dom.events.ElementSelectionEvent;
import fbench.graph.popup.ContextMenu;
import fbench.graph.popup.ECCDialog;
import fbench.graph.popup.FBNetworkDialog;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
/**
* A graphic element representing a Function Block, which encapsulates an
* ElementModel for an IEC 61499 <TT>FB</TT> Element.
*
* @author JHC, JP
*
* @version 20070130/JP - Added drag function
* @version 20051109/JHC - Implemented ElementSelectionEvent listener on
* contained FBType.
* @version 20051004/JHC
*/
public class FB extends GraphNode implements EventListener {
/** The internal FBType GraphNode. */
protected FBType typeNode;
protected String type;
private Element elem;
private float xPos, yPos;
private Point currentMousePoint;
private int currentMouseButton;
private float scaleFactor = Float.parseFloat(
""+((getFontMetrics(getFont()).getHeight() + 4.0) / 100.0));
private boolean isBeingRightClickDragged = false;
public FB() {
super();
setLayout(new BorderLayout());
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
processMousePressed(evt);
}
public void mouseClicked(MouseEvent evt) {
processMouseClicked(evt);
}
public void mouseReleased(MouseEvent evt) {
processMouseReleased(evt);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent evt) {
processMouseDragged(evt);
}
});
}
int parentElementIndex;
private void processMousePressed(MouseEvent mevent){
elem = getElement();
xPos = (Float.parseFloat(elem.getAttribute("x")));
yPos = (Float.parseFloat(elem.getAttribute("y")));
currentMouseButton = mevent.getButton();
currentMousePoint = mevent.getPoint();
if(getParent() != null)
((JLayeredPane) getParent()).moveToFront(this);
}
private void processMouseClicked(MouseEvent evt){
if(isInFBench()){
if(evt.getButton() == MouseEvent.BUTTON1 && evt.getClickCount() == 2){
FBNetworkDialog fbNetworkDialog = new FBNetworkDialog(elem, evt);
fbNetworkDialog.create("Edit Function Block");
}
else if(evt.getButton() == MouseEvent.BUTTON3){
ContextMenu contextMenu = new ContextMenu(getElement(), evt);
contextMenu.create(getElement().getNodeName());
}
}
}
private void processMouseDragged(MouseEvent mevent) {
if(currentMouseButton == MouseEvent.BUTTON1){
int xTransition = mevent.getX() - currentMousePoint.x;
int yTransition = mevent.getY() - currentMousePoint.y;
xPos = xPos+ xTransition / scaleFactor;
yPos = yPos+ yTransition / scaleFactor;
this.setLocation(this.getX() + xTransition,this.getY() + yTransition);
typeNode.setLocation(typeNode.getX(), typeNode.getY());
elem.setAttribute("x", ""+xPos);
elem.setAttribute("y", ""+yPos);
/**
* Update edges connected to this FB
*/
Component[] parentComponent = getParent().getComponents();
for(int i = 0; i < parentComponent.length; i++){
if(parentComponent[i].toString().contains(this.mainLabelText())){
if(parentComponent[i] instanceof GraphEdge){
GraphEdge edge = (GraphEdge)parentComponent[i];
edge.updatePath();
edge.setBounds(edge.getPreferredBounds());
}
}
}
getParent().repaint();
}
if(currentMouseButton == MouseEvent.BUTTON3){
isBeingRightClickDragged = true;
Point rightClickPoint = new Point();
rightClickPoint.setLocation(xPos*scaleFactor, yPos*scaleFactor);
}
}
private void processMouseReleased(MouseEvent evt){
System.out.println("[FB] processMouseReleased");
if(isBeingRightClickDragged){
isBeingRightClickDragged = false;
Point p = evt.getPoint();
p.translate(this.getX(), this.getY());
Component c = getParent().getComponentAt(p);
if(c != null && c instanceof FB && c != this){
FB other = (FB)c;
FBNetworkDialog fbDialog = new FBNetworkDialog((Element)elem.getParentNode(), evt);
fbDialog.setSourceFBName(getFBName());
fbDialog.setDestinationFBName(other.getFBName());
fbDialog.create("Add Connection");
}
}
}
protected void initComponents() {
super.initComponents();
add(mainLabel, BorderLayout.NORTH);
String tname = model.getType();
Document typedoc = Library.getDocument(tname + getTypeSuffix());
if (typedoc == null)
return;
type = typedoc.getDocumentElement().getAttribute("Name");
typeNode = (FBType) GraphElement.forElement(typedoc
.getDocumentElement());
typeNode.setReversed(isPlug());
((org.w3c.dom.events.EventTarget)typedoc).addEventListener(
"ElementSelectionEvent", this, false);
add(typeNode, BorderLayout.CENTER);
}
protected String getTypeSuffix() {
return ".fbt";
}
/**
* Returns <TT>true</TT>, since FB and its subclasses may have visible
* parameters.
*/
public boolean hasVisibleParameters() {
return true;
}
/**
* Returns the contained component with the given name or <TT>null</TT> if
* no component with the given name is found.
*/
public Component getComponentNamed(String compname) {
return GraphElement.getComponentNamed(compname, typeNode);
}
public boolean isSelected() {
return typeNode.isSelected();
}
public void setSelected(boolean newState) {
typeNode.setSelected(newState);
}
/**
* Returns <TT>true</TT> if this element is to be displayed as a Plug
* (inputs and outputs reversed from its type specification).
*/
public boolean isPlug() {
return false;
}
public void handleEvent(Event evt) {
if ((evt instanceof ElementSelectionEvent)
&& (((ElementSelectionEvent) evt).getSource() == typeNode))
{
ElementSelectionEvent sel = (ElementSelectionEvent)evt;
// process mouse press does:
/*
[selevt == ElementSelectionEvent]
selevt.initSelectionEvent(getElement(), this, evt,
ElementSelectionEvent.ACTIVATE);
((org.w3c.dom.events.EventTarget) getElement().getOwnerDocument())
.dispatchEvent(selevt);
*/
sel.initSelectionEvent(this.getElement(), this, ElementSelectionEvent.ACTIVATE);
//processMousePress(((ElementSelectionEvent) evt).getMouseEvent());
}
}
public String getFBType() {
return type;
}
public JLabel getMainLabel(){
return mainLabel;
}
public String getFBName() {
return mainLabel.getText();
}
}