| /******************************************************************************* |
| * <copyright> |
| * |
| * Copyright (c) 2005, 2014 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 |
| * Volker Wegert - Bug 336828: patterns should support delete, |
| * remove, direct editing and conditional palette |
| * creation entry |
| * mwenz - Bug 325084 - Provide documentation for Patterns |
| * cbrand - Bug 376585 - Clean-up deprecations in Graphiti |
| * cbrand - Bug 385190 - Introduce constructor without parameters for patterns |
| * mwenz - Bug 390331 - preDelete and postDelete not called for Patterns |
| * mwenz - Bug 453553 - Provide an abort possibility for delete and remove features in case 'pre' methods fail |
| * |
| * </copyright> |
| * |
| *******************************************************************************/ |
| package org.eclipse.graphiti.pattern; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.eclipse.graphiti.features.DefaultResizeConfiguration; |
| import org.eclipse.graphiti.features.IDeleteFeature; |
| import org.eclipse.graphiti.features.IDirectEditingInfo; |
| import org.eclipse.graphiti.features.IReason; |
| import org.eclipse.graphiti.features.IRemoveFeature; |
| import org.eclipse.graphiti.features.IResizeConfiguration; |
| import org.eclipse.graphiti.features.context.IAreaContext; |
| import org.eclipse.graphiti.features.context.ICreateContext; |
| 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.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.LayoutContext; |
| import org.eclipse.graphiti.features.context.impl.UpdateContext; |
| import org.eclipse.graphiti.features.impl.AbstractCreateFeature; |
| import org.eclipse.graphiti.features.impl.AbstractDirectEditingFeature; |
| 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.DefaultRemoveFeature; |
| import org.eclipse.graphiti.features.impl.DefaultResizeShapeFeature; |
| import org.eclipse.graphiti.features.impl.Reason; |
| import org.eclipse.graphiti.func.IDelete; |
| import org.eclipse.graphiti.func.IDirectEditing; |
| import org.eclipse.graphiti.func.IProposalSupport; |
| import org.eclipse.graphiti.func.IRemove; |
| import org.eclipse.graphiti.mm.algorithms.styles.Point; |
| 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.FreeFormConnection; |
| import org.eclipse.graphiti.mm.pictograms.PictogramElement; |
| import org.eclipse.graphiti.mm.pictograms.Shape; |
| import org.eclipse.graphiti.pattern.config.IPatternConfiguration; |
| import org.eclipse.graphiti.services.Graphiti; |
| import org.eclipse.graphiti.ui.features.DefaultDeleteFeature; |
| |
| /** |
| * This is the base class AbstractConnectionPattern that clients writing a |
| * pattern for a shape domain object should subclass. |
| */ |
| public abstract class AbstractPattern extends AbstractBasePattern implements IPattern { |
| |
| /** |
| * An empty string array used in direct editing. |
| */ |
| protected static final String[] EMPTY_STRING_ARRAY = new String[0]; |
| |
| private IPatternConfiguration patternConfiguration; |
| |
| /** |
| * To avoid code duplication, this base class uses a wrapped default |
| * implementation of an {@link IDeleteFeature} to provide the default |
| * deletion behaviour. Subclasses may decide to either override |
| * {@link #createDeleteFeature(IDeleteContext)} to provide another |
| * {@link IDeleteFeature} implementation or override and extend the |
| * individual {@link IDelete} methods or return a {@link IDeleteFeature} by |
| * overriding the method |
| * {@link DefaultFeatureProviderWithPatterns#getDeleteFeature(IDeleteContext)} |
| * . |
| */ |
| private IDeleteFeature wrappedDeleteFeature; |
| |
| /** |
| * To avoid code duplication, this base class uses a wrapped default |
| * implementation of an {@link IRemoveFeature} to provide the default |
| * removal behavior. Subclasses may decide to either override |
| * {@link #createRemoveFeature(IRemoveContext)} to provide another |
| * {@link IRemoveFeature} implementation or override and extend the |
| * individual {@link IRemove} methods or return a {@link IRemoveFeature} by |
| * overriding the method |
| * {@link DefaultFeatureProviderWithPatterns#getRemoveFeature(IRemoveContext)} |
| * . |
| */ |
| private IRemoveFeature wrappedRemoveFeature; |
| |
| /** |
| * Creates a new {@link AbstractPattern} holding the given |
| * {@link IPatternConfiguration}. |
| * |
| * @param patternConfiguration |
| * The pattern configuration to use within this pattern instance |
| * of <code>null</code> in case no configuration is needed. |
| */ |
| public AbstractPattern(IPatternConfiguration patternConfiguration) { |
| this(); |
| setPatternConfiguration(patternConfiguration); |
| } |
| |
| /** |
| * Creates a new {@link AbstractPattern}. This is a convenience method for |
| * patterns working without any configuration. |
| * |
| * @since 0.10 |
| */ |
| public AbstractPattern() { |
| super(); |
| } |
| |
| /** |
| * Is queried by the Graphiti framework to check if the pattern should |
| * create a new domain object entry in the editor palette. |
| * |
| * @return <code>true</code> in case a palette entry shall be created, |
| * <code>false</code> otherwise. |
| */ |
| public boolean isPaletteApplicable() { |
| return true; |
| } |
| |
| /** |
| * Clients must override this method to indicate that the pattern can be |
| * used to create domain objects as defined in the given |
| * {@link ICreateContext}. Corresponds to the method |
| * {@link AbstractCreateFeature#canCreate(ICreateContext)} . The default |
| * implementation simply returns <code>false</code>. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * created. |
| * @return <code>true</code> in case this pattern can create such a domain |
| * object, <code>false</code> otherwise. |
| */ |
| public boolean canCreate(ICreateContext context) { |
| return false; |
| } |
| |
| /** |
| * Clients may override this method to indicate that the pattern can be used |
| * to layout a shape for a domain objects as defined in the given |
| * {@link ILayoutContext}. Corresponds to the method |
| * {@link AbstractLayoutFeature#canLayout(ILayoutContext)}. The default |
| * implementation checks if the {@link PictogramElement} in the given |
| * context {@link #isPatternControlled(PictogramElement)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * layouted. |
| * @return <code>true</code> in case this pattern can layout a shape for |
| * such a domain object, <code>false</code> otherwise. |
| */ |
| public boolean canLayout(ILayoutContext context) { |
| PictogramElement pictogramElement = context.getPictogramElement(); |
| return isPatternControlled(pictogramElement); |
| } |
| |
| /** |
| * Clients may override this method to indicate that the pattern can be used |
| * to move the shape of a domain objects as defined in the given |
| * {@link IMoveShapeContext}. Corresponds to the method |
| * {@link DefaultMoveShapeFeature#canMoveShape(IMoveShapeContext)}. The |
| * default implementation checks if the {@link PictogramElement} in the |
| * given context {@link #isPatternControlled(PictogramElement)} and the |
| * source and target containers of the shape are the same. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * moved. |
| * @return <code>true</code> in case this pattern can move a shape for such |
| * a domain object, <code>false</code> otherwise. |
| */ |
| public boolean canMoveShape(IMoveShapeContext context) { |
| return context.getSourceContainer() != null |
| && context.getSourceContainer().equals(context.getTargetContainer()) |
| && isPatternRoot(context.getPictogramElement()); |
| } |
| |
| /** |
| * Clients may override this method to indicate that the pattern can be used |
| * to resize the shape of a domain objects as defined in the given |
| * {@link IResizeShapeContext}. Corresponds to the method |
| * {@link DefaultResizeShapeFeature#canResizeShape(IResizeShapeContext)}. |
| * The default implementation checks if the {@link PictogramElement} in the |
| * given context fulfills {@link #isPatternRoot(PictogramElement)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * resized. |
| * @return <code>true</code> in case this pattern can resize a shape for |
| * such a domain object, <code>false</code> otherwise. |
| */ |
| public boolean canResizeShape(IResizeShapeContext context) { |
| return isPatternRoot(context.getPictogramElement()); |
| } |
| |
| /** |
| * Clients may override this method to indicate that the pattern can be used |
| * to update the shape of a domain objects as defined in the given |
| * {@link IUpdateContext}. Corresponds to the method |
| * {@link AbstractUpdateFeature#canUpdate(IUpdateContext)}. The default |
| * implementation checks if the {@link PictogramElement} in the given |
| * context {@link #isPatternControlled(PictogramElement)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * updated. |
| * @return <code>true</code> in case this pattern can update a shape for |
| * such a domain object, <code>false</code> otherwise. |
| */ |
| public boolean canUpdate(IUpdateContext context) { |
| PictogramElement pictogramElement = context.getPictogramElement(); |
| return isPatternControlled(pictogramElement); |
| } |
| |
| /** |
| * Clients must override this method to implement the functionality to |
| * create a new domain object as defined in the given {@link ICreateContext} |
| * . Corresponds to the method |
| * {@link AbstractCreateFeature#create(ICreateContext)}. The default |
| * implementation simply does nothing and returns an empty object array. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * created. |
| * @return An array of the newly create domain objects. |
| */ |
| public Object[] create(ICreateContext context) { |
| return EMPTY; |
| } |
| |
| /** |
| * Client should override to return a string description of the type of |
| * domain object that is created with this pattern. The Graphiti framework |
| * uses this information to fill a tooltip for the creation tool entry in |
| * the palette. The default implementation simply returns <code>null</code> |
| * which indicates that no tooltip shall be displayed. |
| * |
| * @return A {@link String} holding the tooltip |
| */ |
| public String getCreateDescription() { |
| return null; |
| } |
| |
| /** |
| * Client should override to return a string id of the the image icon for |
| * the domain object that is created with this pattern. The Graphiti |
| * framework uses this information to add an icon to the creation tool entry |
| * in the palette. The default implementation simply returns |
| * <code>null</code> which indicates that no icon shall be displayed. |
| * |
| * @return A {@link String} holding the id of the icon as defined in the |
| * AbstractImageProvider. |
| */ |
| public String getCreateImageId() { |
| return null; |
| } |
| |
| /** |
| * Client should override to return a string id of the the large image icon |
| * for the domain object that is created with this pattern. The Graphiti |
| * framework uses this information to add a large icon to the creation tool |
| * entry in the palette. The default implementation simply returns |
| * <code>null</code> which indicates that no icon shall be displayed. |
| * |
| * @return A {@link String} holding the id of the large icon as defined in |
| * the AbstractImageProvider. |
| */ |
| public String getCreateLargeImageId() { |
| return getCreateImageId(); |
| } |
| |
| /** |
| * Client should override to return the name of the domain object that is |
| * created with this pattern. The Graphiti framework uses this information |
| * to fill the text for the creation tool entry in the palette. The default |
| * implementation simply returns <code>null</code> which results in an empty |
| * entry in the palette. |
| * |
| * @return A {@link String} holding the name of the domain object. |
| */ |
| public String getCreateName() { |
| return null; |
| } |
| |
| /** |
| * Clients must override this method to indicate that the pattern uses the |
| * given domain object as its main domain object. |
| * |
| * @param mainBusinessObject |
| * The object to check if it is the main domain object of the |
| * pattern. |
| * @return <code>true</code> in case the pattern has the given domain object |
| * as its main domain object, <code>false</code> otherwise. |
| */ |
| abstract public boolean isMainBusinessObjectApplicable(Object mainBusinessObject); |
| |
| /** |
| * Clients can override this method to implement the functionality to layout |
| * a shape for the given domain object as defined in the given |
| * {@link ILayoutContext} . Corresponds to the method |
| * {@link AbstractLayoutFeature#layout(ILayoutContext)}. The default |
| * implementation simply does nothing and returns <code>false</code> as |
| * indication of this. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * layouted. |
| * @return Should return <code>true</code> in case a layout happened and |
| * <code>false</code> in case none happened. Is used by the Graphiti |
| * framework for performance optimization. |
| */ |
| public boolean layout(ILayoutContext context) { |
| return false; |
| } |
| |
| /** |
| * Clients can override this method to implement the functionality to move a |
| * shape for the given domain object as defined in the given |
| * {@link IMoveShapeContext} . Corresponds to the method |
| * {@link DefaultMoveShapeFeature#moveShape(IMoveShapeContext)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * moved. |
| */ |
| public void moveShape(IMoveShapeContext context) { |
| preMoveShape(context); |
| moveAllBendpoints(context); |
| internalMove(context); |
| postMoveShape(context); |
| } |
| |
| /** |
| * Hook clients can override to add additional steps after the move of the |
| * shape happened. |
| * |
| * @param context |
| * The context holding information on the domain object that was |
| * moved. |
| */ |
| protected void postMoveShape(IMoveShapeContext context) { |
| } |
| |
| /** |
| * Hook clients can override to add additional steps before the move of the |
| * shape happens. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * moved. |
| */ |
| protected void preMoveShape(IMoveShapeContext context) { |
| } |
| |
| /** |
| * Default implementation of the move functionality. Moves shapes to new |
| * coordinates and adapts parents in case this is needed. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * moved. |
| */ |
| protected void internalMove(IMoveShapeContext context) { |
| Shape shapeToMove = context.getShape(); |
| ContainerShape oldContainerShape = context.getSourceContainer(); |
| ContainerShape newContainerShape = context.getTargetContainer(); |
| |
| int x = context.getX(); |
| int y = context.getY(); |
| |
| if (oldContainerShape != newContainerShape) { |
| // the following is a workaround due to an MMR bug |
| if (oldContainerShape != null) { |
| Collection<Shape> children = oldContainerShape.getChildren(); |
| if (children != null) { |
| children.remove(shapeToMove); |
| } |
| } |
| |
| shapeToMove.setContainer(newContainerShape); |
| if (shapeToMove.getGraphicsAlgorithm() != null) { |
| Graphiti.getGaService().setLocation(shapeToMove.getGraphicsAlgorithm(), x, y, |
| avoidNegativeCoordinates()); |
| } |
| } else { // move within the same container |
| if (shapeToMove.getGraphicsAlgorithm() != null) { |
| Graphiti.getGaService().setLocation(shapeToMove.getGraphicsAlgorithm(), x, y, |
| avoidNegativeCoordinates()); |
| } |
| } |
| } |
| |
| /** |
| * Default implementation of the move functionality to move all bendpoints |
| * within a container shape. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * moved. |
| */ |
| protected void moveAllBendpoints(IMoveShapeContext context) { |
| |
| if (!(context.getShape() instanceof ContainerShape)) { |
| return; |
| } |
| |
| ContainerShape shapeToMove = (ContainerShape) context.getShape(); |
| |
| int x = context.getX(); |
| int y = context.getY(); |
| |
| int deltaX = x - shapeToMove.getGraphicsAlgorithm().getX(); |
| int deltaY = y - shapeToMove.getGraphicsAlgorithm().getY(); |
| |
| if (deltaX != 0 || deltaY != 0) { |
| |
| List<Anchor> anchorsFrom = getAnchors(shapeToMove); |
| List<Anchor> anchorsTo = new ArrayList<Anchor>(anchorsFrom); |
| |
| for (Anchor anchorFrom : anchorsFrom) { |
| |
| Collection<Connection> outgoingConnections = anchorFrom.getOutgoingConnections(); |
| |
| for (Connection connection : outgoingConnections) { |
| for (Anchor anchorTo : anchorsTo) { |
| |
| Collection<Connection> incomingConnections = anchorTo.getIncomingConnections(); |
| if (incomingConnections.contains(connection)) { |
| if (connection instanceof FreeFormConnection) { |
| FreeFormConnection ffc = (FreeFormConnection) connection; |
| List<Point> points = ffc.getBendpoints(); |
| for (int i = 0; i < points.size(); i++) { |
| Point point = points.get(i); |
| int oldX = point.getX(); |
| int oldY = point.getY(); |
| points.set(i, Graphiti.getGaService().createPoint(oldX + deltaX, oldY + deltaY)); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private List<Anchor> getAnchors(ContainerShape containerShape) { |
| List<Anchor> ret = new ArrayList<Anchor>(); |
| ret.addAll(containerShape.getAnchors()); |
| |
| List<Shape> children = containerShape.getChildren(); |
| for (Shape shape : children) { |
| if (shape instanceof ContainerShape) { |
| ret.addAll(getAnchors((ContainerShape) shape)); |
| } else { |
| ret.addAll(shape.getAnchors()); |
| } |
| } |
| return ret; |
| } |
| |
| /** |
| * Clients can override this method to implement the functionality to resize |
| * a shape for the given domain object as defined in the given |
| * {@link IResizeShapeContext} . Corresponds to the method |
| * {@link DefaultResizeShapeFeature#resizeShape(IResizeShapeContext)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * resized. |
| */ |
| public void resizeShape(IResizeShapeContext context) { |
| Shape shape = context.getShape(); |
| int x = context.getX(); |
| int y = context.getY(); |
| int width = context.getWidth(); |
| int height = context.getHeight(); |
| |
| if (shape.getGraphicsAlgorithm() != null) { |
| Graphiti.getGaService().setLocationAndSize(shape.getGraphicsAlgorithm(), x, y, width, height); |
| } |
| |
| layoutPictogramElement(shape); |
| } |
| |
| /** |
| * Clients can override this method to implement the functionality to update |
| * a shape for the given domain object as defined in the given |
| * {@link IUpdateContext}. Corresponds to the method |
| * {@link AbstractUpdateFeature#update(IUpdateContext)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * updated. |
| */ |
| public boolean update(IUpdateContext context) { |
| return false; |
| } |
| |
| /** |
| * Clients can override this method to indicate if an update of a shape for |
| * the given domain object as defined in the given {@link IUpdateContext} |
| * needs to be triggered. Corresponds to the method |
| * {@link AbstractUpdateFeature#updateNeeded(IUpdateContext)}. |
| * |
| * @param context |
| * The context holding information on the domain object to be |
| * updated. |
| */ |
| public IReason updateNeeded(IUpdateContext context) { |
| return Reason.createFalseReason(); |
| } |
| |
| /** |
| * Adds the graphical representation of the given new {@link Object} with |
| * the information in the given {@link IAreaContext}. |
| * |
| * @param context |
| * The area context defining where the new object should placed |
| * @param newObject |
| * The new object instance itself |
| */ |
| protected void addGraphicalRepresentation(IAreaContext context, Object newObject) { |
| getFeatureProvider().addIfPossible(new AddContext(context, newObject)); |
| } |
| |
| /** |
| * Clients can override to indicate that moving to negative coordinates |
| * should be possible. The default implementation prohibits this by |
| * returning false. |
| * |
| * @return <code>true</code> in case moving a shape to negative coordinates |
| * should be possible, <code>false</code> otherwise. |
| */ |
| protected boolean avoidNegativeCoordinates() { |
| return false; |
| } |
| |
| /** |
| * This method must be implemented by clients to indicate that the given |
| * {@link PictogramElement} is controlled by this pattern. |
| * |
| * @param pictogramElement |
| * The pictogram element to check |
| * @return <code>true</code> in case the pictogram element is controlled by |
| * this pattern, <code>false</code> otherwise. |
| */ |
| abstract protected boolean isPatternControlled(PictogramElement pictogramElement); |
| |
| /** |
| * This method must be implemented by clients to indicate that the given |
| * {@link PictogramElement} is the root shape of this pattern. |
| * |
| * @param pictogramElement |
| * The pictogram element to check |
| * @return <code>true</code> in case the pictogram element is the root shape |
| * of this pattern, <code>false</code> otherwise. |
| */ |
| abstract protected boolean isPatternRoot(PictogramElement pictogramElement); |
| |
| /** |
| * Helper method that triggers a layout of the given |
| * {@link PictogramElement}. The default implementation queries the feature |
| * provider and tries to find a functionality either in the pattern of an |
| * additional {@link AbstractLayoutFeature} that can handle the request and |
| * triggers the operation. |
| * |
| * @param pe |
| * The pictogram element to layout |
| */ |
| protected void layoutPictogramElement(PictogramElement pe) { |
| LayoutContext context = new LayoutContext(pe); |
| getFeatureProvider().layoutIfPossible(context); |
| } |
| |
| /** |
| * Helper method that triggers an update of the given |
| * {@link PictogramElement}. The default implementation queries the feature |
| * provider and tries to find a functionality either in the pattern of an |
| * additional {@link AbstractUpdateFeature} that can handle the request and |
| * triggers the operation. |
| * |
| * @param pe |
| * The pictogram element to update |
| */ |
| protected void updatePictogramElement(PictogramElement pe) { |
| UpdateContext context = new UpdateContext(pe); |
| getFeatureProvider().updateIfPossible(context); |
| layoutPictogramElement(pe); |
| } |
| |
| /** |
| * Sets the {@link IPatternConfiguration} instance to be used with this |
| * pattern. |
| * |
| * @param patternConfiguration |
| * The new patternConfiguration |
| */ |
| protected void setPatternConfiguration(IPatternConfiguration patternConfiguration) { |
| this.patternConfiguration = patternConfiguration; |
| } |
| |
| /** |
| * Returns the {@link IPatternConfiguration} instance used within this |
| * pattern or <code>null</code> in case none is used. |
| * |
| * @return The patternConfiguration instance or <code>null</code> it there |
| * is none set |
| */ |
| protected IPatternConfiguration getPatternConfiguration() { |
| return patternConfiguration; |
| } |
| |
| /** |
| * Clients can override to complete the {@link IDirectEditingInfo} info. |
| * This information is needed to switch automatically into the direct |
| * editing mode. (e.g. after creation of a new object). |
| * |
| * @param info |
| * The direct editing info |
| * @param bo |
| * The domain object |
| */ |
| public void completeInfo(IDirectEditingInfo info, Object bo) { |
| } |
| |
| /** |
| * Clients can override to complete the {@link IDirectEditingInfo} info. |
| * This information is needed to switch automatically into the direct |
| * editing mode. (e.g. after creation of a new object) |
| * |
| * @param info |
| * The direct editing info |
| * @param bo |
| * The domain object |
| * @param keyProperty |
| * The key property |
| */ |
| public void completeInfo(IDirectEditingInfo info, Object bo, String keyProperty) { |
| } |
| |
| /** |
| * Clients may override to modify the resize behavior. The default |
| * implementation returns a new instance of |
| * {@link DefaultResizeConfiguration}, which allows bothe the horizontal and |
| * vertical resize of a shape. |
| * |
| * @param context |
| * Context object holding information about the shape to be |
| * resized. |
| * @return An instance of {@link IResizeConfiguration} defining the resize |
| * behavior. |
| */ |
| public IResizeConfiguration getResizeConfiguration(IResizeShapeContext context) { |
| return new DefaultResizeConfiguration(); |
| } |
| |
| /** |
| * Creates the {@link IDeleteFeature} instance that handles the deletion of |
| * business objects and diagram elements. The default implementation just |
| * creates an adapted {@link DefaultDeleteFeature}. Concrete pattern |
| * implementations may either override this method to provide their own |
| * subclass of {@link DefaultDeleteFeature} or override and extend the |
| * individual methods provided by {@link IDelete}. |
| * <p> |
| * The difference of the delete feature returned here to the standard |
| * {@link DefaultDeleteFeature} is simply that the instance returned here |
| * cares about the delegation to the pattern's |
| * {@link #preDelete(IDeleteContext)}, {@link #isDeleteAbort()} and |
| * {@link #postDelete(IDeleteContext)} methods. Clients overriding this |
| * method should re-implement that pattern, in case the delegation is |
| * desired. |
| * |
| * @param context |
| * the deletion context |
| * @return the {@link IDeleteFeature} instance to use for this pattern |
| * @see #canDelete(IDeleteContext) |
| * @see #preDelete(IDeleteContext) |
| * @see #isDeleteAbort() |
| * @see #delete(IDeleteContext) |
| * @see #postDelete(IDeleteContext) |
| */ |
| protected IDeleteFeature createDeleteFeature(IDeleteContext context) { |
| return new DefaultDeleteFeature(getFeatureProvider()) { |
| @Override |
| public void preDelete(IDeleteContext context) { |
| super.preDelete(context); |
| AbstractPattern.this.preDelete(context); |
| } |
| |
| @Override |
| public boolean isDeleteAbort() { |
| return AbstractPattern.this.isDeleteAbort(); |
| } |
| |
| @Override |
| public void postDelete(IDeleteContext context) { |
| AbstractPattern.this.postDelete(context); |
| super.postDelete(context); |
| } |
| }; |
| } |
| |
| /** |
| * Clients can override to modify the default behavior if the pattern can |
| * (and wants to) handle a delete request. The default implementation calls |
| * {@link #createDeleteFeature(IDeleteContext)} and asks the result's |
| * canDelete method. |
| * |
| * @param context |
| * The context describing the delete request |
| * |
| * @return <code>true</code>, if the pattern can perform the delete |
| * operation, <code>false</code> otherwise |
| */ |
| public boolean canDelete(IDeleteContext context) { |
| if (wrappedDeleteFeature == null) { |
| wrappedDeleteFeature = createDeleteFeature(context); |
| } |
| return ((wrappedDeleteFeature != null) && wrappedDeleteFeature.canDelete(context)); |
| } |
| |
| /** |
| * Clients can override to add actions before the default delete behavior is |
| * triggered. The default implementation does nothing and is called from the |
| * registered delete feature. |
| * |
| * @param context |
| * The context describing the delete request |
| */ |
| public void preDelete(IDeleteContext context) { |
| } |
| |
| /** |
| * Clients can override to modify the default delete behavior. The default |
| * implementation calls {@link #createDeleteFeature(IDeleteContext)} and |
| * triggers the result's delete method. |
| * |
| * @param context |
| * The context describing the delete request |
| */ |
| public void delete(IDeleteContext context) { |
| if (wrappedDeleteFeature == null) { |
| wrappedDeleteFeature = createDeleteFeature(context); |
| } |
| if (wrappedDeleteFeature != null) { |
| wrappedDeleteFeature.delete(context); |
| } |
| } |
| |
| /** |
| * Clients can override to add actions after the default delete behavior is |
| * triggered. The default implementation does nothing and is called from the |
| * registered delete feature. |
| * |
| * @param context |
| * The context describing the delete request |
| */ |
| public void postDelete(IDeleteContext context) { |
| } |
| |
| /** |
| * Creates the {@link IRemoveFeature} instance that handles the removal of |
| * diagram elements. The default implementation just creates an adapted |
| * {@link DefaultRemoveFeature}. Concrete pattern implementations may either |
| * override this method to provide their own subclass of |
| * {@link DefaultRemoveFeature} or override and extend the individual |
| * methods provided by {@link IRemove}. |
| * <p> |
| * The difference of the remove feature returned here to the standard |
| * {@link DefaultRemoveFeature} is simply that the instance returned here |
| * cares about the delegation to the pattern's |
| * {@link #preRemove(IRemoveContext)}, {@link #isRemoveAbort()} and |
| * {@link #postRemove(IRemoveContext)} methods. Clients overriding this |
| * method should re-implement that pattern, in case the delegation is |
| * desired. |
| * |
| * @param context |
| * the removal context |
| * @return the {@link IRemoveFeature} instance to use for this pattern |
| * @see #canRemove(IRemoveContext) |
| * @see #preRemove(IRemoveContext) |
| * @see #isRemoveAbort() |
| * @see #remove(IRemoveContext) |
| * @see #postRemove(IRemoveContext) |
| */ |
| protected IRemoveFeature createRemoveFeature(IRemoveContext context) { |
| return new DefaultRemoveFeature(getFeatureProvider()) { |
| @Override |
| public void preRemove(IRemoveContext context) { |
| super.preRemove(context); |
| AbstractPattern.this.preRemove(context); |
| } |
| |
| @Override |
| public boolean isRemoveAbort() { |
| return AbstractPattern.this.isRemoveAbort(); |
| } |
| |
| @Override |
| public void postRemove(IRemoveContext context) { |
| AbstractPattern.this.postRemove(context); |
| super.postRemove(context); |
| } |
| }; |
| } |
| |
| /** |
| * Clients can override to modify the default behavior if the pattern can |
| * (and wants to) handle a remove request. The default implementation calls |
| * {@link #createRemoveFeature(IRemoveContext)} and asks the result's |
| * canRemove method. |
| * |
| * @param context |
| * The context describing the remove request |
| * |
| * @return <code>true</code>, if the pattern can perform the delete |
| * operation, <code>false</code> otherwise |
| */ |
| public boolean canRemove(IRemoveContext context) { |
| if (wrappedRemoveFeature == null) { |
| wrappedRemoveFeature = createRemoveFeature(context); |
| } |
| return wrappedRemoveFeature.canRemove(context); |
| } |
| |
| /** |
| * Clients can override to add actions before the default remove behavior is |
| * triggered. The default implementation does nothing and is called from the |
| * registered remove feature. |
| * |
| * @param context |
| * The context describing the remove request |
| */ |
| public void preRemove(IRemoveContext context) { |
| } |
| |
| /** |
| * Clients can override to modify the default remove behavior. The default |
| * implementation calls {@link #createRemoveFeature(IRemoveContext)} and |
| * triggers the result's remove method. |
| * |
| * @param context |
| * The context describing the remove request |
| */ |
| public void remove(IRemoveContext context) { |
| if (wrappedRemoveFeature == null) { |
| wrappedRemoveFeature = createRemoveFeature(context); |
| } |
| wrappedRemoveFeature.remove(context); |
| } |
| |
| /** |
| * Clients can override to add actions after the default remove behavior is |
| * triggered. The default implementation does nothing and is called from the |
| * registered remove feature. |
| * |
| * @param context |
| * The context describing the remove request |
| */ |
| public void postRemove(IRemoveContext context) { |
| } |
| |
| /** |
| * Clients can override this method to indicate that the pattern allows |
| * direct editing for the shape described in the passed |
| * {@link IDirectEditingContext}. Corresponds to the method |
| * {@link AbstractDirectEditingFeature#canDirectEdit(IDirectEditingContext)} |
| * . The default implementation simply returns <code>false</code>. |
| * |
| * @param context |
| * A context object describing the direct edit request. |
| * @return <code>true</code> in case direct editing shall be allowed, |
| * <code>false</code> otherwise. |
| */ |
| public boolean canDirectEdit(IDirectEditingContext context) { |
| return false; |
| } |
| |
| /** |
| * This method will be called by the framework to check if the passed String |
| * is valid as new value for the shape. This method's response time should |
| * be small since the method is queried after each change of the value in |
| * the direct edit UI. The default implementation simply returns null to |
| * indicate that all values are valid. In case of a not valid value, the |
| * returned string shall indicate the reason why the value is not valid. |
| * Corresponds to the method |
| * {@link AbstractDirectEditingFeature#checkValueValid(String, IDirectEditingContext)} |
| * . |
| * |
| * @param value |
| * The new value to check |
| * @param context |
| * A context object describing the direct edit request. |
| * @return <code>null</code> in case of a valid value, a string describing |
| * the reason for being not valid otherwise. |
| */ |
| public String checkValueValid(String value, IDirectEditingContext context) { |
| return null; |
| } |
| |
| /** |
| * Can be overridden by clients to define completion functionality for |
| * direct editing. Corresponds to |
| * {@link AbstractDirectEditingFeature#completeValue(String, int, String, IDirectEditingContext)} |
| * . The default implementation simply returns the parameter chosenValue. |
| * |
| * @param value |
| * The current value |
| * @param caretPosition |
| * The current cursor position |
| * @param choosenValue |
| * The value chosen by user |
| * @param context |
| * A context object describing the direct edit request. |
| * @return The new value |
| */ |
| public String completeValue(String value, int caretPos, String chosenValue, IDirectEditingContext context) { |
| return chosenValue; |
| } |
| |
| /** |
| * This value will be used if the cell editor is a combo box. This |
| * functionality only applies to TYPE_DROPDOWN. Corresponds to the method |
| * {@link AbstractDirectEditingFeature#getPossibleValues(IDirectEditingContext)} |
| * . The default implementation returns an empty string array. |
| * |
| * @param context |
| * A context object describing the direct edit request. |
| * @return The possible values for the combo box. |
| */ |
| public String[] getPossibleValues(IDirectEditingContext context) { |
| return EMPTY_STRING_ARRAY; |
| } |
| |
| /** |
| * This proposals will be used for the completion list of a simple text cell |
| * editor. This functionality only applies to TYPE_TEXT. Corresponds to the |
| * method |
| * {@link AbstractDirectEditingFeature#getValueProposals(String, int, IDirectEditingContext)} |
| * . The default implementation returns an empty string array. |
| * |
| * @param value |
| * The current value |
| * @param caretPosition |
| * The current cursor position |
| * @param context |
| * A context object describing the direct edit request. |
| * @return The proposed values |
| */ |
| public String[] getValueProposals(String value, int caretPos, IDirectEditingContext context) { |
| return EMPTY_STRING_ARRAY; |
| } |
| |
| /** |
| * Checks if auto completion is enabled. This functionality only applies to |
| * TYPE_TEXT. Corresponds to method |
| * {@link AbstractDirectEditingFeature#isAutoCompletionEnabled()}. The |
| * default implementation simply returns <code>false</code>. |
| * |
| * @return <code>true</code>, if proposals should appear automatically, |
| * <code>false</code> otherwise. |
| */ |
| public boolean isAutoCompletionEnabled() { |
| return false; |
| } |
| |
| /** |
| * Checks if completion is available. This functionality only applies to |
| * TYPE_TEXT. Corresponds to method |
| * {@link AbstractDirectEditingFeature#isCompletionAvailable()}. The default |
| * implementation simply returns <code>false</code>. |
| * |
| * @return <code>true</code> if completion is / proposals are available at |
| * all, <code>false</code> otherwise. |
| */ |
| public boolean isCompletionAvailable() { |
| return false; |
| } |
| |
| /** |
| * Defines if the input field should be streched to fit its contents. This |
| * functionality applies to TYPE_TEXT, TYPE_DROPDOWN and |
| * TYPE_DROPDOWN_READ_ONLY. Corresponds to method |
| * {@link AbstractDirectEditingFeature#stretchFieldToFitText()}. The default |
| * implementation simply returns <code>false</code>. |
| * |
| * @return <code>true</code> if the field should exactly fit the contents, |
| * <code>false</code> otherwise. |
| */ |
| public boolean stretchFieldToFitText() { |
| return false; |
| } |
| |
| /** |
| * The Graphiti framework calls this method to decide which UI to show up |
| * for direct editing. Corresponds to the method |
| * {@link AbstractDirectEditingFeature#getEditingType()}. The default |
| * implementation return {@link IDirectEditing#TYPE_NONE}, other valid type |
| * are defined by the TYPE_* constants in {@link IDirectEditing}. |
| * |
| * @return The desired editing type |
| */ |
| public int getEditingType() { |
| return IDirectEditing.TYPE_NONE; |
| } |
| |
| /** |
| * Provides the initial value for display in the newly opened text editing |
| * UI component. Corresponds to the method |
| * {@link AbstractDirectEditingFeature#getInitialValue(IDirectEditingContext)} |
| * . The default implementation always returns an empty string. |
| * |
| * @param context |
| * A context object describing the direct edit request. |
| * @return The initial string value to be displayed for editing by the user. |
| */ |
| public String getInitialValue(IDirectEditingContext context) { |
| return ""; //$NON-NLS-1$ |
| } |
| |
| /** |
| * Set the new value after direct editing is finished. The value comes from |
| * the text editing UI component. Corresponds to the method |
| * {@link AbstractDirectEditingFeature#setValue(String, IDirectEditingContext)} |
| * . The default implementation does nothing. |
| * |
| * @param value |
| * The new value to be set |
| * @param context |
| * A context object describing the direct edit request. |
| */ |
| public void setValue(String value, IDirectEditingContext context) { |
| } |
| |
| /** |
| * The direct editing mode contains controls for code completion and the |
| * selection from a combo box. In both cases the standard implementation |
| * supports only strings. |
| * <p> |
| * If the client wants to work with Objects he must provide an |
| * implementation of {@link IProposalSupport}. In this case the following |
| * methods of the pattern are ignored: |
| * <p> |
| * <code> |
| * <br>* String checkValueValid(String value, IDirectEditingContext context); |
| * <br>* String completeValue(String value, int caretPosition, String choosenValue, IDirectEditingContext context); |
| * <br>* String[] getPossibleValues(IDirectEditingContext context); |
| * <br>* String[] getValueProposals(String value, int caretPosition, IDirectEditingContext context); |
| * <br>* void setValue(String value, IDirectEditingContext context); |
| * </code><br> |
| * Corresponds to the method |
| * {@link AbstractDirectEditingFeature#getProposalSupport()}. The default |
| * implementation returns <code>null</code> to enable the standard |
| * string-based direct editing functionality. |
| * |
| * @return The special implementation to support Objects in code completion |
| * and combo box |
| * @since 0.8 |
| */ |
| public IProposalSupport getProposalSupport() { |
| return null; |
| } |
| |
| /** |
| * Is queried by the framework after a pattern has been executed to find out |
| * if this pattern should appear in the undo stack. By default all patterns |
| * should appear there (see implementation in AbstractPattern), but single |
| * pattern functionality may decide to override this behavior. Note that |
| * this is a dynamic attribute of the pattern that is queried each time |
| * <b>after</b> the pattern functionality has been executed. |
| * <p> |
| * <b>IMPORTANT NOTE:</b> The implementor of the feature is responsible for |
| * correctly implementing this method! It will lead to inconsistencies if |
| * this method returns <code>false</code> although the pattern did changes. |
| * |
| * @param actionType |
| * the followings types are currently supported: |
| * <code>IDelete.class, IRemove.class</code> |
| * |
| * |
| * @return <code>true</code> if the last action of the pattern from this |
| * action type should appear in the undo stack, <code>false</code> |
| * otherwise |
| * |
| * @since 0.9 |
| */ |
| public boolean hasDoneChanges(Class<?> actionType) { |
| boolean ret = true; |
| if (IDelete.class.equals(actionType)) { |
| if (wrappedDeleteFeature != null) { |
| ret = wrappedDeleteFeature.hasDoneChanges(); |
| } |
| } else if (IRemove.class.equals(actionType)) { |
| if (wrappedRemoveFeature != null) { |
| ret = wrappedRemoveFeature.hasDoneChanges(); |
| } |
| } |
| return ret; |
| } |
| |
| /** |
| * @since 0.12 |
| */ |
| @Override |
| public boolean isDeleteAbort() { |
| return false; |
| } |
| |
| /** |
| * @since 0.12 |
| */ |
| @Override |
| public boolean isRemoveAbort() { |
| return false; |
| } |
| } |