/******************************************************************************* * <copyright> * * Copyright (c) 2005, 2013 SAP AG. * 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: * SAP AG - initial API, implementation and documentation * mwenz - Bug 342869 - Image doesn't scale the contained SWT Image on resize * mwenz - Bug 358255 - Add Border/Background decorators * Benjamin Schmeling - mwenz - Bug 367483 - Support composite connections * cbrand - Bug 378341 - Enlargement of the Line Width of Shapes isn't calculated based on the center. * mwenz - Bug 396793 - Text decorators * * </copyright> * *******************************************************************************/ package org.eclipse.graphiti.testtool.sketch; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.graphiti.dt.IDiagramTypeProvider; import org.eclipse.graphiti.features.IAddFeature; import org.eclipse.graphiti.features.ICopyFeature; import org.eclipse.graphiti.features.ICreateConnectionFeature; import org.eclipse.graphiti.features.ICreateFeature; import org.eclipse.graphiti.features.IDeleteFeature; import org.eclipse.graphiti.features.IDirectEditingFeature; import org.eclipse.graphiti.features.ILayoutFeature; import org.eclipse.graphiti.features.IMoveShapeFeature; import org.eclipse.graphiti.features.IPasteFeature; import org.eclipse.graphiti.features.IReconnectionFeature; import org.eclipse.graphiti.features.IResizeShapeFeature; import org.eclipse.graphiti.features.context.IAddContext; import org.eclipse.graphiti.features.context.ICopyContext; import org.eclipse.graphiti.features.context.ICustomContext; import org.eclipse.graphiti.features.context.IDeleteContext; import org.eclipse.graphiti.features.context.IDirectEditingContext; import org.eclipse.graphiti.features.context.ILayoutContext; import org.eclipse.graphiti.features.context.IMoveShapeContext; import org.eclipse.graphiti.features.context.IPasteContext; import org.eclipse.graphiti.features.context.IReconnectionContext; import org.eclipse.graphiti.features.context.IResizeShapeContext; import org.eclipse.graphiti.features.custom.ICustomFeature; import org.eclipse.graphiti.mm.algorithms.AbstractText; import org.eclipse.graphiti.mm.algorithms.Ellipse; import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; import org.eclipse.graphiti.mm.algorithms.Image; import org.eclipse.graphiti.mm.algorithms.MultiText; import org.eclipse.graphiti.mm.algorithms.Polygon; import org.eclipse.graphiti.mm.algorithms.Polyline; import org.eclipse.graphiti.mm.algorithms.Rectangle; import org.eclipse.graphiti.mm.algorithms.RoundedRectangle; import org.eclipse.graphiti.mm.algorithms.styles.LineStyle; import org.eclipse.graphiti.mm.algorithms.styles.Orientation; import org.eclipse.graphiti.mm.algorithms.styles.Style; 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.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import org.eclipse.graphiti.testtool.sketch.features.AddAnythingFeature; import org.eclipse.graphiti.testtool.sketch.features.AddDiagramFeature; import org.eclipse.graphiti.testtool.sketch.features.AddLinkFeature; import org.eclipse.graphiti.testtool.sketch.features.BackgroundColorFeature; import org.eclipse.graphiti.testtool.sketch.features.ChangeAlignmentFeature; import org.eclipse.graphiti.testtool.sketch.features.ClearDecoratorsFeature; import org.eclipse.graphiti.testtool.sketch.features.CornerDimensionFeature; import org.eclipse.graphiti.testtool.sketch.features.DisplayDecoratorFeature; import org.eclipse.graphiti.testtool.sketch.features.FontColorFeature; import org.eclipse.graphiti.testtool.sketch.features.ForegroundColorFeature; import org.eclipse.graphiti.testtool.sketch.features.GradientColorFeature; import org.eclipse.graphiti.testtool.sketch.features.LayoutContainerShapeGhostAndInnerShapeFeature; import org.eclipse.graphiti.testtool.sketch.features.LineStyleFeature; import org.eclipse.graphiti.testtool.sketch.features.LineWidthFeature; import org.eclipse.graphiti.testtool.sketch.features.ModifyControlPointsFeature; import org.eclipse.graphiti.testtool.sketch.features.SendToBackFeature; import org.eclipse.graphiti.testtool.sketch.features.SendToFrontFeature; import org.eclipse.graphiti.testtool.sketch.features.SetImageAttributesFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchDeleteFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchFontFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchGhostLayoutFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchLabelDirectEditingFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchLayoutFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchMoveShapeFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchReconnectionFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchResizeShapeFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchTextDirectEditingFeature; import org.eclipse.graphiti.testtool.sketch.features.SketchTextProposalDirectEditingFeature; import org.eclipse.graphiti.testtool.sketch.features.SwitchModeFeature; import org.eclipse.graphiti.testtool.sketch.features.ToggleDecorator; import org.eclipse.graphiti.testtool.sketch.features.TransparencyFeature; import org.eclipse.graphiti.testtool.sketch.features.bd.CreateChannelFeature; import org.eclipse.graphiti.testtool.sketch.features.create.CreateCsGhostAndInnerShapeFeature; import org.eclipse.graphiti.testtool.sketch.features.create.CreateHumanFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateCanFigureFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateCompositeConnectionFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateCurvedConnectionFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateFreeformConnectionFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateGaContainerFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateGaContainerFeatureWithGhost; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateGaShapeFeature; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateGaShapeFeatureWithGhost; import org.eclipse.graphiti.testtool.sketch.features.create.SketchCreateManhattanConnectionFeature; import org.eclipse.graphiti.testtool.sketch.features.pool.CreateLaneFeauture; import org.eclipse.graphiti.testtool.sketch.features.pool.CreatePoolFeature; import org.eclipse.graphiti.testtool.sketch.features.pool.LayoutPoolFeature; import org.eclipse.graphiti.testtool.sketch.features.style.CreateDefaultStylesFeature; import org.eclipse.graphiti.testtool.sketch.features.style.IgnoreAllFeature; import org.eclipse.graphiti.testtool.sketch.features.style.MakeStyleFeature; import org.eclipse.graphiti.testtool.sketch.features.style.SetStyleFeature; import org.eclipse.graphiti.testtool.sketch.features.style.UnsetStyleFeature; import org.eclipse.graphiti.ui.features.DefaultFeatureProvider; /** * The Class SketchFeatureProvider. */ public class SketchFeatureProvider extends DefaultFeatureProvider { public static final String CF_RECTANGLE_MULTI_TEXT = "Rectangle"; public static final String CF_RECTANGLE_SINGLE_TEXT = "Rectangle Single Text"; private static final String NO_MOVE = "no move"; private static final boolean TEST_RESIZE_SHAPE_FEATURE = false; private final int TRANSPARENCY_STEP_SIZE = 5; private final int LINE_WIDTH_STEP_SIZE = 1; private boolean testMode = false; // if true, then this feature provider is // used in the test suite private final Dimension CORNER_DIMENSION[] = new Dimension[] { new Dimension(0, 0), new Dimension(4, 4), new Dimension(8, 8), new Dimension(20, 20), new Dimension(21, 21), new Dimension(100, 100), new Dimension(101, 101), new Dimension(200, 200), new Dimension(100, 20), new Dimension(20, 100), }; /** * Instantiates a new sketch feature provider. * * @param dtp * the dtp */ public SketchFeatureProvider(IDiagramTypeProvider dtp) { super(dtp); } @Override public ICreateFeature[] getCreateFeatures() { List<ICreateFeature> features = new ArrayList<ICreateFeature>(); features.add(new CreateCsGhostAndInnerShapeFeature(this, "CS + Ghost + inner Shape", "create CS with Ghost and inner Shape")); features.add(createCreateGaContainerFeature("Rectangle Container", "draw rectangle", Rectangle.class)); features.add(createCreateGaContainerFeature("Rounded Rectangle Container", "draw rounded rectangle", RoundedRectangle.class)); features.add(createCreateGaContainerFeature("Ellipse Container", "draw ellipse", Ellipse.class)); features.add(createCreateGaContainerFeature("Triangle Container", "draw triangle", Polygon.class)); features.add(createCreateGaShapeFeature(CF_RECTANGLE_MULTI_TEXT, "draw rectangle", Rectangle.class)); features.add(createCreateGaShapeFeatureSingleText(CF_RECTANGLE_SINGLE_TEXT, "draw rectangle with a single line text", Rectangle.class)); features.add(createCreateGaShapeFeature("Rounded Rectangle", "draw rounded rectangle", RoundedRectangle.class)); features.add(createCreateGaShapeFeature("Ellipse", "draw ellipse", Ellipse.class)); features.add(createCreateGaShapeFeature("Triangle", "draw triangle", Polygon.class)); features.add(createCreateGaShapeFeature("Arrow", "draw Arrow outline", Polygon.class)); features.add(createCreateGaShapeFeature("Line", "draw line", Polyline.class)); features.add(createCreateGaShapeFeature("Image", "draw image", Image.class)); features.add(createCreateGaShapeFeatureWithGhost("Rectangle Ghost", "rectangle with ghost", Rectangle.class)); features.add(createCreateGaShapeFeatureWithGhost("Rounded Rectangle Ghost", "rounded rectangle with ghost", RoundedRectangle.class)); features.add(createCreateGaShapeFeatureWithGhost("Ellipse Ghost", "ellipse with ghost", Ellipse.class)); features.add(createCreateGaContainerFeatureWithGhost("Rectangle Container Ghost", "rectangle container with ghost", Rectangle.class)); features.add(createCreateGaContainerFeatureWithGhost("Rounded Container Rectangle Ghost", "rounded rectangle container with ghost", RoundedRectangle.class)); features.add(createCreateGaContainerFeatureWithGhost("Ellipse Container Ghost", "ellipse container with ghost", Ellipse.class)); features.add(new CreatePoolFeature(this, "Pool", "create a pool")); features.add(new SketchCreateCanFigureFeature(this, "Can figure", "example for a platform ga")); features.add(new CreateHumanFeature(this, "Human", "create ghost with human")); return features.toArray(new ICreateFeature[0]); } @Override public ICustomFeature[] getCustomFeatures(ICustomContext context) { List<ICustomFeature> retList = new ArrayList<ICustomFeature>(); boolean isCp = SketchUtil.isConnectionPoint(context.getPictogramElements()[0]); if (isCp) { return retList.toArray(new ICustomFeature[0]); } for (int i = 0; i <= 10; i += LINE_WIDTH_STEP_SIZE) { retList.add(new LineWidthFeature(this, i)); } retList.add(new LineStyleFeature(this, LineStyle.SOLID)); retList.add(new LineStyleFeature(this, LineStyle.DASH)); retList.add(new LineStyleFeature(this, LineStyle.DASHDOT)); retList.add(new LineStyleFeature(this, LineStyle.DASHDOTDOT)); retList.add(new LineStyleFeature(this, LineStyle.DOT)); for (int i = 0; i < CORNER_DIMENSION.length; i++) { retList.add(new CornerDimensionFeature(this, CORNER_DIMENSION[i])); } retList.add(new SendToFrontFeature(this)); retList.add(new SendToBackFeature(this)); retList.add(new ForegroundColorFeature(this)); retList.add(new BackgroundColorFeature(this)); retList.add(new GradientColorFeature(this)); retList.add(new FontColorFeature(this)); retList.add(new SketchFontFeature(this)); retList.add(new CreateLaneFeauture(this)); retList.add(new ChangeAlignmentFeature(this, "Left", Orientation.ALIGNMENT_LEFT, null)); retList.add(new ChangeAlignmentFeature(this, "Center", Orientation.ALIGNMENT_CENTER, null)); retList.add(new ChangeAlignmentFeature(this, "Right", Orientation.ALIGNMENT_RIGHT, null)); retList.add(new ChangeAlignmentFeature(this, "Top", null, Orientation.ALIGNMENT_TOP)); retList.add(new ChangeAlignmentFeature(this, "Middle", null, Orientation.ALIGNMENT_CENTER)); retList.add(new ChangeAlignmentFeature(this, "Bottom", null, Orientation.ALIGNMENT_BOTTOM)); retList.add(new ChangeAlignmentFeature(this, "Top Left", Orientation.ALIGNMENT_LEFT, Orientation.ALIGNMENT_TOP)); retList.add(new ChangeAlignmentFeature(this, "Top Right", Orientation.ALIGNMENT_RIGHT, Orientation.ALIGNMENT_TOP)); retList.add(new ChangeAlignmentFeature(this, "Middle Center", Orientation.ALIGNMENT_CENTER, Orientation.ALIGNMENT_CENTER)); retList.add(new ChangeAlignmentFeature(this, "Bottom Left", Orientation.ALIGNMENT_LEFT, Orientation.ALIGNMENT_BOTTOM)); retList.add(new ChangeAlignmentFeature(this, "Bottom Right", Orientation.ALIGNMENT_RIGHT, Orientation.ALIGNMENT_BOTTOM)); for (int i = 0; i < 100; i += TRANSPARENCY_STEP_SIZE) { retList.add(new TransparencyFeature(this, i)); } retList.add(new TransparencyFeature(this, 100)); retList.add(new ToggleDecorator(this)); retList.add(new CreateDefaultStylesFeature(this)); retList.add(new MakeStyleFeature(this)); Collection<Style> styles = getDiagramTypeProvider().getDiagram().getStyles(); for (Style style : styles) { createSetStyleFeatures(style, retList); } retList.add(new UnsetStyleFeature(this)); retList.add(new IgnoreAllFeature(this)); retList.add(new SwitchModeFeature(this)); retList.add(new ModifyControlPointsFeature(this)); retList.add(new SetImageAttributesFeature(this, context, SetImageAttributesFeature.ATTRIBUTE_STRETCH_HORIZONTALLY)); retList.add(new SetImageAttributesFeature(this, context, SetImageAttributesFeature.ATTRIBUTE_STRETCH_VERTICALLY)); retList.add(new SetImageAttributesFeature(this, context, SetImageAttributesFeature.ATTRIBUTE_PROPORTIONAL)); retList.add(new DisplayDecoratorFeature(this, context, DisplayDecoratorFeature.TYPE_IMAGE)); retList.add(new DisplayDecoratorFeature(this, context, DisplayDecoratorFeature.TYPE_BORDER)); retList.add(new DisplayDecoratorFeature(this, context, DisplayDecoratorFeature.TYPE_COLOR)); retList.add(new DisplayDecoratorFeature(this, context, DisplayDecoratorFeature.TYPE_TEXT)); retList.add(new ClearDecoratorsFeature(this, context)); return retList.toArray(new ICustomFeature[0]); } private void createSetStyleFeatures(Style parentStyle, List<ICustomFeature> retList) { retList.add(new SetStyleFeature(parentStyle, this)); Collection<Style> styles = parentStyle.getStyles(); for (Style style : styles) { createSetStyleFeatures(style, retList); } } @Override public ICreateConnectionFeature[] getCreateConnectionFeatures() { List<ICreateConnectionFeature> retList = new ArrayList<ICreateConnectionFeature>(); retList.add(new SketchCreateFreeformConnectionFeature(this, "free", "freeform connection")); retList.add(new SketchCreateManhattanConnectionFeature(this, "manhattan", "manhattan connection")); retList.add(new SketchCreateCurvedConnectionFeature(this, "curved", "curved connection")); retList.add(new SketchCreateCompositeConnectionFeature(this, "composite", "composite connection")); retList.add(new CreateChannelFeature(this, "channel", "channel connection")); return retList.toArray(new ICreateConnectionFeature[0]); } private ICreateFeature createCreateGaContainerFeature(String name, String description, Class<? extends GraphicsAlgorithm> gaType) { ICreateFeature createFeature = new SketchCreateGaContainerFeature(this, name, description, gaType); return createFeature; } private ICreateFeature createCreateGaShapeFeature(String name, String description, Class<? extends GraphicsAlgorithm> gaType) { ICreateFeature createFeature = new SketchCreateGaShapeFeature(this, name, description, gaType); return createFeature; } private ICreateFeature createCreateGaShapeFeatureSingleText(String name, String description, Class<? extends GraphicsAlgorithm> gaType) { ICreateFeature createFeature = new SketchCreateGaShapeFeature(this, name, description, gaType, false); return createFeature; } private ICreateFeature createCreateGaShapeFeatureWithGhost(String name, String description, Class<? extends GraphicsAlgorithm> gaType) { // breaks the build: ICreateFeature createFeature = new // SketchCreateGaShapeFeatureWithGhost(this, name, description, // gaType); ICreateFeature createFeature = new SketchCreateGaShapeFeatureWithGhost(this, name, description, gaType); return createFeature; } private ICreateFeature createCreateGaContainerFeatureWithGhost(String name, String description, Class<? extends GraphicsAlgorithm> gaType) { // breaks the build: ICreateFeature createFeature = new // SketchCreateGaShapeFeatureWithGhost(this, name, description, // gaType); ICreateFeature createFeature = new SketchCreateGaContainerFeatureWithGhost(this, name, description, gaType); return createFeature; } @Override public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) { Shape shape = context.getShape(); if (shape != null) { GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); if (checkNoMove(ga)) { return null; } } return new SketchMoveShapeFeature(this); } private boolean checkNoMove(GraphicsAlgorithm ga) { if (ga instanceof AbstractText) { AbstractText at = (AbstractText) ga; if (NO_MOVE.equalsIgnoreCase(at.getValue())) { return true; } } else { List<GraphicsAlgorithm> gaChildren = ga.getGraphicsAlgorithmChildren(); for (GraphicsAlgorithm child : gaChildren) { if (checkNoMove(child)) { return true; } } } return false; } @Override public IAddFeature getAddFeature(IAddContext context) { IAddFeature ret = super.getAddFeature(context); Object newObject = context.getNewObject(); if (newObject instanceof Diagram) { ret = new AddDiagramFeature(this); } else if (!(context.getTargetContainer() instanceof Diagram) && !(newObject instanceof PictogramElement)) { // works only container shapes, because drop is only allowed on // container shapes ret = new AddLinkFeature(this); } else { return new AddAnythingFeature(this); } return ret; } @Override public ILayoutFeature getLayoutFeature(ILayoutContext context) { PictogramElement pe = context.getPictogramElement(); if (SketchUtil.getLabelGa(pe) != null) { return new SketchLayoutFeature(this); } else if (SketchUtil.getGhostGa(pe) != null) { return new SketchGhostLayoutFeature(this); } else if (SketchUtil.isPoolPe(pe)) { return new LayoutPoolFeature(this); } else { boolean check = context.getPictogramElement() instanceof ContainerShape; if (check) { ContainerShape cs = (ContainerShape) pe; List<Shape> children = cs.getChildren(); if (!children.isEmpty()) { Shape firstChild = children.get(0); if (firstChild != null) { GraphicsAlgorithm ga = firstChild.getGraphicsAlgorithm(); check = check && ga instanceof Ellipse; if (check) { return new LayoutContainerShapeGhostAndInnerShapeFeature(this); } } } } } return super.getLayoutFeature(context); } @Override public IDirectEditingFeature getDirectEditingFeature(IDirectEditingContext context) { IDirectEditingFeature ret = null; PictogramElement pe = context.getPictogramElement(); AbstractText labelGa = SketchUtil.getLabelGa(pe); if (labelGa != null) { if (labelGa instanceof MultiText) { ret = new SketchLabelDirectEditingFeature(this); } else { if (labelGa.getValue().startsWith("p")) { //$NON-NLS-1$ ret = new SketchTextProposalDirectEditingFeature(this); } else { ret = new SketchTextDirectEditingFeature(this); } } } return ret; } @Override public IResizeShapeFeature getResizeShapeFeature(IResizeShapeContext context) { final PictogramElement pe = context.getPictogramElement(); if (SketchUtil.isConnectionPoint(pe)) { return null; } if (pe instanceof ConnectionDecorator) { return null; } if (pe.getGraphicsAlgorithm() instanceof Polyline) { return null; } if (TEST_RESIZE_SHAPE_FEATURE) { return new SketchResizeShapeFeature(this); } else { return super.getResizeShapeFeature(context); } } @Override public ICopyFeature getCopyFeature(ICopyContext context) { // return new DefaultCopyFeature(this); return null; } @Override public IPasteFeature getPasteFeature(IPasteContext context) { // return new DefaultPasteFeature(this); return null; } @Override public IDeleteFeature getDeleteFeature(IDeleteContext context) { IDeleteFeature ret = null; ret = new SketchDeleteFeature(this); return ret; } public void setTestMode(boolean testMode) { this.testMode = testMode; } public boolean isTestMode() { return testMode; } @Override public IReconnectionFeature getReconnectionFeature(IReconnectionContext context) { return new SketchReconnectionFeature(this); } }