/***************************************************************************** * Copyright (c) 2011 CEA LIST. * * * 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: * Amine EL KOUHEN (CEA LIST/LIFL) - Amine.Elkouhen@cea.fr * Ansgar Radermacher (CEA LIST) - ansgar.radermacher@cea.fr *****************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.providers; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.Locator; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.gef.EditPart; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.handles.HandleBounds; import org.eclipse.gmf.runtime.diagram.ui.services.decorator.Decoration; import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoration; import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget; import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget.Direction; import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.infra.services.decoration.util.Decoration.PreferedPosition; import org.eclipse.papyrus.infra.services.decoration.util.IPapyrusDecoration; import org.eclipse.swt.graphics.Image; // TODO: Auto-generated Javadoc /** * The Class DiagramDecorationAdapter. */ public class DiagramDecorationAdapter { /** The decorator target. */ protected IDecoratorTarget decoratorTarget; /** The decoration. */ protected EList<IDecoration> decorations; protected EList<IPapyrusDecoration> pDecorations; /** The decoration image. */ protected Image decorationImage; /** * Instantiates a new diagram decoration adapter. * * @param decoratorTarget * the decorator target */ public DiagramDecorationAdapter(IDecoratorTarget decoratorTarget) { this.decoratorTarget = decoratorTarget; } /** * Gets the decorator target. * * @return the decorator target */ public IDecoratorTarget getDecoratorTarget() { return this.decoratorTarget; } /** * Removes the decoration. */ public void removeDecorations() { if((decoratorTarget == null) || (decorations == null)) { return; } for(IDecoration decoration : decorations) { removeDecoration(decoration); } } /** * Sets the decorator target. * * @param decoratorTarget * the new decorator target */ public void setDecoratorTarget(IDecoratorTarget decoratorTarget) { this.decoratorTarget = decoratorTarget; } /** * Gets the decoration image. * * @return the decoration image */ public Image getDecorationImage() { return decorationImage; } /** * Gets the tool tip. * * @param message * the message * @return the tool tip */ public Label getToolTip(String message) { return new Label(message, getDecorationImage()); } /** * Sets the decoration. * * @param pDecoration * A set of papyrus decorations * @param percentageFromSource * the distance in percent from source node (only used for decorations on an edge). 50 indicates in the middle * between source and target * @param margin * the margin from right corner (only used for decorations on a node) * @param isVolatile * the is volatile * @return the set of JFace decorations */ public EList<IDecoration> setDecorations(EList<IPapyrusDecoration> pDecorations, int percentageFromSource, int margin, boolean isVolatile) { final int distBetweenIconsPercent = 20; final int percentageMin = 10; final int percentageMax = 90; decorations = new BasicEList<IDecoration>(); if(pDecorations.size() > 1) { percentageFromSource -= distBetweenIconsPercent / 2 * (pDecorations.size() - 1); } if(percentageFromSource < percentageMin) { percentageFromSource = percentageMin; } for(IPapyrusDecoration pDecoration : pDecorations) { // TODO: createImage each time leaks! Image image = pDecoration.getDecorationImageForGE().createImage(); IDecoration decoration = setDecoration(decoratorTarget, image, percentageFromSource, margin, isVolatile); decorations.add(decoration); String message = pDecoration.getMessage(); Label toolTip = getToolTip(message); if(decoration instanceof Decoration) { ((Decoration)decoration).setToolTip(toolTip); } percentageFromSource += distBetweenIconsPercent; if(percentageFromSource > percentageMax) { percentageFromSource = percentageMax; } margin += image.getBounds().width; } this.pDecorations = pDecorations; return decorations; } /** * Removes the decoration. * * @param decoratorTarget * the decorator target * @param Decoration * the decoration */ public void removeDecoration(IDecoration decoration) { if((decoration == null) || (decoratorTarget == null)) { return; } if(decoration instanceof IFigure) { IFigure parent = ((IFigure)decoration).getParent(); if(parent != null) { parent.remove((IFigure)decoration); } } // decorations.remove(decoration); GraphicalEditPart ownerEditPart = (GraphicalEditPart)decoratorTarget.getAdapter(GraphicalEditPart.class); if(ownerEditPart.getViewer() != null) { ownerEditPart.getViewer().getVisualPartMap().remove(decoration); } } /** * Gets the decoration. * TODO: has side effect, rename? * * @param decoratorTarget * the decorator target * @param image * the image * @param position * the position * @param percentageFromSource * the percentage from source, only evaluated for edge decorations * @param margin * the margin in pixels from the target position. * @See org.eclipse.gmf.runtime.diagram.ui.services.decorator.addShapeDecoration: * The margin is the space, in himetric units, between the * shape's edge and the decoration. A positive margin will place * the figure outside the shape, a negative margin will place the * decoration inside the shape. * @param isVolatile * the is volatile * @return the decoration */ public IDecoration setDecoration(IDecoratorTarget decoratorTarget, Image image, int percentageFromSource, int margin, boolean isVolatile) { final View view = (View)decoratorTarget.getAdapter(View.class); org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoration decoration = null; if(view == null || view.eResource() == null || image == null) { return decoration; } EditPart editPart = (EditPart)decoratorTarget.getAdapter(EditPart.class); if(editPart == null || editPart.getViewer() == null) { return decoration; } if(editPart instanceof GraphicalEditPart) { GraphicalEditPart gEditPart = (GraphicalEditPart)editPart; if(view instanceof Edge) { decoration = decoratorTarget.addConnectionDecoration(image, percentageFromSource, isVolatile); } else { IFigure parentFig = gEditPart.getFigure(); margin = MapModeUtil.getMapMode(parentFig).DPtoLP(margin); Locator locator = new MultiIconTopRightLocator(parentFig, margin); // test to create fig from image in order to use addDecorator directly with a locator // ImageFigure fig = new ImageFigure(image); // fig.setParent(parentFig); // fig.setVisible(true); // BorderLayout layout = new BorderLayout(); // layout.setConstraint(fig, BorderLayout.CENTER); // Rectangle r = fig.getBounds(); // Direction NORTH_EAST will be ignored, since we impose "our" locator below decoration = decoratorTarget.addShapeDecoration(image, IDecoratorTarget.Direction.NORTH_EAST, margin, isVolatile); if(decoration instanceof Decoration) { ((Decoration)decoration).setLocator(locator); } // decoration = decoratorTarget.addDecoration(fig, locator, isVolatile); } } return decoration; } /** * Gets the decoration. * * @param decoratorTarget * the decorator target * @param figure * the figure * @param position * the position * @param percentageFromSource * the percentage from source * @param margin * the margin * @param isVolatile * the is volatile * @return the decoration */ public IDecoration setDecoration(IDecoratorTarget decoratorTarget, IFigure figure, int percentageFromSource, int margin, boolean isVolatile) { final View view = (View)decoratorTarget.getAdapter(View.class); org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoration decoration = null; if(view == null || view.eResource() == null || figure == null) { return decoration; } EditPart editPart = (EditPart)decoratorTarget.getAdapter(EditPart.class); if(editPart == null || editPart.getViewer() == null) { return decoration; } if(editPart instanceof GraphicalEditPart) { if(view instanceof Edge) { decoration = decoratorTarget.addConnectionDecoration(figure, percentageFromSource, isVolatile); } else { IFigure parentFig = ((GraphicalEditPart)editPart).getFigure(); margin = MapModeUtil.getMapMode(parentFig).DPtoLP(margin); // Locator locator = new MultiIconTopRightLocator(parentFig, margin); // decoration = decoratorTarget.addDecoration(figure, locator, isVolatile); decoration = decoratorTarget.addShapeDecoration(figure, IDecoratorTarget.Direction.NORTH_EAST, margin, isVolatile); } } return decoration; } /** * A locator that places elements to the upper right corner with a "margin" distance to the left. * * @See org.eclipse.gmf.runtime.gef.ui.internal.figures.RelativetoBorderLocator * @author ansgar * */ public class MultiIconTopRightLocator implements Locator { public MultiIconTopRightLocator(IFigure parentFig, int rightMargin) { this.reference = parentFig; if(rightMargin < 0) { // avoid negative right margin. This could imply that the decorator enlarges the reference figure // which in turn might re-position the decorator to the right and thus causing an enlargement in // an endless loop rightMargin = 0; } this.rightMargin = rightMargin; } public void relocate(IFigure target) { Rectangle bounds = reference instanceof HandleBounds ? new PrecisionRectangle(((HandleBounds)reference).getHandleBounds()) : new PrecisionRectangle(reference.getBounds()); reference.translateToAbsolute(bounds); target.translateToRelative(bounds); Point pTR = bounds.getTopRight(); Point pTL = bounds.getTopLeft(); Point pDecoration = new Point(pTR); int decorationX = pTR.x - target.getSize().width - rightMargin; if(decorationX > pTL.x) { // only set position, if it is inside the figure, i.e. bigger than left margin pDecoration.setX(decorationX); } else { pDecoration.setX(pTL.x); } target.setLocation(pDecoration); } protected IFigure reference; protected int rightMargin; }; /** * Gets the direction. * * @param position * the position * @return the direction */ @Deprecated private Direction getDirection(PreferedPosition position) { switch(position) { case NORTH_WEST: return IDecoratorTarget.Direction.NORTH_WEST; case NORTH: return IDecoratorTarget.Direction.NORTH; case NORTH_EAST: return IDecoratorTarget.Direction.NORTH_EAST; case EAST: return IDecoratorTarget.Direction.EAST; case SOUTH_EAST: return IDecoratorTarget.Direction.SOUTH_EAST; case SOUTH: return IDecoratorTarget.Direction.SOUTH; case SOUTH_WEST: return IDecoratorTarget.Direction.SOUTH_WEST; case WEST: return IDecoratorTarget.Direction.WEST; case CENTER: return IDecoratorTarget.Direction.CENTER; default: return IDecoratorTarget.Direction.NORTH_EAST; } } }