package org.openlca.app.results.analysis.sankey.model;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.NodeEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.swt.graphics.Font;
import org.openlca.app.db.Cache;
import org.openlca.app.results.analysis.sankey.layout.LayoutPolicy;
import org.openlca.app.results.analysis.sankey.layout.XYLayoutCommand;
import org.openlca.core.database.EntityCache;
import org.openlca.core.model.descriptors.ProcessDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Objects;
public class ProcessEditPart extends AbstractGraphicalEditPart implements
NodeEditPart, PropertyChangeListener {
private EntityCache cache = Cache.getEntityCache();
@Override
public void activate() {
super.activate();
((Node) getModel()).addPropertyChangeListener(this);
}
@Override
protected void createEditPolicies() {
installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutPolicy());
}
@Override
protected IFigure createFigure() {
ProcessNode process = getModel();
ProcessFigure figure = new ProcessFigure(process);
figure.addPropertyChangeListener(this);
return figure;
}
@Override
public ProcessNode getModel() {
return (ProcessNode) super.getModel();
}
@Override
protected List<ConnectionLink> getModelSourceConnections() {
List<ConnectionLink> sourceConnections = new ArrayList<>();
ProcessNode thisNode = getModel();
for (ConnectionLink link : thisNode.links) {
if (link.getSourceNode().equals(thisNode))
sourceConnections.add(link);
}
return sourceConnections;
}
@Override
protected List<ConnectionLink> getModelTargetConnections() {
List<ConnectionLink> targetConnections = new ArrayList<>();
for (ConnectionLink link : getModel().links) {
if (link.getTargetNode().equals(getModel())) {
targetConnections.add(link);
}
}
return targetConnections;
}
@Override
public void deactivate() {
IFigure figure = getFigure();
if (figure instanceof ProcessFigure) {
ProcessFigure pFigure = (ProcessFigure) figure;
Font boldFont = pFigure.getBoldFont();
if (boldFont != null && !boldFont.isDisposed())
boldFont.dispose();
}
super.deactivate();
((Node) getModel()).removePropertyChangeListener(this);
}
@Override
public Command getCommand(Request request) {
Command requested = null;
if (request instanceof ChangeBoundsRequest) {
ChangeBoundsRequest req = (ChangeBoundsRequest) request;
if (req.getSizeDelta().height == 0 && req.getSizeDelta().width == 0) {
Command commandChain = null;
for (Object o : req.getEditParts()) {
if (o instanceof ProcessEditPart) {
ProcessEditPart part = (ProcessEditPart) o;
XYLayoutCommand command = new XYLayoutCommand();
command.setProcessNode(part.getModel());
Rectangle bounds = (part.getModel()).figure
.getBounds().getCopy();
part.getModel().figure.translateToAbsolute(bounds);
Rectangle moveResize = new Rectangle(
req.getMoveDelta(), req.getSizeDelta());
bounds.resize(moveResize.getSize());
bounds.translate(moveResize.getLocation());
part.getModel().figure.translateToRelative(bounds);
command.setConstraint(bounds);
if (commandChain == null) {
commandChain = command;
} else {
commandChain = commandChain.chain(command);
}
}
}
requested = commandChain;
}
}
return requested;
}
@Override
public List<Node> getModelChildren() {
return getModel().getChildrenArray();
}
@Override
public ConnectionAnchor getSourceConnectionAnchor(
ConnectionEditPart connection) {
ConnectionLink link = (ConnectionLink) connection.getModel();
return new ProcessLinkAnchor(link, false);
}
@Override
public ConnectionAnchor getSourceConnectionAnchor(Request arg0) {
return null;
}
@Override
public ConnectionAnchor getTargetConnectionAnchor(
ConnectionEditPart connection) {
ConnectionLink link = (ConnectionLink) connection.getModel();
return new ProcessLinkAnchor(link, true);
}
@Override
public ConnectionAnchor getTargetConnectionAnchor(Request arg0) {
return null;
}
@Override
public boolean isSelectable() {
return true;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ProcessNode.CONNECTION))
refreshConnections(evt);
else {
GraphicalEditPart part = (GraphicalEditPart) getViewer()
.getContents();
IFigure figure = part.getFigure();
figure.revalidate();
}
}
private void refreshConnections(PropertyChangeEvent evt) {
Object linkObj = evt.getOldValue() != null ? evt.getOldValue() : evt
.getNewValue();
if (!(linkObj instanceof ConnectionLink))
return;
ConnectionLink link = (ConnectionLink) linkObj;
ProcessDescriptor thisProcess = getModel().process;
ProcessDescriptor provider = cache.get(ProcessDescriptor.class, link
.getProcessLink().providerId);
ProcessDescriptor recipient = cache.get(ProcessDescriptor.class, link
.getProcessLink().processId);
boolean isLoop = Objects.equal(provider, recipient);
try {
if (thisProcess.equals(provider)) {
refreshSourceConnections();
if (isLoop)
refreshTargetConnections();
} else {
refreshTargetConnections();
}
} catch (Exception e) {
Logger log = LoggerFactory.getLogger(getClass());
log.error("Failed to refresh connections for process "
+ thisProcess, e);
}
}
}