/******************************************************************************* * 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.algorithms.Polyline; import org.eclipse.graphiti.mm.pictograms.Anchor; import org.eclipse.graphiti.mm.pictograms.Connection; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; 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.ActorContainerClass; import org.eclipse.etrice.core.room.ActorContainerRef; import org.eclipse.etrice.core.room.Binding; import org.eclipse.etrice.core.room.BindingEndPoint; import org.eclipse.etrice.core.room.LogicalSystem; import org.eclipse.etrice.core.room.Port; import org.eclipse.etrice.core.room.RoomFactory; import org.eclipse.etrice.core.room.StructureClass; import org.eclipse.etrice.core.room.SubSystemClass; public class BindingSupport { public static final IColorConstant LINE_COLOR = new ColorConstant(0, 0, 0); public static final IColorConstant INHERITED_COLOR = new ColorConstant(100, 100, 100); class FeatureProvider extends DefaultFeatureProvider { private class CreateFeature extends AbstractCreateConnectionFeature { private boolean justStarted = false; public CreateFeature(IFeatureProvider fp) { super(fp, "Binding", "create Binding"); } @Override public String getCreateImageId() { return ImageProvider.IMG_BINDING; } @Override public boolean canCreate(ICreateConnectionContext context) { Port src = getPort(context.getSourceAnchor()); Port tgt = getPort(context.getTargetAnchor()); ActorContainerRef srcRef = getRef(context.getSourceAnchor()); if (justStarted) { justStarted = false; beginHighLightMatches(src, srcRef); } if (src==null || tgt==null) { return false; } StructureClass ac = getParent(context); if (ac==null) { return false; } ActorContainerRef tgtRef = getRef(context.getTargetAnchor()); return ValidationUtil.isConnectable(src, srcRef, tgt, tgtRef, ac).isOk(); } public boolean canStartConnection(ICreateConnectionContext context) { Port src = getPort(context.getSourceAnchor()); boolean canStart = src!=null; if (canStart) { ActorContainerRef ref = getRef(context.getSourceAnchor()); if (ref==null) { // this port is local, i.e. owned by the parent itself ActorContainerClass acc = (ActorContainerClass) src.eContainer(); if (!ValidationUtil.isConnectable(src, null, acc).isOk()) canStart = false; } else { ActorContainerClass acc = (ActorContainerClass) ref.eContainer(); if (!ValidationUtil.isConnectable(src, ref, acc).isOk()) canStart = false; } } if (canStart) justStarted = true; return canStart; } private Port getPort(Anchor anchor) { if (anchor != null) { Object obj = getBusinessObjectForPictogramElement(anchor.getParent()); if (obj instanceof Port) { return (Port) obj; } } 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; } public ActorContainerRef getRef(Anchor anchor) { ContainerShape shape = (ContainerShape) anchor.getParent().eContainer(); Object bo = getBusinessObjectForPictogramElement(shape); if (bo instanceof ActorContainerRef) return (ActorContainerRef) bo; return null; } @Override public Connection create(ICreateConnectionContext context) { Connection newConnection = null; endHighLightMatches(); Port src = getPort(context.getSourceAnchor()); Port dst = getPort(context.getTargetAnchor()); StructureClass ac = getParent(context); if (src!=null && dst!=null && ac!=null) { Binding bind = RoomFactory.eINSTANCE.createBinding(); BindingEndPoint ep1 = RoomFactory.eINSTANCE.createBindingEndPoint(); ActorContainerRef ar1 = getRef(context.getSourceAnchor()); ep1.setPort(src); ep1.setActorRef(ar1); BindingEndPoint ep2 = RoomFactory.eINSTANCE.createBindingEndPoint(); ActorContainerRef ar2 = getRef(context.getTargetAnchor()); ep2.setPort(dst); ep2.setActorRef(ar2); bind.setEndpoint1(ep1); bind.setEndpoint2(ep2); ac.getBindings().add(bind); AddConnectionContext addContext = new AddConnectionContext(context.getSourceAnchor(), context.getTargetAnchor()); addContext.setNewObject(bind); newConnection = (Connection) getFeatureProvider().addIfPossible(addContext); } return newConnection; } private void beginHighLightMatches(Port port, ActorContainerRef ref) { if (port==null) return; StructureClass acc = (ActorContainerClass) ((ref!=null)? ref.eContainer():port.eContainer()); if (acc instanceof ActorClass) { } else if (acc instanceof SubSystemClass) { } else if (acc instanceof LogicalSystem) { } else { assert(false): "unknown kind of StructureClass"; } } private void endHighLightMatches() { } } private class AddFeature extends AbstractAddFeature { public AddFeature(IFeatureProvider fp) { super(fp); } @Override public boolean canAdd(IAddContext context) { if (context instanceof IAddConnectionContext && context.getNewObject() instanceof Binding) { return true; } return false; } @Override public PictogramElement add(IAddContext context) { IAddConnectionContext addConContext = (IAddConnectionContext) context; Binding addedEReference = (Binding) context.getNewObject(); boolean inherited = isInherited(getDiagram(), addedEReference); IPeCreateService peCreateService = Graphiti.getPeCreateService(); // CONNECTION WITH POLYLINE Connection connection = peCreateService.createFreeFormConnection(getDiagram()); connection.setStart(addConContext.getSourceAnchor()); connection.setEnd(addConContext.getTargetAnchor()); Graphiti.getPeService().setPropertyValue(connection, Constants.TYPE_KEY, Constants.BIND_TYPE); IGaService gaService = Graphiti.getGaService(); Polyline polyline = gaService.createPolyline(connection); polyline.setForeground(manageColor(inherited?INHERITED_COLOR:LINE_COLOR)); // create link and wire it link(connection, addedEReference); return connection; } } 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("Binding 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 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 Binding) { Binding b = (Binding) bo; if (isInherited(getDiagram(), b)) return false; } return true; } } private IFeatureProvider fp; public FeatureProvider(IDiagramTypeProvider dtp, IFeatureProvider fp) { super(dtp); this.fp = fp; } private boolean isInherited(Diagram diag, Binding b) { ActorClass ac = (ActorClass) Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(diag.getChildren().get(0)); return (b.eContainer()!=ac); } @Override public ICreateConnectionFeature[] getCreateConnectionFeatures() { return new ICreateConnectionFeature[] { new CreateFeature(fp) }; } @Override public IAddFeature getAddFeature(IAddContext context) { return new AddFeature(fp); } @Override public IUpdateFeature getUpdateFeature(IUpdateContext context) { return new UpdateFeature(fp); } @Override public IRemoveFeature getRemoveFeature(IRemoveContext context) { return new RemoveFeature(fp); } @Override public IDeleteFeature getDeleteFeature(IDeleteContext context) { return new DeleteFeature(fp); } } class BehaviorProvider extends DefaultToolBehaviorProvider { public BehaviorProvider(IDiagramTypeProvider dtp) { super(dtp); } } private FeatureProvider pfp; private BehaviorProvider tbp; public BindingSupport(IDiagramTypeProvider dtp, IFeatureProvider fp) { pfp = new FeatureProvider(dtp,fp); tbp = new BehaviorProvider(dtp); } public IFeatureProvider getFeatureProvider() { return pfp; } public IToolBehaviorProvider getToolBehaviorProvider() { return tbp; } }