blob: 331eb7cb9c981b386198aa474ea1690e26b93da9 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2008 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.diagram.ui.render.clipboard;
import java.awt.Image;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Stack;
import org.eclipse.core.runtime.Assert;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.geometry.Translatable;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.LayerManager;
import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.image.PartPositionInfo;
import org.eclipse.gmf.runtime.diagram.ui.internal.figures.IExpandableFigure;
import org.eclipse.gmf.runtime.diagram.ui.internal.services.decorator.Decoration;
import org.eclipse.gmf.runtime.diagram.ui.l10n.SharedImages;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.PointListUtilities;
import org.eclipse.gmf.runtime.draw2d.ui.geometry.LineSeg.Sign;
import org.eclipse.gmf.runtime.draw2d.ui.internal.graphics.ScaledGraphics;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.IMapMode;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
import org.eclipse.gmf.runtime.draw2d.ui.render.internal.graphics.RenderedMapModeGraphics;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.ImageData;
/**
* Provides the framework to generate SWT and AWT images of a diagram or a
* subset of editparts on a diagram.
*
* @author sshaw
* @author Barys Dubauski
*/
abstract public class DiagramGenerator {
private int image_margin = 0;
private DiagramEditPart _dgrmEP;
/**
* Creates a new instance.
*
* @param dgrmEP
* the diagram editpart
*/
public DiagramGenerator(DiagramEditPart dgrmEP) {
this._dgrmEP = dgrmEP;
image_margin = getMapMode().DPtoLP(10);
}
/**
* @return DiagramEditPart
*/
protected DiagramEditPart getDiagramEditPart() {
return this._dgrmEP;
}
/**
* Allows hook for the creation of a <code>Graphics</code> object that is
* used for the rendering of the diagram.
*
* @param width
* of the clipping area
* @param height
* of the clipping area
* @return Graphics element that is the target for rendering.
*/
abstract protected Graphics setUpGraphics(int width, int height);
/**
* Allows hook to dispose of any artifacts around the creation of the
* <code>Graphics</code> object used for rendering.
*
* @param g
* Graphics element that is to be disposed.
*/
protected void disposeGraphics(Graphics g) {
g.dispose();
}
/**
* Creates an image descriptor representing the image rendered from the
* diagram.
*
* @param g
* Graphics object where information to form the image descriptor
* can be retrieved from.
* @return ImageDescriptor representing the image rendered from the diagram.
*/
abstract protected ImageDescriptor getImageDescriptor(Graphics g);
/**
* Creates an AWT image for the contents of the diagram editpart.
*
* @return an image in AWT format
*/
final public Image createAWTImageForDiagram() {
List editparts = getDiagramEditPart().getPrimaryEditParts();
return createAWTImageForParts(editparts);
}
/**
* Creates an AWT image for the list of editparts passed in.
*
* @param editparts
* the list of <code>IGraphicalEditParts</code> that will be
* rendered to the Image
* @return an image in AWT format
*/
public Image createAWTImageForParts(List editparts) {
org.eclipse.swt.graphics.Rectangle diagramArea = calculateImageRectangle(editparts);
return createAWTImageForParts(editparts, diagramArea);
}
/**
* Creates an SWT image descriptor for the contents of the diagram editpart.
*
* @return an image descriptor for an SWT image
*/
final public ImageDescriptor createSWTImageDescriptorForDiagram() {
List editparts = getDiagramEditPart().getPrimaryEditParts();
return createSWTImageDescriptorForParts(editparts);
}
/**
* Creates an SWT image descriptor for the list of editparts passed in.Any
* connections where both the source and target editparts are passed in are
* also drawn.
*
* @param editparts
* the list of <code>IGraphicalEditParts</code> that will be
* rendered to the Image
* @return an image descriptor for an SWT image
*/
final public ImageDescriptor createSWTImageDescriptorForParts(List editparts) {
org.eclipse.swt.graphics.Rectangle sourceRect = calculateImageRectangle(editparts);
return createSWTImageDescriptorForParts(editparts, sourceRect);
}
/**
* @return
*/
protected IMapMode getMapMode() {
IMapMode mm = MapModeUtil.getMapMode(getDiagramEditPart().getFigure());
return mm;
}
/**
* Renders the list of editparts to the graphics object. Any connections
* where both the source and target editparts are passed in are also drawn.
*
* @param graphics
* the graphics object on which to draw
* @param translateOffset
* a <code>Point</code> that the value the
* <code>graphics</code> object will be translated by in
* relative coordinates.
* @param editparts
* the list of <code>IGraphicalEditParts</code> that will be
* rendered to the graphics object
*/
final protected void renderToGraphics(Graphics graphics,
Point translateOffset, List editparts) {
List sortedEditparts = sortSelection(editparts);
graphics.translate((-translateOffset.x), (-translateOffset.y));
graphics.pushState();
List<GraphicalEditPart> connectionsToPaint = new LinkedList<GraphicalEditPart>();
Map decorations = findDecorations(editparts);
for (Iterator editPartsItr = editparts.listIterator(); editPartsItr.hasNext();) {
IGraphicalEditPart editPart = (IGraphicalEditPart) editPartsItr.next();
// do not paint selected connection part
if (editPart instanceof ConnectionEditPart) {
connectionsToPaint.add(editPart);
} else {
connectionsToPaint.addAll(findConnectionsToPaint(editPart));
// paint shape figure
IFigure figure = editPart.getFigure();
paintFigure(graphics, figure);
paintDecorations(graphics, figure, decorations);
}
}
// paint the connection parts after shape parts paint
decorations = findDecorations(connectionsToPaint);
for (Iterator<GraphicalEditPart> connItr = connectionsToPaint.iterator(); connItr.hasNext();) {
IFigure figure = connItr.next().getFigure();
paintFigure(graphics, figure);
paintDecorations(graphics, figure, decorations);
}
}
/**
* Collects all connections contained within the given edit part
*
* @param editPart the container editpart
* @return connections within it
*/
private Collection<ConnectionEditPart> findConnectionsToPaint(IGraphicalEditPart editPart) {
/*
* Set of node editparts contained within the given editpart
*/
HashSet<GraphicalEditPart> editParts = new HashSet<GraphicalEditPart>();
/*
* All connection editparts that have a source contained within the given editpart
*/
HashSet<ConnectionEditPart> connectionEPs = new HashSet<ConnectionEditPart>();
/*
* Connections contained within the given editpart (or just the connections to paint
*/
HashSet<ConnectionEditPart> connectionsToPaint = new HashSet<ConnectionEditPart>();
/*
* Populate the set of node editparts
*/
getNestedEditParts(editPart, editParts);
/*
* Populate the set of connections whose source is within the given editpart
*/
for (Iterator<GraphicalEditPart> editPartsItr = editParts.iterator(); editPartsItr.hasNext();) {
connectionEPs.addAll(getAllConnectionsFrom(editPartsItr.next()));
}
/*
* Create a set of connections constained within the given editpart
*/
while (!connectionEPs.isEmpty()) {
/*
* Take the first connection and check whethe there is a path
* through that connection that leads to the target contained within
* the given editpart
*/
Stack<ConnectionEditPart> connectionsPath = new Stack<ConnectionEditPart>();
ConnectionEditPart conn = connectionEPs.iterator().next();
connectionEPs.remove(conn);
connectionsPath.add(conn);
/*
* Initialize the target for the current path
*/
EditPart target = conn.getTarget();
while(connectionEPs.contains(target)) {
/*
* If the target end is a connection, check if it's one of the
* connection's whose target is a connection and within the
* given editpart. Append it to the path if it is. Otherwise
* check if the target is within the actual connections or nodes
* contained within the given editpart
*/
ConnectionEditPart targetConn = (ConnectionEditPart) target;
connectionEPs.remove(targetConn);
connectionsPath.add(targetConn);
/*
* Update the target for the new path
*/
target = targetConn.getTarget();
}
/*
* The path is built, check if it's target is a node or a connection
* contained within the given editpart
*/
if (editParts.contains(target) || connectionsToPaint.contains(target)) {
connectionsToPaint.addAll(connectionsPath);
}
}
return connectionsToPaint;
}
/**
* Returns all connections orginating from a given editpart. All means that
* connections originating from connections that have a source given
* editpart will be included
*
* @param ep the editpart
* @return all source connections
*/
private List<ConnectionEditPart> getAllConnectionsFrom(GraphicalEditPart ep) {
LinkedList<ConnectionEditPart> connections = new LinkedList<ConnectionEditPart>();
for (Iterator itr = ep.getSourceConnections().iterator(); itr.hasNext();) {
ConnectionEditPart sourceConn = (ConnectionEditPart) itr.next();
connections.add(sourceConn);
connections.addAll(getAllConnectionsFrom(sourceConn));
}
return connections;
}
/**
* This method is used when a figure needs to be painted to the graphics.
* The figure will be translated based on its absolute positioning.
*
* @param graphics
* Graphics object to render figure
* @param figure
* the figure to be rendered
*/
private void paintFigure(Graphics graphics, IFigure figure) {
if (!figure.isVisible())
return;
// Calculate the Relative bounds and absolute bounds
Rectangle relBounds = null;
if (figure instanceof IExpandableFigure)
relBounds = ((IExpandableFigure) figure).getExtendedBounds()
.getCopy();
else
relBounds = figure.getBounds().getCopy();
Rectangle abBounds = relBounds.getCopy();
translateToPrintableLayer(figure, abBounds);
// Calculate the difference
int transX = abBounds.x - relBounds.x;
int transY = abBounds.y - relBounds.y;
// Paint the figure
graphics.pushState();
graphics.translate(transX, transY);
figure.paint(graphics);
graphics.popState();
graphics.restoreState();
}
/**
* Find the decorations that adorn the specified <code>editParts</code>.
*
* @param editparts
* the list of <code>IGraphicalEditParts</code> for which to
* find decorations
* @return a mapping of {@link IFigure}to ({@link Decoration}or
* {@link Collection}of decorations})
*/
private Map findDecorations(Collection editparts) {
// create inverse mapping of figures to edit parts (need this to map
// decorations to edit parts)
Map figureMap = mapFiguresToEditParts(editparts);
Map result = new java.util.HashMap();
if (!editparts.isEmpty()) {
IGraphicalEditPart first = (IGraphicalEditPart) editparts.iterator().next();
IFigure decorationLayer = LayerManager.Helper.find(first).getLayer(
DiagramRootEditPart.DECORATION_PRINTABLE_LAYER);
if (decorationLayer != null) {
// compute the figures of the shapes
List figures = new java.util.ArrayList(editparts);
for (ListIterator iter = figures.listIterator(); iter.hasNext();) {
iter.set(((IGraphicalEditPart) iter.next()).getFigure());
}
// find the decorations on figures that were selected
for (Iterator iter = decorationLayer.getChildren().iterator(); iter
.hasNext();) {
Object next = iter.next();
if (next instanceof Decoration) {
Decoration decoration = (Decoration) next;
IFigure owner = decoration.getOwnerFigure();
while (owner != null) {
if (figureMap.containsKey(owner)) {
Object existing = result.get(owner);
if (existing == null) {
result.put(owner, decoration);
} else if (existing instanceof Collection) {
((Collection) existing).add(decoration);
} else {
Collection c = new java.util.ArrayList(2);
c.add(existing);
c.add(decoration);
result.put(owner, c);
}
break;
} else {
owner = owner.getParent();
}
}
}
}
}
}
return result;
}
/**
* Constructs a mapping of figures to their corresponding edit parts.
*
* @param editParts
* a collection of <code>IGraphicalEditParts</code>
* @return a mapping of {@link IFigure}to {@link IGraphicalEditPart}
*/
private Map mapFiguresToEditParts(Collection editParts) {
Map result = new java.util.HashMap();
for (Iterator iter = editParts.iterator(); iter.hasNext();) {
IGraphicalEditPart next = (IGraphicalEditPart) iter.next();
result.put(next.getFigure(), next);
}
return result;
}
/**
* Paints the decorations adorning the specified <code>figure</code>, if
* any.
*
* @param graphics
* the graphics to paint on
* @param figure
* the figure
* @param decorations
* mapping of figures to decorations, in which we will find the
* <code>figure</code>'s decorations
*/
private void paintDecorations(Graphics graphics, IFigure figure,
Map decorations) {
Object decoration = decorations.get(figure);
if (decoration != null) {
if (decoration instanceof Collection) {
for (Iterator iter = ((Collection) decoration).iterator(); iter
.hasNext();) {
paintFigure(graphics, (IFigure) iter.next());
}
} else {
paintFigure(graphics, (IFigure) decoration);
}
}
}
/**
* This is a recursive method that search a tree of edit parts looking for
* edit parts contained in the open list. If the edit part is found it is
* removed from the open list and placed in the closed list.
*
* @param editPart
* @param open
* @param closed
*/
private void sortSelection(GraphicalEditPart editPart, List open,
List closed) {
// Do nothing if the open list is empty
if (open.isEmpty()) {
return;
}
// IF the edit part is contained in the open list (we are searching for
// it)
if (open.contains(editPart)) {
// Add the Edit Part to the closed list and remove it from
// the open list
closed.add(editPart);
open.remove(editPart);
}
for (Iterator iter = editPart.getChildren().iterator(); iter.hasNext();) {
GraphicalEditPart child = (GraphicalEditPart) iter.next();
sortSelection(child, open, closed);
}
}
private List sortSelection(List toSort) {
List closed = new ArrayList(toSort.size());
List open = new ArrayList(toSort.size());
open.addAll(toSort);
sortSelection(getDiagramEditPart(), open, closed);
if (!open.isEmpty()) {
closed.addAll(open);
}
return closed;
}
/**
* This method is used to obtain the list of child edit parts for shape
* compartments.
*
* @param childEditPart
* base edit part to get the list of children editparts
* @param editParts
* list of nested shape edit parts
*/
private void getNestedEditParts(IGraphicalEditPart childEditPart,
Collection editParts) {
for (Iterator iter = childEditPart.getChildren().iterator(); iter
.hasNext();) {
IGraphicalEditPart child = (IGraphicalEditPart) iter.next();
editParts.add(child);
getNestedEditParts(child, editParts);
}
}
/**
* Determine the minimal rectangle required to bound the list of editparts.
* A margin is used around each of the editpart's figures when calculating
* the size.
*
* @param editparts
* the list of <code>IGraphicalEditParts</code> from which
* their figure bounds will be used
* @return Rectangle the minimal rectangle that can bound the figures of the
* list of editparts
*/
public org.eclipse.swt.graphics.Rectangle calculateImageRectangle(
List editparts) {
int minX = 0;
int maxX = 0;
int minY = 0;
int maxY = 0;
IMapMode mm = getMapMode();
for (int i = 0; i < (editparts.size()); i++) {
IGraphicalEditPart editPart = (IGraphicalEditPart) editparts.get(i);
IFigure figure = editPart.getFigure();
Rectangle bounds = null;
if (figure instanceof IExpandableFigure)
bounds = ((IExpandableFigure) figure).getExtendedBounds();
else
bounds = figure.getBounds().getCopy();
translateToPrintableLayer(figure, bounds);
bounds = bounds.getExpanded(getImageMargin(), getImageMargin());
if (i == 0) {
minX = bounds.x;
maxX = bounds.x + bounds.width;
minY = bounds.y;
maxY = bounds.y + bounds.height;
} else {
minX = Math.min(minX, bounds.x);
maxX = Math.max(maxX, (bounds.x + bounds.width));
minY = Math.min(minY, bounds.y);
maxY = Math.max(maxY, (bounds.y + bounds.height));
}
}
int width = (maxX - minX);
int height = (maxY - minY);
if (width <= 0) {
width = mm.DPtoLP(100);
}
if (height <= 0) {
height = mm.DPtoLP(100); // create an empty image if the
// diagram does not contain child
}
org.eclipse.swt.graphics.Rectangle imageRect = new org.eclipse.swt.graphics.Rectangle(
minX, minY, width, height);
return imageRect;
}
/**
* Get the positional data and the semantic elements for each
* <code>ShapeEditPart</code>, <code>ShapeCompartmentEditPart</code>,
* and <code>ConnectionEditPart</code> on the diagram.
*
* @return A list of {@link PartPositionInfo}objects with positional data
* and the semantic element for the relevant editparts on the
* diagram.
*/
public List getDiagramPartInfo() {
Assert.isNotNull(_dgrmEP);
return getDiagramPartInfo(_dgrmEP);
}
/**
* Get the positional data and the semantic elements for each
* <code>ShapeEditPart</code>, <code>ShapeCompartmentEditPart</code>,
* and <code>ConnectionEditPart</code> on the diagram.
*
* @param diagramEditPart
* The diagram edit part.
* @return A list of {@link PartPositionInfo}objects with positional data
* and the semantic element for the relevant editparts on the
* diagram.
*/
public List getDiagramPartInfo(DiagramEditPart diagramEditPart) {
List result = new ArrayList();
List editParts = new ArrayList();
List children = diagramEditPart.getPrimaryEditParts();
IMapMode mm = getMapMode();
// We will use the diagram generate that was used to generate the image
// to figure out the outer-bound rectangle so that we are calculating
// the
// image positions using the same box as was used to create the image.
org.eclipse.swt.graphics.Rectangle imageRect = calculateImageRectangle(children);
Iterator li = children.iterator();
while (li.hasNext()) {
IGraphicalEditPart part = (IGraphicalEditPart) li.next();
editParts.add(part);
getNestedEditParts(part, editParts);
}
Iterator iter = editParts.iterator();
while (iter.hasNext()) {
IGraphicalEditPart part = (IGraphicalEditPart) iter.next();
IFigure figure = part.getFigure();
// RATLC00139941: Need to support any kind of shape edit part
// and shape compartments, too, because these sometimes
// correspond to distinct semantic elements
if (part instanceof ShapeEditPart
|| part instanceof ShapeCompartmentEditPart) {
PartPositionInfo position = new PartPositionInfo();
position.setSemanticElement(ViewUtil
.resolveSemanticElement((View) part.getModel()));
Rectangle bounds = figure.getBounds().getCopy();
translateToPrintableLayer(figure, bounds);
bounds.translate(-imageRect.x, -imageRect.y);
position.setPartHeight(mm.LPtoDP(bounds.height));
position.setPartWidth(mm.LPtoDP(bounds.width));
position.setPartX(mm.LPtoDP(bounds.x));
position.setPartY(mm.LPtoDP(bounds.y));
result.add(0, position);
} else if (part instanceof ConnectionEditPart) {
// find a way to get (P1, P2, ... PN) for connection edit part
// add MARGIN and calculate "stripe" for the polyline instead of
// bounding box.
PartPositionInfo position = new PartPositionInfo();
position.setSemanticElement(ViewUtil
.resolveSemanticElement((View) part.getModel()));
if (figure instanceof PolylineConnection) {
PolylineConnection mainPoly = (PolylineConnection) figure;
PointList mainPts = mainPoly.getPoints();
translateToPrintableLayer(figure, mainPts);
List envelopingPts = calculateEnvelopingPolyline(mainPts,
new Point(imageRect.x, imageRect.y));
List transformedPts = convertPolylineUnits(envelopingPts);
position.setPolyline(transformedPts);
result.add(0, position);
}
}
}
return result;
}
/**
* Recursively moves up the figure containment tree until it reaches the
* printable layer or the root.
*
* @param figure
* the figure that the translatable is relative to
* @param translatable
* the object that needs to be translated
*/
private void translateToPrintableLayer(IFigure figure,
Translatable translatable) {
IFigure printableLayer = getDiagramEditPart().getLayer(
LayerConstants.PRINTABLE_LAYERS);
if (figure == null || figure.equals(printableLayer)) {
return;
}
figure.translateToParent(translatable);
translateToPrintableLayer(figure.getParent(), translatable);
}
/**
* Calculates enveloping polyline for a given polyline with margin MARGIN
*
* E1 E2
* +----------------+
* | |<------- MARGIN
* A *----------------* B
* | |
* +----------------+
* E4 E3
*
* On the figure above: AB is a given polyline. E1E2E3E4 is enveloping
* polyline built around AB perimeter using margin MARGIN.
*
*
* @param polyPts
* @param origin
* location of the main diagram bounding box used to shift
* coordinates to be relative against diagram
*
* @return List of Point type objects (that carry X and Y coordinate pair)
* representing the polyline
* @author Barys Dubauski
*/
private List calculateEnvelopingPolyline(PointList polyPts, Point origin) {
ArrayList result = new ArrayList();
List mainSegs = PointListUtilities.getLineSegments(polyPts);
int mainSegsLength = mainSegs.size();
LineSeg segment = null;
Point orthoPoint1 = null;
Point orthoPoint2 = null;
// collect points clockwise
for (int i = 0; i < mainSegsLength; i++) {
segment = (LineSeg) mainSegs.get(i);
orthoPoint1 = segment.locatePoint(0.0, getImageMargin(),
Sign.POSITIVE);
orthoPoint1.translate(-origin.x, -origin.y);
orthoPoint2 = segment.locatePoint(1.0, getImageMargin(),
Sign.POSITIVE);
orthoPoint2.translate(-origin.x, -origin.y);
result.add(orthoPoint1);
result.add(orthoPoint2);
}
// now add the original poly
for (int i = mainSegsLength - 1; i >= 0; i--) {
segment = (LineSeg) mainSegs.get(i);
orthoPoint1 = segment.getTerminus();
orthoPoint1.translate(-origin.x, -origin.y);
result.add(orthoPoint1);
orthoPoint2 = segment.getOrigin();
orthoPoint2.translate(-origin.x, -origin.y);
result.add(orthoPoint2);
}
// add first point to close the polyline per "poly" area type HTML
// requirements
Object first = result.get(0);
result.add(first);
return result;
}
/**
* transforms coordinates of the polyline from logical units to device units
*
* @param polyPts
* @return List of Point type objects (that carry X and Y coordinate pair)
* representing the polyline
* @author Barys Dubauski
*/
private List convertPolylineUnits(List polyPts) {
ArrayList result = new ArrayList();
Iterator iter = polyPts.iterator();
IMapMode mm = getMapMode();
while (iter.hasNext()) {
Point point = (Point) iter.next();
Point newPoint = new Point(mm.LPtoDP(point.x), mm.LPtoDP(point.y));
result.add(newPoint);
}
return result;
}
/**
* @return <code>int</code> value that is the margin around the generated
* image in logical coordinates.
*/
protected int getImageMargin() {
return image_margin;
}
/**
* Generates AWT image of specified editparts on the specified rectangle.
*
* @param editParts editparts
* @param diagramArea clipping rectangle
* @return AWT image
*/
public Image createAWTImageForParts(List editParts,
org.eclipse.swt.graphics.Rectangle diagramArea) {
return null;
}
final public ImageDescriptor createSWTImageDescriptorForParts(
List editparts, org.eclipse.swt.graphics.Rectangle sourceRect) {
// initialize imageDesc to the error icon
ImageDescriptor imageDesc = new ImageDescriptor() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.resource.ImageDescriptor#getImageData()
*/
public ImageData getImageData() {
return SharedImages.get(SharedImages.IMG_ERROR).getImageData();
}
};
Graphics graphics = null;
try {
IMapMode mm = getMapMode();
// Create the graphics and wrap it with the HiMetric graphics object
graphics = setUpGraphics(mm.LPtoDP(sourceRect.width), mm
.LPtoDP(sourceRect.height));
RenderedMapModeGraphics mapModeGraphics = new RenderedMapModeGraphics(
graphics, getMapMode());
renderToGraphics(mapModeGraphics, new Point(sourceRect.x,
sourceRect.y), editparts);
imageDesc = getImageDescriptor(graphics);
} finally {
if (graphics != null)
disposeGraphics(graphics);
}
return imageDesc;
}
/**
* Creates an SWT image descriptor for editparts. Editparts are scaled to fit in maxDeviceWidth and maxDeviceHeight
* frame
*
* @param editParts editparts
* @param maxDeviceWidth max width for the image
* @param maxDeviceHeight max height for the image
* @param useMargins true if 10 pisels margins are required to bound the editparts image
* @return the image descriptor
*/
final public ImageDescriptor createConstrainedSWTImageDecriptorForParts(List editParts, int maxDeviceWidth, int maxDeviceHeight, boolean useMargins) {
ImageDescriptor imageDesc = new ImageDescriptor() {
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.resource.ImageDescriptor#getImageData()
*/
public ImageData getImageData() {
return SharedImages.get(SharedImages.IMG_ERROR).getImageData();
}
};
Graphics graphics = null;
try {
IMapMode mm = getMapMode();
Rectangle originalBounds = new PrecisionRectangle(new Rectangle(calculateImageRectangle(editParts)));
getMapMode().LPtoDP(originalBounds);
int deviceMargins = mm.LPtoDP(getImageMargin());
int threshold = useMargins ? deviceMargins : 0;
double xScalingFactor = 1.0, yScalingFactor = xScalingFactor;
originalBounds.shrink(deviceMargins, deviceMargins);
if (maxDeviceWidth > threshold) {
xScalingFactor = (maxDeviceWidth - threshold - threshold)/ (originalBounds.preciseWidth());
}
if (maxDeviceHeight > threshold) {
yScalingFactor = (maxDeviceHeight - threshold - threshold) / (originalBounds.preciseHeight());
}
double scalingFactor = Math.min(Math.min(xScalingFactor, yScalingFactor), 1);
int imageWidth = originalBounds.width + threshold + threshold;
int imageHeight = originalBounds.height + threshold + threshold;
if (scalingFactor < 1) {
imageWidth = (int) Math.round(originalBounds.preciseWidth() * scalingFactor) + threshold + threshold;
imageHeight = (int) Math.round(originalBounds.preciseHeight() * scalingFactor) + threshold + threshold;
}
// Create the graphics and wrap it with the HiMetric graphics object
graphics = setUpGraphics(imageWidth, imageHeight);
ScaledGraphics scaledGraphics = new ScaledGraphics(graphics);
RenderedMapModeGraphics mapModeGraphics = new RenderedMapModeGraphics(
scaledGraphics, getMapMode());
graphics.translate(threshold, threshold);
mapModeGraphics.scale(scalingFactor);
Point location = new PrecisionPoint(originalBounds.preciseX(), originalBounds.preciseY());
mm.DPtoLP(location);
renderToGraphics(mapModeGraphics, location, editParts);
imageDesc = getImageDescriptor(graphics);
} finally {
if (graphics != null)
disposeGraphics(graphics);
}
return imageDesc;
}
/**
* Creates an AWT image for editparts. Editparts are scaled to fit in maxDeviceWidth and maxDeviceHeight
* frame
*
* @param editParts editparts
* @param maxDeviceWidth max width for the image
* @param maxDeviceHeight max height for the image
* @param useMargins true if 10 pisels margins are required to bound the editparts image
* @return the image
*/
public Image createConstrainedAWTImageForParts(List editParts, int maxDeviceWidth, int maxDeviceHeight, boolean useMargins) {
return null;
}
}