/*******************************************************************************
* 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;
import java.util.Arrays;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.etrice.core.naming.RoomFragmentProvider;
import org.eclipse.etrice.core.room.ChoicePoint;
import org.eclipse.etrice.core.room.State;
import org.eclipse.etrice.core.room.StateGraph;
import org.eclipse.etrice.core.room.TrPoint;
import org.eclipse.etrice.core.room.Transition;
import org.eclipse.etrice.core.room.util.RoomSwitch;
import org.eclipse.etrice.ui.behavior.support.ChoicePointSupport;
import org.eclipse.etrice.ui.behavior.support.InitialPointSupport;
import org.eclipse.etrice.ui.behavior.support.StateGraphSupport;
import org.eclipse.etrice.ui.behavior.support.StateSupport;
import org.eclipse.etrice.ui.behavior.support.TrPointSupport;
import org.eclipse.etrice.ui.behavior.support.TransitionSupport;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.ILayoutFeature;
import org.eclipse.graphiti.features.IMoveShapeFeature;
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.ICustomContext;
import org.eclipse.graphiti.features.context.IDeleteContext;
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.IPictogramElementContext;
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.custom.ICustomFeature;
import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
import org.eclipse.graphiti.mm.algorithms.styles.LineStyle;
import org.eclipse.graphiti.mm.pictograms.ConnectionDecorator;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.tb.DefaultToolBehaviorProvider;
import org.eclipse.graphiti.tb.IContextButtonPadData;
import org.eclipse.graphiti.tb.ISelectionInfo;
import org.eclipse.graphiti.tb.IToolBehaviorProvider;
import org.eclipse.graphiti.tb.SelectionInfoImpl;
import org.eclipse.graphiti.ui.features.DefaultFeatureProvider;
import org.eclipse.graphiti.util.IColorConstant;
public class ProviderDispatcher {
private class FeatureProviderSwitch extends RoomSwitch<IFeatureProvider> {
private ContainerShape parent = null;
@Override
public IFeatureProvider doSwitch(EObject theEObject) {
if (theEObject==null)
return null;
if (theEObject.eIsProxy()) {
if (RoomFragmentProvider.isState(theEObject))
return stateGraphSupport.getFeatureProvider();
if (RoomFragmentProvider.isTrPoint(theEObject))
return trPointSupport.getFeatureProvider();
if (RoomFragmentProvider.isChoicePoint(theEObject))
return choicePointSupport.getFeatureProvider();
if (RoomFragmentProvider.isStateGraph(theEObject))
return stateGraphSupport.getFeatureProvider();
if (RoomFragmentProvider.isTransition(theEObject))
return transitionSupport.getFeatureProvider();
}
return super.doSwitch(theEObject);
}
@Override
public IFeatureProvider caseStateGraph(StateGraph object) {
if (parent!=null && parent.getLink()!=null) {
if (parent.getLink().getBusinessObjects().size()>0) {
EObject bo = parent.getLink().getBusinessObjects().get(0);
if (bo instanceof StateGraph)
return initialPointSupport.getFeatureProvider();
}
parent = null;
}
return stateGraphSupport.getFeatureProvider();
}
@Override
public IFeatureProvider caseTrPoint(TrPoint object) {
return trPointSupport.getFeatureProvider();
}
@Override
public IFeatureProvider caseChoicePoint(ChoicePoint object) {
return choicePointSupport.getFeatureProvider();
}
@Override
public IFeatureProvider caseState(State object) {
return stateSupport.getFeatureProvider();
}
@Override
public IFeatureProvider caseTransition(Transition object) {
return transitionSupport.getFeatureProvider();
}
@Override
public IFeatureProvider defaultCase(EObject object) {
return null;
}
public ICreateFeature[] getCreateFeatures() {
return concatAll(
stateSupport.getFeatureProvider().getCreateFeatures(),
initialPointSupport.getFeatureProvider().getCreateFeatures(),
trPointSupport.getFeatureProvider().getCreateFeatures(),
choicePointSupport.getFeatureProvider().getCreateFeatures()
);
}
public ICreateConnectionFeature[] getCreateConnectionFeatures() {
return transitionSupport.getFeatureProvider().getCreateConnectionFeatures();
}
public ICustomFeature[] getCustomFeatures(ICustomContext context) {
return concatAll(
trPointSupport.getFeatureProvider().getCustomFeatures(context),
stateSupport.getFeatureProvider().getCustomFeatures(context),
transitionSupport.getFeatureProvider().getCustomFeatures(context)
);
}
public void setParentContainer(ContainerShape parent) {
this.parent = parent;
}
}
private class ToolBehaviorProviderSwitch extends RoomSwitch<IToolBehaviorProvider> {
private ContainerShape parent = null;
@Override
public IToolBehaviorProvider doSwitch(EObject theEObject) {
if (theEObject==null)
return null;
if (theEObject.eIsProxy()) {
if (RoomFragmentProvider.isState(theEObject))
return stateGraphSupport.getToolBehaviorProvider();
if (RoomFragmentProvider.isTrPoint(theEObject))
return trPointSupport.getToolBehaviorProvider();
if (RoomFragmentProvider.isChoicePoint(theEObject))
return choicePointSupport.getToolBehaviorProvider();
if (RoomFragmentProvider.isStateGraph(theEObject))
return stateGraphSupport.getToolBehaviorProvider();
if (RoomFragmentProvider.isTransition(theEObject))
return transitionSupport.getToolBehaviorProvider();
}
return super.doSwitch(theEObject);
}
@Override
public IToolBehaviorProvider caseStateGraph(StateGraph object) {
if (parent!=null && parent.getLink()!=null) {
if (parent.getLink().getBusinessObjects().size()>0) {
EObject bo = parent.getLink().getBusinessObjects().get(0);
if (bo instanceof StateGraph)
return initialPointSupport.getToolBehaviorProvider();
}
parent = null;
}
return stateGraphSupport.getToolBehaviorProvider();
}
@Override
public IToolBehaviorProvider caseTrPoint(TrPoint object) {
return trPointSupport.getToolBehaviorProvider();
}
@Override
public IToolBehaviorProvider caseChoicePoint(ChoicePoint object) {
return choicePointSupport.getToolBehaviorProvider();
}
@Override
public IToolBehaviorProvider caseState(State object) {
return stateSupport.getToolBehaviorProvider();
}
@Override
public IToolBehaviorProvider caseTransition(Transition object) {
return transitionSupport.getToolBehaviorProvider();
}
@Override
public IToolBehaviorProvider defaultCase(EObject object) {
return null;
}
public void setParentContainer(ContainerShape parent) {
this.parent = parent;
}
}
private class DispatchingFeatureProvider extends DefaultFeatureProvider {
public DispatchingFeatureProvider(IDiagramTypeProvider dtp) {
super(dtp);
}
@Override
public ICreateFeature[] getCreateFeatures() {
return getAllCreateFeatures();
}
@Override
public ICreateConnectionFeature[] getCreateConnectionFeatures() {
return getAllCreateConnectionFeatures();
}
@Override
public IAddFeature getAddFeature(IAddContext context) {
featureSwitch.setParentContainer(context.getTargetContainer());
IFeatureProvider fp = featureSwitch.doSwitch(((EObject) context.getNewObject()));
if (fp==null)
return super.getAddFeature(context);
else
return fp.getAddFeature(context);
}
@Override
public ILayoutFeature getLayoutFeature(ILayoutContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getLayoutFeature(context);
else
return super.getLayoutFeature(context);
}
@Override
public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getMoveShapeFeature(context);
else
return super.getMoveShapeFeature(context);
}
@Override
public IResizeShapeFeature getResizeShapeFeature(IResizeShapeContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getResizeShapeFeature(context);
else
return super.getResizeShapeFeature(context);
}
@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getUpdateFeature(context);
else
return super.getUpdateFeature(context);
}
@Override
public IDeleteFeature getDeleteFeature(IDeleteContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getDeleteFeature(context);
else
return super.getDeleteFeature(context);
}
@Override
public IRemoveFeature getRemoveFeature(IRemoveContext context) {
IFeatureProvider fp = getFeatureProvider(context);
if (fp!=null)
return fp.getRemoveFeature(context);
else
return super.getRemoveFeature(context);
}
@Override
public ICustomFeature[] getCustomFeatures(ICustomContext context) {
return getAllCustomFeatures(context);
}
private EObject getBusinessObject(IPictogramElementContext context) {
PictogramElement pictogramElement = context.getPictogramElement();
EObject bo = (EObject) getBusinessObjectForPictogramElement(pictogramElement);
return bo;
}
private IFeatureProvider getFeatureProvider(IPictogramElementContext context) {
EObject eco = context.getPictogramElement().eContainer();
if (eco instanceof ContainerShape) {
featureSwitch.setParentContainer((ContainerShape) eco);
IFeatureProvider fp = featureSwitch.doSwitch(getBusinessObject(context));
if (fp!=null)
return fp;
}
return null;
}
}
private class DispatchingToolBehaviorProvider extends DefaultToolBehaviorProvider {
public DispatchingToolBehaviorProvider(IDiagramTypeProvider diagramTypeProvider) {
super(diagramTypeProvider);
}
@Override
public GraphicsAlgorithm[] getClickArea(PictogramElement pe) {
IToolBehaviorProvider bp = getToolBehaviorProvider(pe);
if (bp==null)
return super.getClickArea(pe);
else
return bp.getClickArea(pe);
}
@Override
public GraphicsAlgorithm getSelectionBorder(PictogramElement pe) {
IToolBehaviorProvider bp = getToolBehaviorProvider(pe);
if (bp==null)
return super.getSelectionBorder(pe);
else
return bp.getSelectionBorder(pe);
}
@Override
public ICustomFeature getDoubleClickFeature(IDoubleClickContext context) {
IToolBehaviorProvider bp = getToolBehaviorProvider(context.getPictogramElements()[0]);
if (bp==null)
return super.getDoubleClickFeature(context);
else
return bp.getDoubleClickFeature(context);
}
protected IToolBehaviorProvider getToolBehaviorProvider(PictogramElement pe) {
IFeatureProvider fp = getFeatureProvider();
if (pe instanceof ConnectionDecorator)
pe = (PictogramElement) pe.eContainer();
EObject bo = (EObject) fp.getBusinessObjectForPictogramElement(pe);
if (bo==null)
return null;
EObject eco = pe.eContainer();
if (eco instanceof ContainerShape) {
behaviorSwitch.setParentContainer((ContainerShape) eco);
IToolBehaviorProvider bp = behaviorSwitch.doSwitch(bo);
if (bp!=null)
return bp;
}
IToolBehaviorProvider bp = behaviorSwitch.doSwitch(bo);
return bp;
}
@Override
public IContextButtonPadData getContextButtonPad(IPictogramElementContext context) {
IToolBehaviorProvider bp = getToolBehaviorProvider(context.getPictogramElement());
if (bp==null)
return super.getContextButtonPad(context);
else
return bp.getContextButtonPad(context);
}
public ISelectionInfo getSelectionInfoForShape(Shape shape) {
ISelectionInfo si = new SelectionInfoImpl(IColorConstant.SHAPE_SELECTION_FG, IColorConstant.HANDLE_FG, IColorConstant.HANDLE_BG,
LineStyle.DASH);
// si.setPrimarySelectionBackgroundColor(IColorConstant.LIGHT_GRAY);
// si.setSecondarySelectionBackgroundColor(IColorConstant.LIGHT_GRAY);
return si;
}
@Override
public String getToolTip(GraphicsAlgorithm ga) {
IToolBehaviorProvider bp = getToolBehaviorProvider(ga.getPictogramElement());
if (bp==null)
return super.getToolTip(ga);
else
return bp.getToolTip(ga);
}
}
private StateGraphSupport stateGraphSupport;
private TrPointSupport trPointSupport;
private InitialPointSupport initialPointSupport;
private ChoicePointSupport choicePointSupport;
private StateSupport stateSupport;
private TransitionSupport transitionSupport;
private FeatureProviderSwitch featureSwitch;
private ToolBehaviorProviderSwitch behaviorSwitch;
private DispatchingFeatureProvider dispatchingFP;
private DispatchingToolBehaviorProvider dispatchingBP;
public ProviderDispatcher(IDiagramTypeProvider dtp) {
// create those first before using them
dispatchingFP = new DispatchingFeatureProvider(dtp);
dispatchingBP = new DispatchingToolBehaviorProvider(dtp);
stateGraphSupport = new StateGraphSupport(dtp, dispatchingFP);
trPointSupport = new TrPointSupport(dtp, dispatchingFP);
initialPointSupport = new InitialPointSupport(dtp, dispatchingFP);
choicePointSupport = new ChoicePointSupport(dtp, dispatchingFP);
stateSupport = new StateSupport(dtp, dispatchingFP);
transitionSupport = new TransitionSupport(dtp, dispatchingFP);
featureSwitch = new FeatureProviderSwitch();
behaviorSwitch = new ToolBehaviorProviderSwitch();
}
public IFeatureProvider getFeatureProvider() {
return dispatchingFP;
}
public IToolBehaviorProvider getToolBehaviorProvider() {
return dispatchingBP;
}
private ICreateFeature[] getAllCreateFeatures() {
return featureSwitch.getCreateFeatures();
}
private ICreateConnectionFeature[] getAllCreateConnectionFeatures() {
return featureSwitch.getCreateConnectionFeatures();
}
private ICustomFeature[] getAllCustomFeatures(ICustomContext context) {
return featureSwitch.getCustomFeatures(context);
}
private static <T> T[] concatAll(T[] first, T[]... rest) {
int totalLength = first.length;
for (T[] array : rest) {
totalLength += array.length;
}
T[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (T[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
}