blob: a7c8c0b2c5943dc94eca65e95b320da30ae57cdb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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.gef.editparts;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.ExposeHelper;
import org.eclipse.gef.GraphicalEditPart;
/**
* An implementation of <code>ExposeHelper</code> for use with editparts using a
* <code>Viewport</code>.
*
* @author hudsonr
* @since 2.0
*/
public class ViewportExposeHelper extends ViewportHelper implements
ExposeHelper {
private Insets exposeMargin;
private int minimumFrameCount = 3;
private int maximumFrameCount = 8;
/**
* Constructs a new ViewportExposeHelper on the specified GraphicalEditPart.
* The GraphicalEditPart must have a <code>Viewport</code> somewhere between
* its <i>contentsPane</i> and its <i>figure</i> inclusively.
*
* @param owner
* the GraphicalEditPart that owns the Viewport
*/
public ViewportExposeHelper(GraphicalEditPart owner) {
super(owner);
}
/**
* Exposes the descendant EditPart by smoothly scrolling the
* <code>Viewport</code>. The smoothness is determined by the minimum and
* maximum frame count, and the overall amount being scrolled.
*
* @see org.eclipse.gef.ExposeHelper#exposeDescendant(EditPart)
*/
public void exposeDescendant(EditPart part) {
Viewport port = findViewport(owner);
if (port == null)
return;
IFigure target = ((GraphicalEditPart) part).getFigure();
/*
* All calculations are done relative to the contents of the viewport.
* The expose margin is added in absolute coordinates, and then taken
* back to relative viewport coordinates.
*/
Rectangle exposeRegion = target.getBounds().getCopy();
target.translateToAbsolute(exposeRegion);
if (exposeMargin != null)
exposeRegion.expand(exposeMargin);
port.getContents().translateToRelative(exposeRegion);
Point offset = port.getContents().getBounds().getLocation();
// By substracting the offset, the region is now the difference from the
// contents origin.
exposeRegion.translate(offset.negate());
exposeRegion.translate(port.getHorizontalRangeModel().getMinimum(),
port.getVerticalRangeModel().getMinimum());
Dimension viewportSize = port.getClientArea().getSize();
Point topLeft = exposeRegion.getTopLeft();
Point bottomRight = exposeRegion.getBottomRight().translate(
viewportSize.getNegated());
Point finalLocation = new Point();
if (viewportSize.width < exposeRegion.width)
finalLocation.x = Math.min(bottomRight.x,
Math.max(topLeft.x, port.getViewLocation().x));
else
finalLocation.x = Math.min(topLeft.x,
Math.max(bottomRight.x, port.getViewLocation().x));
if (viewportSize.height < exposeRegion.height)
finalLocation.y = Math.min(bottomRight.y,
Math.max(topLeft.y, port.getViewLocation().y));
else
finalLocation.y = Math.min(topLeft.y,
Math.max(bottomRight.y, port.getViewLocation().y));
Point startLocation = port.getViewLocation();
int dx = finalLocation.x - startLocation.x;
int dy = finalLocation.y - startLocation.y;
int frames = (Math.abs(dx) + Math.abs(dy)) / 15;
frames = Math.max(frames, getMinimumFrameCount());
frames = Math.min(frames, getMaximumFrameCount());
int stepX = Math.min((dx / frames), (viewportSize.width / 3));
int stepY = Math.min((dy / frames), (viewportSize.height / 3));
for (int i = 1; i < frames; i++) {
port.setViewLocation(startLocation.x + stepX * i, startLocation.y
+ stepY * i);
port.getUpdateManager().performUpdate();
}
port.setViewLocation(finalLocation);
}
/**
* Returns the maximumFrameCount.
*
* @return int
*/
public int getMaximumFrameCount() {
return maximumFrameCount;
}
/**
* Returns the minimumFrameCount.
*
* @return int
*/
public int getMinimumFrameCount() {
return minimumFrameCount;
}
/**
* Sets the amount of margin to be left around the descendant being exposed.
* There is no margin by default.
*
* @param margin
* the margin in pixels
*/
public void setMargin(Insets margin) {
exposeMargin = margin;
}
/**
* Sets the maximumFrameCount.
*
* @param maximumFrameCount
* The maximumFrameCount to set
*/
public void setMaximumFrameCount(int maximumFrameCount) {
this.maximumFrameCount = maximumFrameCount;
}
/**
* Sets the minimumFrameCount.
*
* @param minimumFrameCount
* The minimumFrameCount to set
*/
public void setMinimumFrameCount(int minimumFrameCount) {
this.minimumFrameCount = minimumFrameCount;
if (getMaximumFrameCount() < minimumFrameCount)
setMaximumFrameCount(minimumFrameCount);
}
}