package com.isencia.passerelle.workbench.model.editor.ui.editpart;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.Clickable;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CommandStackListener;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ptolemy.actor.Actor;
import ptolemy.actor.TypedIOPort;
import ptolemy.data.BooleanToken;
import ptolemy.data.Token;
import ptolemy.data.expr.Parameter;
import ptolemy.kernel.Entity;
import ptolemy.kernel.Port;
import ptolemy.kernel.util.Attribute;
import com.isencia.passerelle.core.ControlPort;
import com.isencia.passerelle.core.ErrorPort;
import com.isencia.passerelle.workbench.model.editor.ui.Activator;
import com.isencia.passerelle.workbench.model.editor.ui.editpolicy.ActorEditPolicy;
import com.isencia.passerelle.workbench.model.editor.ui.editpolicy.ComponentNodeDeletePolicy;
import com.isencia.passerelle.workbench.model.editor.ui.figure.ActorFigure;
import com.isencia.passerelle.workbench.model.editor.ui.figure.PortFigure;
import com.isencia.passerelle.workbench.model.editor.ui.figure.RectangularActorFigure;
import com.isencia.passerelle.workbench.model.editor.ui.palette.PaletteBuilder;
import com.isencia.passerelle.workbench.model.ui.command.AttributeCommand;
public class ActorEditPart extends AbstractNodeEditPart implements IActorNodeEditPart {
private static final String TRIGGER_PORT_NAME = "trigger";
private final static Logger logger = LoggerFactory.getLogger(ActorEditPart.class);
public final static ImageDescriptor IMAGE_DESCRIPTOR_PROPERTIES = Activator.getImageDescriptor("icons/input.gif");
public final static Color COLOR_ERROR_PORT = new Color(null, 192, 20, 20);
public final static Color COLOR_CONTROL_PORT = new Color(null, 50, 50, 255);
public final static Color COLOR_TRIGGER_PORT = new Color(null, 255, 225, 20);
public final static Color COLOR_SOURCE_ACTOR = new Color(null, 138, 226, 52);
public final static Color COLOR_SINK_ACTOR = new Color(null,252,175,62);
public final static ImageDescriptor IMAGE_COMMENT = Activator.getImageDescriptor("icons/comment.png");
public final static ImageDescriptor IMAGE_DESCRIPTOR_ACTOR = Activator.getImageDescriptor("icons/actor.gif");
public final static ImageDescriptor IMAGE_DESCRIPTOR_PARAMETER = Activator.getImageDescriptor("icons/parameter.gif");
public final static ImageDescriptor IMAGE_DESCRIPTOR_INPUTPORT = Activator.getImageDescriptor("icons/input.gif");
public final static ImageDescriptor IMAGE_DESCRIPTOR_OUTPUTPORT = Activator.getImageDescriptor("icons/output.gif");
public Logger getLogger() {
return logger;
}
protected void createEditPolicies() {
if (getParent() instanceof DiagramEditPart) {
installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new ActorEditPolicy(((DiagramEditPart) getParent()).getMultiPageEditorPart(), this));
}
installEditPolicy(EditPolicy.COMPONENT_ROLE, new ComponentNodeDeletePolicy(getDiagram(), ((DiagramEditPart) getParent()).getMultiPageEditorPart()));
}
/**
* Returns a newly created Figure to represent this.
*
* @return Figure of this EditPart
*/
protected IFigure createFigure() {
Actor actorModel = getActor();
// ImageFigure drillDownImageFigure = new ImageFigure(
// createImage(IMAGE_DESCRIPTOR_ACTOR));
// drillDownImageFigure.setAlignment(PositionConstants.SOUTH);
// drillDownImageFigure.setBorder(new MarginBorder(0, 0, 5, 0));
ImageDescriptor imageDescriptor = PaletteBuilder.getInstance().getIcon(actorModel.getClass());
if (imageDescriptor == null) {
imageDescriptor = IMAGE_DESCRIPTOR_ACTOR;
}
ActorFigure actorFigure = getActorFigure(actorModel.getDisplayName(), createImage(imageDescriptor), new Clickable[] {});
boolean isSource = true;
List<TypedIOPort> inputPortList = actorModel.inputPortList();
if (inputPortList != null && inputPortList.size()>0) {
for (TypedIOPort inputPort : inputPortList) {
PortFigure portFigure = actorFigure.addInput(inputPort.getName(), inputPort.getDisplayName());
if (inputPort instanceof ErrorPort) {
portFigure.setFillColor(COLOR_ERROR_PORT);
} else if (inputPort instanceof ControlPort) {
portFigure.setFillColor(COLOR_CONTROL_PORT);
} else if (TRIGGER_PORT_NAME.equals(inputPort.getName())) {
portFigure.setFillColor(COLOR_TRIGGER_PORT);
} else {
// we've got a normal input port, so the actor is not a source
isSource = false;
}
}
}
if(isSource) {
actorFigure.setBackgroundColor(COLOR_SOURCE_ACTOR);
}
boolean isSink = true;
List<TypedIOPort> outputPortList = actorModel.outputPortList();
if (outputPortList != null) {
for (TypedIOPort outputPort : outputPortList) {
PortFigure portFigure = actorFigure.addOutput(outputPort.getName(), outputPort.getDisplayName());
if (outputPort instanceof ErrorPort) {
portFigure.setFillColor(COLOR_ERROR_PORT);
} else if (outputPort instanceof ControlPort) {
portFigure.setFillColor(COLOR_CONTROL_PORT);
} else {
isSink = false;
}
}
}
if(isSink) {
actorFigure.setBackgroundColor(COLOR_SINK_ACTOR);
}
// Listen to break point status if there is a break point attribute.
if (actorModel instanceof Entity) {
if (isDebuggable()) {
updateBreakPoint(actorFigure);
if (getParent() instanceof DiagramEditPart) {
final DiagramEditPart dep = (DiagramEditPart) getParent();
dep.getMultiPageEditorPart().getEditor().getEditDomain().getCommandStack().addCommandStackListener(new DebugStackNotifier(dep, actorFigure));
}
}
}
return actorFigure;
}
private final class DebugStackNotifier implements CommandStackListener {
private DiagramEditPart dep;
private ActorFigure actorFigure;
public DebugStackNotifier(DiagramEditPart dep, ActorFigure actorFigure) {
this.dep = dep;
this.actorFigure = actorFigure;
}
@Override
public void commandStackChanged(EventObject event) {
CommandStack stack = (CommandStack) event.getSource();
Command last = stack.getUndoCommand();
if (!(last instanceof AttributeCommand))
return;
if (dep.getMultiPageEditorPart().isDisposed()) {
stack.removeCommandStackListener(this);
return;
}
if (actorFigure.getParent() == null) {
stack.removeCommandStackListener(this);
return;
}
updateBreakPoint(actorFigure);
}
}
private void updateBreakPoint(ActorFigure figure) {
final Entity entity = (Entity) getActor();
final Attribute att = entity.getAttribute("_break_point");
final boolean isBreak = getBooleanValue(att, false);
figure.setBreakPoint(isBreak);
}
public boolean isDebuggable() {
try {
final Entity entity = (Entity) getActor();
final Attribute att = entity.getAttribute("_break_point");
return att != null;
} catch (Throwable ne) {
return false;
}
}
private static boolean getBooleanValue(Attribute att, boolean defaultValue) {
try {
if (att == null)
return defaultValue;
if (!(att instanceof Parameter))
return defaultValue;
Token tok = ((Parameter) att).getToken();
if (!(tok instanceof BooleanToken))
return defaultValue;
return ((BooleanToken) tok).booleanValue();
} catch (Throwable ne) {
return defaultValue;
}
}
/**
* Overide to return alternative actor figures
*
* @param displayName
* @param createImage
* @param clickables
* @return
*/
protected ActorFigure getActorFigure(String displayName, Image createImage, Clickable[] clickables) {
return new RectangularActorFigure(displayName, getModel().getClass(), createImage, clickables);
}
/**
* Returns the Figure of this as a ActorFigure.
*
* @return ActorFigure of this.
*/
/**
* Returns the model of this as a Actor.
*
* @return Model of this as an Actor.
*/
public Actor getActor() {
Object model = getModel();
if (model instanceof Actor)
return (Actor) model;
return null;
}
public void setSelected(int i) {
super.setSelected(i);
refreshVisuals();
}
@Override
protected List getModelSourceConnections() {
return getModelConnections(getDiagram().getLinkHolder(), getActor(), false);
}
@Override
protected List getModelTargetConnections() {
return getModelConnections(getDiagram().getLinkHolder(), getActor(), true);
}
/**
* Returns the connection anchor for the given ConnectionEditPart's source.
*
* @return ConnectionAnchor.
*/
public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connEditPart) {
return getConnectionAnchor(connEditPart, (ActorFigure) getComponentFigure(), getActor(), false);
}
/**
* Returns the connection anchor of a source connection which is at the given point.
*
* @return ConnectionAnchor.
*/
public ConnectionAnchor getSourceConnectionAnchor(Request request) {
Point pt = new Point(((DropRequest) request).getLocation());
return getComponentFigure().getSourceConnectionAnchorAt(pt);
}
/**
* Returns the connection anchor for the given ConnectionEditPart's target.
*
* @return ConnectionAnchor.
*/
public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connEditPart) {
return getConnectionAnchor(connEditPart, (ActorFigure) getComponentFigure(), getActor(), true);
}
/**
* Returns the Output Port based on a given Anchor
*
* @return Port.
*/
public Port getSourcePort(ConnectionAnchor anchor) {
getLogger().debug("Get Source port based on anchor");
return getPort(anchor, (ActorFigure) getComponentFigure(), getActor(), true);
}
/**
* Returns the Input Port based on a given Anchor
*
* @return Port.
*/
public Port getTargetPort(ConnectionAnchor anchor) {
getLogger().debug("Get Target port based on anchor");
return getPort(anchor, (ActorFigure) getComponentFigure(), getActor(), false);
}
public static Port getPort(ConnectionAnchor anchor, ActorFigure actorFigure, Actor actor, boolean source) {
List outputPortList = null;
if (source)
outputPortList = actor.outputPortList();
else
outputPortList = actor.inputPortList();
for (Iterator iterator = outputPortList.iterator(); iterator.hasNext();) {
Port port = (Port) iterator.next();
if (port.getName() != null && port.getName().equals(actorFigure.getConnectionAnchorName(anchor)))
return port;
}
return null;
}
/**
* Returns the connection anchor of a terget connection which is at the given point.
*
* @return ConnectionAnchor.
*/
public ConnectionAnchor getTargetConnectionAnchor(Request request) {
Point pt = new Point(((DropRequest) request).getLocation());
return getComponentFigure().getTargetConnectionAnchorAt(pt);
}
/**
* Returns the name of the given connection anchor.
*
* @return The name of the ConnectionAnchor as a String.
*/
final protected String mapConnectionAnchorToTerminal(ConnectionAnchor c) {
return getComponentFigure().getConnectionAnchorName(c);
}
}