/*******************************************************************************
* Copyright (c) 2010 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* CONTRIBUTORS:
* Thomas Schuetz and Henrik Rentz-Reichert (initial contribution)
*
*******************************************************************************/
package org.eclipse.etrice.ui.structure.support;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.etrice.core.validation.ValidationUtil;
import org.eclipse.etrice.ui.structure.ImageProvider;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.IReason;
import org.eclipse.graphiti.features.IRemoveFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddConnectionContext;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ICreateConnectionContext;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.IRemoveContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.context.impl.AddConnectionContext;
import org.eclipse.graphiti.features.context.impl.RemoveContext;
import org.eclipse.graphiti.features.impl.AbstractAddFeature;
import org.eclipse.graphiti.features.impl.AbstractCreateConnectionFeature;
import org.eclipse.graphiti.features.impl.AbstractUpdateFeature;
import org.eclipse.graphiti.features.impl.DefaultRemoveFeature;
import org.eclipse.graphiti.features.impl.Reason;
import org.eclipse.graphiti.mm.GraphicsAlgorithmContainer;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.pictograms.Anchor;
import org.eclipse.graphiti.mm.pictograms.Connection;
import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.ManhattanConnection;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.PictogramsFactory;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.graphiti.services.IGaService;
import org.eclipse.graphiti.services.IPeCreateService;
import org.eclipse.graphiti.tb.DefaultToolBehaviorProvider;
import org.eclipse.graphiti.tb.IToolBehaviorProvider;
import org.eclipse.graphiti.ui.features.DefaultDeleteFeature;
import org.eclipse.graphiti.ui.features.DefaultFeatureProvider;
import org.eclipse.graphiti.util.ColorConstant;
import org.eclipse.graphiti.util.IColorConstant;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerRef;
import org.eclipse.etrice.core.room.LayerConnection;
import org.eclipse.etrice.core.room.RefSAPoint;
import org.eclipse.etrice.core.room.RelaySAPoint;
import org.eclipse.etrice.core.room.RoomFactory;
import org.eclipse.etrice.core.room.SAPoint;
import org.eclipse.etrice.core.room.SPPRef;
import org.eclipse.etrice.core.room.SPPoint;
import org.eclipse.etrice.core.room.StructureClass;
public class LayerConnectionSupport {
private static final IColorConstant LINE_COLOR = new ColorConstant(0, 0, 0);
private static final int LINE_WIDTH = 2;
class FeatureProvider extends DefaultFeatureProvider {
private class CreateFeature extends AbstractCreateConnectionFeature {
public CreateFeature(IFeatureProvider fp) {
super(fp, "LayerConnection", "create LayerConnection");
}
@Override
public String getCreateImageId() {
return ImageProvider.IMG_LAYER_CONNECTION;
}
@Override
public boolean canCreate(ICreateConnectionContext context) {
SPPRef src = getSPPRef(context.getSourceAnchor());
ActorContainerRef srcRef = getRef(context.getSourceAnchor());
SPPRef tgt = getSPPRef(context.getTargetAnchor());
ActorContainerRef tgtRef = getRef(context.getTargetAnchor());
StructureClass sc = getParent(context);
return ValidationUtil.isConnectable(src, srcRef, tgt, tgtRef, sc).isOk();
}
public boolean canStartConnection(ICreateConnectionContext context) {
SPPRef src = getSPPRef(context.getSourceAnchor());
ActorContainerRef ref = getRef(context.getSourceAnchor());
StructureClass sc = getParent(context);
return ValidationUtil.isConnectableSrc(src, ref, sc);
}
private SPPRef getSPPRef(Anchor anchor) {
if (anchor != null) {
Object obj = getBusinessObjectForPictogramElement(anchor.getParent());
if (obj instanceof SPPRef) {
return (SPPRef) obj;
}
}
return null;
}
public ActorContainerRef getRef(Anchor anchor) {
if (anchor != null) {
ContainerShape shape = (ContainerShape) anchor.getParent().eContainer();
Object bo = getBusinessObjectForPictogramElement(shape);
if (bo instanceof ActorContainerRef)
return (ActorContainerRef) bo;
}
return null;
}
public StructureClass getParent(ICreateConnectionContext context) {
ContainerShape shape = (ContainerShape) context.getSourcePictogramElement().eContainer();
Object bo = getBusinessObjectForPictogramElement(shape);
if (bo instanceof StructureClass)
return (StructureClass) bo;
shape = (ContainerShape) shape.eContainer();
bo = getBusinessObjectForPictogramElement(shape);
if (bo instanceof StructureClass)
return (StructureClass) bo;
return null;
}
@Override
public Connection create(ICreateConnectionContext context) {
SPPRef src = getSPPRef(context.getSourceAnchor());
ActorContainerRef srcRef = getRef(context.getSourceAnchor());
SPPRef dst = getSPPRef(context.getTargetAnchor());
ActorContainerRef dstRef = getRef(context.getTargetAnchor());
LayerConnection lc = RoomFactory.eINSTANCE.createLayerConnection();
SAPoint sapt = null;
if (src!=null) {
sapt = RoomFactory.eINSTANCE.createRelaySAPoint();
((RelaySAPoint)sapt).setRelay(src);
}
else if (srcRef!=null) {
sapt = RoomFactory.eINSTANCE.createRefSAPoint();
((RefSAPoint)sapt).setRef(srcRef);
}
lc.setFrom(sapt);
SPPoint sppt = RoomFactory.eINSTANCE.createSPPoint();
sppt.setRef(dstRef);
sppt.setService(dst);
lc.setTo(sppt);
AddConnectionContext addContext = new AddConnectionContext(context.getSourceAnchor(), context.getTargetAnchor());
addContext.setNewObject(lc);
return (Connection) getFeatureProvider().addIfPossible(addContext);
}
}
private class AddFeature extends AbstractAddFeature {
public AddFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canAdd(IAddContext context) {
if (context instanceof IAddConnectionContext && context.getNewObject() instanceof LayerConnection) {
return true;
}
return false;
}
@Override
public PictogramElement add(IAddContext context) {
IAddConnectionContext addConContext = (IAddConnectionContext) context;
LayerConnection addedEReference = (LayerConnection) context.getNewObject();
IPeCreateService peCreateService = Graphiti.getPeCreateService();
Connection connection = createConnection();
connection.setStart(addConContext.getSourceAnchor());
connection.setEnd(addConContext.getTargetAnchor());
Graphiti.getPeService().setPropertyValue(connection, Constants.TYPE_KEY, Constants.CONN_TYPE);
IGaService gaService = Graphiti.getGaService();
Polyline polyline = gaService.createPolyline(connection);
polyline.setForeground(manageColor(LINE_COLOR));
polyline.setLineWidth(LINE_WIDTH);
ConnectionDecorator cd = peCreateService
.createConnectionDecorator(connection, false, 1.0, true);
createArrow(cd);
// create link and wire it
link(connection, addedEReference);
return connection;
}
private Connection createConnection() {
// IPeCreateService peCreateService = Graphiti.getPeCreateService();
// Connection ret = peCreateService.createManhattanConnection(getDiagram());
//peCreateService.createFreeFormConnection(getDiagram());
ManhattanConnection ret = PictogramsFactory.eINSTANCE.createManhattanConnection();
ret.setVisible(true);
ret.setActive(true);
ret.setParent(getDiagram());
return ret;
}
private Polyline createArrow(GraphicsAlgorithmContainer gaContainer) {
IGaService gaService = Graphiti.getGaService();
Polyline polyline =
gaService.createPolyline(gaContainer, new int[] { -15, 10, 0, 0, -15, -10 });
polyline.setForeground(manageColor(LINE_COLOR));
polyline.setLineWidth(LINE_WIDTH);
return polyline;
}
}
private class RemoveFeature extends DefaultRemoveFeature {
public RemoveFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canRemove(IRemoveContext context) {
return false;
}
}
private class DeleteFeature extends DefaultDeleteFeature {
public DeleteFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canDelete(IDeleteContext context) {
EObject bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(context.getPictogramElement());
if (bo instanceof LayerConnection) {
LayerConnection lc = (LayerConnection) bo;
if (isInherited(getDiagram(), lc))
return false;
}
return true;
}
}
private class UpdateFeature extends AbstractUpdateFeature {
public UpdateFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canUpdate(IUpdateContext context) {
Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
if (bo instanceof EObject && ((EObject)bo).eIsProxy())
return true;
return false;
}
@Override
public IReason updateNeeded(IUpdateContext context) {
Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
if (bo instanceof EObject && ((EObject)bo).eIsProxy()) {
return Reason.createTrueReason("LayerConnection deleted from model");
}
return Reason.createFalseReason();
}
@Override
public boolean update(IUpdateContext context) {
ContainerShape containerShape = (ContainerShape)context.getPictogramElement();
Object bo = getBusinessObjectForPictogramElement(containerShape);
if (bo instanceof EObject && ((EObject)bo).eIsProxy()) {
IRemoveContext rc = new RemoveContext(containerShape);
IFeatureProvider featureProvider = getFeatureProvider();
IRemoveFeature removeFeature = featureProvider.getRemoveFeature(rc);
if (removeFeature != null) {
removeFeature.remove(rc);
}
EcoreUtil.delete((EObject) bo);
return true;
}
return false;
}
}
private IFeatureProvider fp;
public FeatureProvider(IDiagramTypeProvider dtp, IFeatureProvider fp) {
super(dtp);
this.fp = fp;
}
private boolean isInherited(Diagram diag, LayerConnection lc) {
ActorClass ac = (ActorClass) Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(diag.getChildren().get(0));
return (lc.eContainer()!=ac);
}
@Override
public ICreateConnectionFeature[] getCreateConnectionFeatures() {
return new ICreateConnectionFeature[] { new CreateFeature(fp) };
}
@Override
public IAddFeature getAddFeature(IAddContext context) {
return new AddFeature(fp);
}
@Override
public IRemoveFeature getRemoveFeature(IRemoveContext context) {
return new RemoveFeature(fp);
}
@Override
public IDeleteFeature getDeleteFeature(IDeleteContext context) {
return new DeleteFeature(fp);
}
@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
return new UpdateFeature(fp);
}
}
class BehaviorProvider extends DefaultToolBehaviorProvider {
public BehaviorProvider(IDiagramTypeProvider dtp) {
super(dtp);
}
}
private FeatureProvider pfp;
private BehaviorProvider tbp;
public LayerConnectionSupport(IDiagramTypeProvider dtp, IFeatureProvider fp) {
pfp = new FeatureProvider(dtp,fp);
tbp = new BehaviorProvider(dtp);
}
public IFeatureProvider getFeatureProvider() {
return pfp;
}
public IToolBehaviorProvider getToolBehaviorProvider() {
return tbp;
}
}