/*******************************************************************************
* 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.behavior.support;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.etrice.core.naming.RoomNameProvider;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerRef;
import org.eclipse.etrice.core.room.ActorRef;
import org.eclipse.etrice.core.room.BaseState;
import org.eclipse.etrice.core.room.RefinedState;
import org.eclipse.etrice.core.room.RoomFactory;
import org.eclipse.etrice.core.room.State;
import org.eclipse.etrice.core.room.StateGraph;
import org.eclipse.etrice.core.room.SubSystemRef;
import org.eclipse.etrice.core.room.TrPoint;
import org.eclipse.etrice.ui.behavior.ImageProvider;
import org.eclipse.etrice.ui.behavior.dialogs.StatePropertyDialog;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.ILayoutFeature;
import org.eclipse.graphiti.features.IMoveShapeFeature;
import org.eclipse.graphiti.features.IReason;
import org.eclipse.graphiti.features.IRemoveFeature;
import org.eclipse.graphiti.features.IResizeShapeFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ICreateContext;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.features.context.IDoubleClickContext;
import org.eclipse.graphiti.features.context.ILayoutContext;
import org.eclipse.graphiti.features.context.IMoveShapeContext;
import org.eclipse.graphiti.features.context.IRemoveContext;
import org.eclipse.graphiti.features.context.IResizeShapeContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.RemoveContext;
import org.eclipse.graphiti.features.custom.AbstractCustomFeature;
import org.eclipse.graphiti.features.custom.ICustomFeature;
import org.eclipse.graphiti.features.impl.AbstractAddFeature;
import org.eclipse.graphiti.features.impl.AbstractCreateFeature;
import org.eclipse.graphiti.features.impl.AbstractLayoutFeature;
import org.eclipse.graphiti.features.impl.AbstractUpdateFeature;
import org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature;
import org.eclipse.graphiti.features.impl.DefaultResizeShapeFeature;
import org.eclipse.graphiti.features.impl.Reason;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.RoundedRectangle;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.Color;
import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
import org.eclipse.graphiti.mm.pictograms.ChopboxAnchor;
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.mm.pictograms.Shape;
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.DefaultFeatureProvider;
import org.eclipse.graphiti.util.ColorConstant;
import org.eclipse.graphiti.util.IColorConstant;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
public class StateSupport {
private static final int LINE_WIDTH = 1;
public static final int DEFAULT_SIZE_X = 60;
public static final int DEFAULT_SIZE_Y = 30;
public static final int MIN_SIZE_X = 60;
public static final int MIN_SIZE_Y = 30;
public static final int MARGIN = 20;
public static final int CORNER_WIDTH = 20;
public static final int HINT_CORNER_WIDTH = 5;
public static final IColorConstant LINE_COLOR = new ColorConstant(0, 0, 0);
public static final IColorConstant INHERITED_COLOR = new ColorConstant(100, 100, 100);
private static final IColorConstant BACKGROUND = new ColorConstant(200, 200, 200);
private static class FeatureProvider extends DefaultFeatureProvider {
private class CreateFeature extends AbstractCreateFeature {
public CreateFeature(IFeatureProvider fp) {
super(fp, "State", "create State");
}
@Override
public String getCreateImageId() {
return ImageProvider.IMG_STATE;
}
@Override
public boolean canCreate(ICreateContext context) {
if (context.getTargetContainer().getLink()!=null)
if (context.getTargetContainer().getLink().getBusinessObjects().size()==1) {
EObject obj = context.getTargetContainer().getLink().getBusinessObjects().get(0);
if (obj instanceof StateGraph) {
return true;
}
}
return false;
}
@Override
public Object[] create(ICreateContext context) {
StateGraph sg = (StateGraph) context.getTargetContainer().getLink().getBusinessObjects().get(0);
boolean inherited = isInherited(getDiagram(), sg);
if (inherited) {
// TODOHRR: handling of refined state - also consider refining action codes
// we have to insert a refined state first
RefinedState rs = RoomFactory.eINSTANCE.createRefinedState();
rs.setBase((BaseState) sg.eContainer());
ActorClass ac = getActorClass(getDiagram());
ac.getStateMachine().getStates().add(rs);
// now we change the context
sg = RoomFactory.eINSTANCE.createStateGraph();
rs.setSubgraph(sg);
link(context.getTargetContainer(), sg);
}
// create new State
BaseState s = RoomFactory.eINSTANCE.createBaseState();
s.setName(RoomNameProvider.getUniqueStateName(sg));
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
StatePropertyDialog dlg = new StatePropertyDialog(shell, s, sg);
if (dlg.open()!=Window.OK)
// find a method to abort creation
//throw new RuntimeException();
return EMPTY;
sg.getStates().add(s);
addGraphicalRepresentation(context, s);
// return newly created business object(s)
return new Object[] { s };
}
}
private class AddFeature extends AbstractAddFeature {
public AddFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canAdd(IAddContext context) {
if (context.getNewObject() instanceof State) {
if (context.getTargetContainer().getLink().getBusinessObjects().size()==1) {
EObject obj = context.getTargetContainer().getLink().getBusinessObjects().get(0);
if (obj instanceof StateGraph) {
return true;
}
}
}
return false;
}
@Override
public PictogramElement add(IAddContext context) {
State s = (State) context.getNewObject();
ContainerShape acShape = context.getTargetContainer();
// CONTAINER SHAPE WITH RECTANGLE
IPeCreateService peCreateService = Graphiti.getPeCreateService();
ContainerShape containerShape =
peCreateService.createContainerShape(acShape, true);
Graphiti.getPeService().setPropertyValue(containerShape, Constants.TYPE_KEY, Constants.STATE_TYPE);
int width = context.getWidth() <= 0 ? DEFAULT_SIZE_X : context.getWidth();
int height = context.getHeight() <= 0 ? DEFAULT_SIZE_Y : context.getHeight();
boolean inherited = isInherited(getDiagram(), s);
Color lineColor = manageColor(inherited?INHERITED_COLOR:LINE_COLOR);
IGaService gaService = Graphiti.getGaService();
{
final Rectangle invisibleRectangle = gaService.createInvisibleRectangle(containerShape);
gaService.setLocationAndSize(invisibleRectangle,
context.getX()-(width/2+MARGIN), context.getY()-(height/2+MARGIN), width + 2*MARGIN, height + 2*MARGIN);
RoundedRectangle rect = createFigure(s, invisibleRectangle, lineColor, manageColor(BACKGROUND));
// anchor for direct transitions to this state
ChopboxAnchor anchor = peCreateService.createChopboxAnchor(containerShape);
anchor.setReferencedGraphicsAlgorithm(rect);
// create link and wire it
link(containerShape, s);
}
{
Shape labelShape = peCreateService.createShape(containerShape, false);
Text label = gaService.createDefaultText(labelShape, s.getName());
label.setForeground(lineColor);
label.setBackground(lineColor);
label.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER);
label.setVerticalAlignment(Orientation.ALIGNMENT_CENTER);
gaService.setLocationAndSize(label, MARGIN, MARGIN, width, height);
}
// call the layout feature
layoutPictogramElement(containerShape);
return containerShape;
}
}
private class LayoutFeature extends AbstractLayoutFeature {
public LayoutFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canLayout(ILayoutContext context) {
// return true, if pictogram element is linked to a State
PictogramElement pe = context.getPictogramElement();
if (!(pe instanceof ContainerShape))
return false;
Object bo = getBusinessObjectForPictogramElement(pe);
return bo instanceof State;
}
@Override
public boolean layout(ILayoutContext context) {
boolean anythingChanged = false;
ContainerShape containerShape = (ContainerShape) context
.getPictogramElement();
// our invisible rectangle
GraphicsAlgorithm containerGa = containerShape.getGraphicsAlgorithm();
int w = containerGa.getWidth();
int h = containerGa.getHeight();
if (containerGa.getGraphicsAlgorithmChildren().size()>=1) {
// the visible border
GraphicsAlgorithm ga = containerGa.getGraphicsAlgorithmChildren().get(0);
int nw = w-2*MARGIN;
int nh = h-2*MARGIN;
ga.setWidth(nw);
ga.setHeight(nh);
Object bo = getBusinessObjectForPictogramElement(containerShape);
if (bo instanceof State) {
State s = (State) bo;
ga.getGraphicsAlgorithmChildren().clear();
Color lineColor = manageColor(isInherited(getDiagram(), s)?INHERITED_COLOR:LINE_COLOR);
addSubStructureHint(s, (RoundedRectangle) ga, lineColor);
}
if (!containerShape.getChildren().isEmpty()) {
GraphicsAlgorithm childGA = containerShape.getChildren().get(0).getGraphicsAlgorithm();
assert(childGA instanceof Text): "label expected";
childGA.setWidth(nw);
childGA.setHeight(nh);
}
anythingChanged = true;
}
return anythingChanged;
}
}
private static class PropertyFeature extends AbstractCustomFeature {
public PropertyFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public String getName() {
return "Edit State...";
}
@Override
public String getDescription() {
return "Edit State Properties";
}
@Override
public boolean canExecute(ICustomContext context) {
PictogramElement[] pes = context.getPictogramElements();
if (pes != null && pes.length == 1) {
Object bo = getBusinessObjectForPictogramElement(pes[0]);
if (bo instanceof State) {
return true;
}
}
return false;
}
@Override
public void execute(ICustomContext context) {
State s = (State) getBusinessObjectForPictogramElement(context.getPictogramElements()[0]);
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
StateGraph sg = (StateGraph)s.eContainer();
StatePropertyDialog dlg = new StatePropertyDialog(shell, s, sg);
if (dlg.open()!=Window.OK)
// TODOHRR: introduce a method to revert changes
//throw new RuntimeException();
return;
updateFigure(s, context);
}
private void updateFigure(State s, ICustomContext context) {
ContainerShape container = (ContainerShape)context.getPictogramElements()[0];
// we clear the figure and rebuild it
GraphicsAlgorithm invisibleRect = context.getPictogramElements()[0].getGraphicsAlgorithm();
invisibleRect.getGraphicsAlgorithmChildren().clear();
createFigure(s, invisibleRect, manageColor(LINE_COLOR), manageColor(BACKGROUND));
GraphicsAlgorithm ga = container.getChildren().get(0).getGraphicsAlgorithm();
if (ga instanceof Text) {
((Text)ga).setValue(s.getName());
}
}
}
private static class GoDownFeature extends AbstractCustomFeature implements
ICustomFeature {
public GoDownFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public String getName() {
return "Switch to SubGraph";
}
@Override
public String getDescription() {
return "Switch Context to SubGraph";
}
@Override
public boolean canExecute(ICustomContext context) {
ContainerShape container = (ContainerShape)context.getPictogramElements()[0];
Object bo = getBusinessObjectForPictogramElement(container);
if (bo instanceof State) {
if (((State) bo).getSubgraph()!=null)
return true;
}
return false;
}
@Override
public void execute(ICustomContext context) {
getDiagramEditor().selectPictogramElements(new PictogramElement[] {});
ContainerShape container = (ContainerShape)context.getPictogramElements()[0];
Object bo = getBusinessObjectForPictogramElement(container);
if (bo instanceof State) {
if (((State) bo).getSubgraph()!=null)
ContextSwitcher.switchTo(getDiagram(), ((State) bo).getSubgraph());
}
}
@Override
public boolean hasDoneChanges() {
return false;
}
}
private static class CreateSubGraphFeature extends AbstractCustomFeature implements
ICustomFeature {
public CreateSubGraphFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public String getName() {
return "Create SubGraph";
}
@Override
public String getDescription() {
return "Create and Switch to New SubGraph";
}
@Override
public boolean canExecute(ICustomContext context) {
ContainerShape container = (ContainerShape)context.getPictogramElements()[0];
Object bo = getBusinessObjectForPictogramElement(container);
if (bo instanceof State) {
if (((State) bo).getSubgraph()==null)
return true;
}
return false;
}
@Override
public void execute(ICustomContext context) {
getDiagramEditor().selectPictogramElements(new PictogramElement[] {});
ContainerShape container = (ContainerShape)context.getPictogramElements()[0];
Object bo = getBusinessObjectForPictogramElement(container);
if (bo instanceof State) {
State s = (State) bo;
s.setSubgraph(RoomFactory.eINSTANCE.createStateGraph());
AddContext addContext = new AddContext();
addContext.setNewObject(s.getSubgraph());
addContext.setTargetContainer(getDiagram());
addContext.setX(StateGraphSupport.MARGIN);
addContext.setY(StateGraphSupport.MARGIN);
PictogramElement subGraphShape = getFeatureProvider().addIfPossible(addContext);
if (subGraphShape!=null) {
RoundedRectangle borderRect = (RoundedRectangle) container.getGraphicsAlgorithm().getGraphicsAlgorithmChildren().get(0);
boolean inherited = isInherited(getDiagram(), s);
Color lineColor = manageColor(inherited?INHERITED_COLOR:LINE_COLOR);
addSubStructureHint(s, borderRect, lineColor);
}
ContextSwitcher.switchTo(getDiagram(), s.getSubgraph());
}
}
}
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 bo instanceof State;
}
@Override
public IReason updateNeeded(IUpdateContext context) {
Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
if (bo instanceof EObject && ((EObject)bo).eIsProxy()) {
return Reason.createTrueReason("State deleted from model");
}
State s = (State) bo;
// check if ref still owned/inherited anymore
ContainerShape containerShape = (ContainerShape)context.getPictogramElement();
bo = getBusinessObjectForPictogramElement(containerShape);
if (bo instanceof ActorClass) {
ActorClass ac = (ActorClass) bo;
boolean found = false;
do {
if (ac==s.eContainer())
found = true;
ac = ac.getBase();
}
while (!found && ac!=null);
if (!found)
return Reason.createTrueReason("Ref not inherited anymore");
}
// check sub structure hint
{
boolean hasSubStruct = hasSubStructure(s);
GraphicsAlgorithm invisibleRect = containerShape.getGraphicsAlgorithm();
if (!invisibleRect.getGraphicsAlgorithmChildren().isEmpty()) {
GraphicsAlgorithm borderRect = invisibleRect.getGraphicsAlgorithmChildren().get(0);
if (hasSubStruct && borderRect.getGraphicsAlgorithmChildren().isEmpty())
return Reason.createTrueReason("Ref has sub structure now");
if (!hasSubStruct && !borderRect.getGraphicsAlgorithmChildren().isEmpty())
return Reason.createTrueReason("Ref has no sub structure anymore");
}
}
// check class name
int last = containerShape.getChildren().size()-1;
if (last>=0) {
GraphicsAlgorithm ga = containerShape.getChildren().get(last).getGraphicsAlgorithm();
if (ga instanceof Text) {
if (bo instanceof ActorContainerRef) {
String label = getLabel((ActorContainerRef) bo);
if (!((Text)ga).getValue().equals(label))
return Reason.createTrueReason("Class name is out of date");
}
}
}
// TODOHRR: check interface ports and spps added to model not present in diagram
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;
}
State s = (State) bo;
{
boolean hasSubStruct = hasSubStructure(s);
GraphicsAlgorithm invisibleRect = containerShape.getGraphicsAlgorithm();
if (!invisibleRect.getGraphicsAlgorithmChildren().isEmpty()) {
GraphicsAlgorithm borderRect = invisibleRect.getGraphicsAlgorithmChildren().get(0);
if (hasSubStruct && borderRect.getGraphicsAlgorithmChildren().isEmpty()) {
Color lineColor = manageColor(isInherited(getDiagram(), s)?INHERITED_COLOR:LINE_COLOR);
addSubStructureHint(s, (RoundedRectangle) borderRect, lineColor);
}
else if (!hasSubStruct && !borderRect.getGraphicsAlgorithmChildren().isEmpty()) {
containerShape.getGraphicsAlgorithm().getGraphicsAlgorithmChildren().clear();
}
}
}
int last = containerShape.getChildren().size()-1;
if (last>=0) {
GraphicsAlgorithm ga = containerShape.getChildren().get(last).getGraphicsAlgorithm();
if (ga instanceof Text) {
((Text)ga).setValue(s.getName());
}
}
return true;
}
}
private class MoveShapeFeature extends DefaultMoveShapeFeature {
public MoveShapeFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canMoveShape(IMoveShapeContext context) {
boolean canMove = super.canMoveShape(context);
if (canMove) {
Object bo = getBusinessObjectForPictogramElement(context.getPictogramElement());
if (bo instanceof State) {
State s = (State) bo;
//ContainerShape sgShape = context.getTargetContainer();
// TODOHRR: also check coordinates (no overlap with state graph boundaries)
return !isInherited(getDiagram(), s);
}
}
return canMove;
}
}
private class ResizeFeature extends DefaultResizeShapeFeature {
public ResizeFeature(IFeatureProvider fp) {
super(fp);
}
@Override
public boolean canResizeShape(IResizeShapeContext context) {
if (!super.canResizeShape(context))
return false;
int width = context.getWidth()-MARGIN;
int height = context.getHeight()-MARGIN;
if (width>0 && height>0)
if (width < MIN_SIZE_X+MARGIN || height < MIN_SIZE_Y+MARGIN)
return false;
return true;
}
@Override
public void resizeShape(IResizeShapeContext context) {
Shape shape = context.getShape();
if (shape.getGraphicsAlgorithm()!=null) {
GraphicsAlgorithm containerGa = shape.getGraphicsAlgorithm();
if (containerGa.getGraphicsAlgorithmChildren().size()==1) {
// scale interface item coordinates
// we refer to the visible rectangle which defines the border of our structure class
// since the margin is not scaled
GraphicsAlgorithm ga = containerGa.getGraphicsAlgorithmChildren().get(0);
double sx = (context.getWidth()-2*MARGIN)/(double)ga.getWidth();
double sy = (context.getHeight()-2*MARGIN)/(double)ga.getHeight();
for (Shape childShape : ((ContainerShape)context.getShape()).getChildren()) {
Object childBo = getBusinessObjectForPictogramElement(childShape);
if (childBo instanceof TrPoint) {
ga = childShape.getGraphicsAlgorithm();
ga.setX((int) (ga.getX()*sx));
ga.setY((int) (ga.getY()*sy));
}
}
}
}
super.resizeShape(context);
}
}
private IFeatureProvider fp;
public FeatureProvider(IDiagramTypeProvider dtp, IFeatureProvider fp) {
super(dtp);
this.fp = fp;
}
public static RoundedRectangle createFigure(State s,
GraphicsAlgorithm invisibleRect, Color darkColor,
Color brightColor) {
IGaService gaService = Graphiti.getGaService();
RoundedRectangle rect = gaService.createRoundedRectangle(invisibleRect, CORNER_WIDTH, CORNER_WIDTH);
rect.setForeground(darkColor);
rect.setBackground(brightColor);
rect.setLineWidth(LINE_WIDTH);
gaService.setLocationAndSize(rect, MARGIN, MARGIN, invisibleRect.getWidth()-2*MARGIN, invisibleRect.getHeight()-2*MARGIN);
addSubStructureHint(s, rect, darkColor);
return rect;
}
@Override
public ICreateFeature[] getCreateFeatures() {
return new ICreateFeature[] { new CreateFeature(fp) };
}
@Override
public IAddFeature getAddFeature(IAddContext context) {
return new AddFeature(fp);
}
@Override
public ILayoutFeature getLayoutFeature(ILayoutContext context) {
return new LayoutFeature(fp);
}
@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
return new UpdateFeature(fp);
}
@Override
public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) {
return new MoveShapeFeature(fp);
}
@Override
public IResizeShapeFeature getResizeShapeFeature(
IResizeShapeContext context) {
return new ResizeFeature(fp);
}
@Override
public ICustomFeature[] getCustomFeatures(ICustomContext context) {
return new ICustomFeature[] { new PropertyFeature(fp), new GoDownFeature(fp), new CreateSubGraphFeature(fp) };
}
private static ActorClass getActorClass(Diagram diag) {
EObject bo = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(diag);
if (bo instanceof ActorClass)
return (ActorClass) bo;
return null;
}
protected static String getLabel(ActorContainerRef acr) {
String className = "<unknown>";
if (acr instanceof ActorRef) {
if (((ActorRef)acr).getType()!=null)
className = ((ActorRef)acr).getType().getName();
}
else if (acr instanceof SubSystemRef) {
if (((SubSystemRef)acr).getType()!=null)
className = ((SubSystemRef)acr).getType().getName();
}
return acr.getName()+"\n("+className+")";
}
protected static boolean isInherited(Diagram diag, EObject obj) {
ActorClass parent = getActorClass(diag);
while (obj!=null) {
if (obj instanceof ActorClass)
return obj!=parent;
obj = obj.eContainer();
}
assert(false): "no parent actor class found";
return false;
}
private static boolean hasSubStructure(State acr) {
return (acr.getSubgraph()!=null);
}
private static void addSubStructureHint(State s,
RoundedRectangle rect, Color lineColor) {
if (hasSubStructure(s)) {
int x = rect.getWidth()-25;
int y = 3;
IGaService gaService = Graphiti.getGaService();
RoundedRectangle hint1 = gaService.createRoundedRectangle(rect, HINT_CORNER_WIDTH, HINT_CORNER_WIDTH);
hint1.setForeground(lineColor);
hint1.setFilled(false);
hint1.setLineWidth(LINE_WIDTH);
gaService.setLocationAndSize(hint1, x, y, 15, 8);
}
}
}
private class BehaviorProvider extends DefaultToolBehaviorProvider {
public BehaviorProvider(IDiagramTypeProvider dtp) {
super(dtp);
}
@Override
public GraphicsAlgorithm[] getClickArea(PictogramElement pe) {
GraphicsAlgorithm invisible = pe.getGraphicsAlgorithm();
GraphicsAlgorithm rectangle =
invisible.getGraphicsAlgorithmChildren().get(0);
return new GraphicsAlgorithm[] { rectangle };
}
@Override
public GraphicsAlgorithm getSelectionBorder(PictogramElement pe) {
GraphicsAlgorithm invisible = pe.getGraphicsAlgorithm();
GraphicsAlgorithm rectangle =
invisible.getGraphicsAlgorithmChildren().get(0);
return rectangle;
}
@Override
public ICustomFeature getDoubleClickFeature(IDoubleClickContext context) {
return new FeatureProvider.GoDownFeature(getDiagramTypeProvider().getFeatureProvider());
}
}
private FeatureProvider pfp;
private BehaviorProvider tbp;
public StateSupport(IDiagramTypeProvider dtp, IFeatureProvider fp) {
pfp = new FeatureProvider(dtp,fp);
tbp = new BehaviorProvider(dtp);
}
public IFeatureProvider getFeatureProvider() {
return pfp;
}
public IToolBehaviorProvider getToolBehaviorProvider() {
return tbp;
}
}