blob: ac42005c74b22d950dfc77e02276ea135202749b [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2002, 2010 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.Collection;
import java.util.HashMap;
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.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.PrecisionRectangle;
import org.eclipse.draw2d.geometry.Rectangle;
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.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.figures.IExpandableFigure;
import org.eclipse.gmf.runtime.diagram.ui.image.PartPositionInfo;
import org.eclipse.gmf.runtime.diagram.ui.l10n.SharedImages;
import org.eclipse.gmf.runtime.diagram.ui.render.util.DiagramImageUtils;
import org.eclipse.gmf.runtime.diagram.ui.render.util.PartPositionInfoGenerator;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.Decoration;
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.draw2d.ui.render.internal.graphics.RenderedScaledGraphics;
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;
private IFigure printableLayer;
private Dimension emptyImageSize;
private static final int DEFAULT_IMAGE_MARGIN_PIXELS = 10;
private static final int DEFAULT_EMPTY_IMAGE_SIZE_PIXELS = 100;
/**
* Creates a new instance.
*
* @param dgrmEP
* the diagram editpart
*/
public DiagramGenerator(DiagramEditPart dgrmEP) {
this._dgrmEP = dgrmEP;
this.printableLayer = LayerManager.Helper.find(_dgrmEP).getLayer(LayerConstants.PRINTABLE_LAYERS);
IMapMode mm = getMapMode();
image_margin = mm.DPtoLP(DEFAULT_IMAGE_MARGIN_PIXELS);
emptyImageSize = (Dimension) mm.DPtoLP(new Dimension(
DEFAULT_EMPTY_IMAGE_SIZE_PIXELS,
DEFAULT_EMPTY_IMAGE_SIZE_PIXELS));
}
/**
* @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() {
return MapModeUtil.getMapMode(getDiagramEditPart().getFigure());
}
/**
* 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() || figure.getBounds().isEmpty())
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();
DiagramImageUtils.translateTo(abBounds, figure, printableLayer);
// 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
*/
/*
* The 2 commented out methods are not being used currently
*/
// 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) {
Rectangle rect = DiagramImageUtils.calculateImageRectangle(editparts,
getImageMargin(), emptyImageSize);
return new org.eclipse.swt.graphics.Rectangle(rect.x, rect.y,
rect.width, rect.height);
}
/**
* 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) {
Map<String, Object> options = new HashMap<String, Object>();
Point origin = DiagramImageUtils.calculateImageRectangle(
diagramEditPart.getPrimaryEditParts(), getImageMargin(),
emptyImageSize).getLocation();
options.put(PartPositionInfoGenerator.CONNECTION_MARGIN,
new Double(getImageMargin() >> 1));
options.put(PartPositionInfoGenerator.DIAGRAM_ORIGIN, origin);
return PartPositionInfoGenerator.getDiagramPartInfo(diagramEditPart,
options);
}
public List<PartPositionInfo> getConstrainedDiagramPartInfo(int maxWidth,
int maxHeight, boolean useMargins) {
return getConstrainedDiagramPartInfo(_dgrmEP, maxWidth, maxHeight,
useMargins);
}
public List<PartPositionInfo> getConstrainedDiagramPartInfo(
DiagramEditPart diagramEditPart, int maxWidth, int maxHeight,
boolean useMargins) {
List<IGraphicalEditPart> children = (List<IGraphicalEditPart>) 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.
ConstrainedImageRenderingData data = getConstrainedImageRenderingData(
children, maxWidth, maxHeight, useMargins);
Rectangle imageRect = data.imageOriginalBounds.getCopy();
mm.DPtoLP(imageRect);
if (useMargins) {
imageRect.shrink(getImageMargin(), getImageMargin());
}
imageRect.performScale(data.scalingFactor);
if (useMargins) {
imageRect.expand(getImageMargin(), getImageMargin());
}
Map<String, Object> options = new HashMap<String, Object>();
options.put(PartPositionInfoGenerator.CONNECTION_MARGIN,
new Double(mm.DPtoLP(5)));
options.put(PartPositionInfoGenerator.DIAGRAM_ORIGIN, imageRect.getLocation());
options.put(PartPositionInfoGenerator.SCALE_FACTOR, new Double(data.scalingFactor));
return PartPositionInfoGenerator.getDiagramPartInfo(diagramEditPart, options);
}
/**
* @return <code>int</code> value that is the margin around the generated
* image in logical coordinates.
* @since 1.3
*/
public int getImageMargin() {
return image_margin;
}
/**
* Sets the image margin value (width of the white frame around the image).
* The value must be in logical units.
*
* @param imageMargin
* @since 1.3
*/
public void setImageMargin(int imageMargin) {
Assert.isTrue(imageMargin >= 0);
image_margin = imageMargin;
}
/**
* 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();
PrecisionRectangle rect = new PrecisionRectangle();
rect.setX(sourceRect.x);
rect.setY(sourceRect.y);
rect.setWidth(sourceRect.width);
rect.setHeight(sourceRect.height);
mm.LPtoDP(rect);
// Create the graphics and wrap it with the HiMetric graphics object
graphics = setUpGraphics((int) Math.round(rect.preciseWidth),
(int) Math.round(rect.preciseHeight));
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();
ConstrainedImageRenderingData data = getConstrainedImageRenderingData(
editParts, maxDeviceWidth, maxDeviceHeight, useMargins);
// Create the graphics and wrap it with the HiMetric graphics object
graphics = setUpGraphics(data.imageWidth, data.imageHeight);
ScaledGraphics scaledGraphics = new RenderedScaledGraphics(graphics);
RenderedMapModeGraphics mapModeGraphics = new RenderedMapModeGraphics(
scaledGraphics, getMapMode());
graphics.translate(data.margin, data.margin);
mapModeGraphics.scale(data.scalingFactor);
Point location = new PrecisionPoint(data.imageOriginalBounds
.preciseX(), data.imageOriginalBounds.preciseY());
mm.DPtoLP(location);
renderToGraphics(mapModeGraphics, location, editParts);
imageDesc = getImageDescriptor(graphics);
} finally {
if (graphics != null)
disposeGraphics(graphics);
}
return imageDesc;
}
class ConstrainedImageRenderingData {
double scalingFactor;
int imageWidth; // in pixels
int imageHeight; // in pixels
Rectangle imageOriginalBounds; // in pixels
int margin; // margins size in pixels
}
ConstrainedImageRenderingData getConstrainedImageRenderingData(
List editParts, int maxDeviceWidth, int maxDeviceHeight,
boolean useMargins) {
ConstrainedImageRenderingData data = new ConstrainedImageRenderingData();
IMapMode mm = getMapMode();
data.imageOriginalBounds = new PrecisionRectangle(new Rectangle(
calculateImageRectangle(editParts)));
mm.LPtoDP(data.imageOriginalBounds);
int deviceMargins = mm.LPtoDP(getImageMargin());
data.margin = useMargins ? deviceMargins : 0;
double xScalingFactor = 1.0, yScalingFactor = xScalingFactor;
data.imageOriginalBounds.shrink(deviceMargins, deviceMargins);
if (maxDeviceWidth > data.margin) {
xScalingFactor = (maxDeviceWidth - data.margin - data.margin)
/ (data.imageOriginalBounds.preciseWidth());
}
if (maxDeviceHeight > data.margin) {
yScalingFactor = (maxDeviceHeight - data.margin - data.margin)
/ (data.imageOriginalBounds.preciseHeight());
}
data.scalingFactor = Math.min(Math.min(xScalingFactor, yScalingFactor),
1);
data.imageWidth = data.imageOriginalBounds.width + data.margin
+ data.margin;
data.imageHeight = data.imageOriginalBounds.height + data.margin
+ data.margin;
if (data.scalingFactor < 1) {
data.imageWidth = (int) Math.round(data.imageOriginalBounds
.preciseWidth()
* data.scalingFactor)
+ data.margin + data.margin;
data.imageHeight = (int) Math.round(data.imageOriginalBounds
.preciseHeight()
* data.scalingFactor)
+ data.margin + data.margin;
} else {
data.scalingFactor = 1;
}
return data;
}
/**
* 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;
}
}