/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.policy;
import java.util.List;
import org.eclipse.draw2d.FreeformFigure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.xmind.gef.GEF;
import org.xmind.gef.IGraphicalViewer;
import org.xmind.gef.IViewer;
import org.xmind.gef.Request;
import org.xmind.gef.ZoomManager;
import org.xmind.gef.draw2d.geometry.Geometry;
import org.xmind.gef.draw2d.geometry.PrecisionPoint;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
/**
* @author Brian Sun
*/
public class ScalableEditPolicy extends AbstractEditPolicy {
public boolean understands(String requestType) {
return super.understands(requestType)
|| GEF.REQ_ZOOM.equals(requestType)
|| GEF.REQ_ZOOMIN.equals(requestType)
|| GEF.REQ_ZOOMOUT.equals(requestType)
|| GEF.REQ_ACTUALSIZE.equals(requestType)
|| GEF.REQ_FITSIZE.equals(requestType)
|| GEF.REQ_FITSELECTION.equals(requestType);
}
/**
* @see org.xmind.gef.policy.Policy#handle(org.xmind.gef.Request)
*/
public void handle(Request req) {
String type = req.getType();
if (GEF.REQ_ZOOM.equals(type)) {
performZoomRequest(req);
} else if (GEF.REQ_ZOOMIN.equals(type)) {
performZoomIn(getGraphicalViewer(req));
} else if (GEF.REQ_ZOOMOUT.equals(type)) {
performZoomOut(getGraphicalViewer(req));
} else if (GEF.REQ_ACTUALSIZE.equals(type)) {
performActualSize(getGraphicalViewer(req));
} else if (GEF.REQ_FITSIZE.equals(type)) {
performFitSize(getGraphicalViewer(req));
} else if (GEF.REQ_FITSELECTION.equals(type)) {
performFitSelection(req);
}
}
protected IGraphicalViewer getGraphicalViewer(Request req) {
IViewer viewer = req.getTargetViewer();
if (viewer != null && viewer instanceof IGraphicalViewer) {
return (IGraphicalViewer) viewer;
}
return null;
}
protected void preserveCenter(final Runnable action,
IGraphicalViewer viewer) {
PrecisionPoint center = viewer == null ? null
: new PrecisionPoint(viewer.getCenterPoint());
if (center != null && viewer != null) {
center.scale(1 / viewer.getZoomManager().getScale());
}
try {
action.run();
} finally {
if (viewer != null && center != null) {
if (viewer.getZoomManager() != null)
center.scale(viewer.getZoomManager().getScale());
viewer.center(center.toDraw2DPoint());
}
}
}
/**
*
*/
protected void performZoomOut(IGraphicalViewer viewer) {
if (viewer == null)
return;
final ZoomManager zoomManager = viewer.getZoomManager();
preserveCenter(new Runnable() {
public void run() {
zoomManager.zoomOut();
}
}, viewer);
}
/**
*
*/
protected void performZoomIn(final IGraphicalViewer viewer) {
if (viewer == null)
return;
preserveCenter(new Runnable() {
public void run() {
viewer.getZoomManager().zoomIn();
}
}, viewer);
}
/**
*
*/
protected void performActualSize(final IGraphicalViewer viewer) {
if (viewer == null)
return;
viewer.getZoomManager().actualSize();
viewer.center(0, 0);
}
/**
* @param request
*/
protected void performZoomRequest(Request request) {
Object param = request.getParameter(GEF.PARAM_ZOOM_SCALE);
if (param == null || !(param instanceof Double))
return;
final double scale = ((Double) param).doubleValue();
final IGraphicalViewer viewer = getGraphicalViewer(request);
if (viewer == null)
return;
preserveCenter(new Runnable() {
public void run() {
viewer.getZoomManager().setScale(scale);
}
}, viewer);
}
protected void performFitSize(final IGraphicalViewer viewer) {
if (viewer == null)
return;
final Rectangle bounds = getContentsBounds(viewer);
if (bounds != null) {
fitBounds(viewer, bounds, viewer.getZoomManager());
}
}
protected void fitBounds(final IGraphicalViewer viewer,
final Rectangle bounds, final ZoomManager zoomManager) {
IFigure viewport = ((IGraphicalViewer) viewer).getCanvas()
.getViewport();
Dimension viewportSize = getViewportSize(viewer, viewport, zoomManager);
zoomManager.fitScale(viewportSize, bounds.getSize());
bounds.getCenter().scale(zoomManager.getScale());
viewport.getUpdateManager().runWithUpdate(new Runnable() {
public void run() {
viewer.center(
bounds.getCopy().scale(zoomManager.getScale() * 2));
}
});
}
protected Dimension getViewportSize(IGraphicalViewer viewer,
IFigure viewport, ZoomManager zoomManager) {
return viewport.getSize();
}
protected void ensureVisible(IGraphicalViewer viewer, Rectangle bounds) {
viewer.ensureVisible(bounds);
}
protected Rectangle getContentsBounds(IGraphicalViewer viewer) {
return getBounds(viewer.getRootPart().getContents());
}
protected Rectangle getBounds(IPart p) {
if (p != null && p.getStatus().isActive()
&& p instanceof IGraphicalPart) {
IFigure figure = ((IGraphicalPart) p).getFigure();
if (figure != null) {
if (figure instanceof FreeformFigure)
return ((FreeformFigure) figure).getFreeformExtent();
return figure.getBounds();
}
}
return null;
}
protected void performFitSelection(Request req) {
final IGraphicalViewer viewer = getGraphicalViewer(req);
if (viewer == null)
return;
List<IPart> selectedParts = req.getTargets();
if (selectedParts.isEmpty()) {
selectedParts = viewer.getSelectionSupport().getPartSelection();
}
if (selectedParts.isEmpty())
return;
final Rectangle bounds = getSelectionBounds(viewer, selectedParts);
if (bounds != null) {
fitBounds(viewer, bounds, viewer.getZoomManager());
}
}
protected Rectangle getSelectionBounds(IGraphicalViewer viewer,
List<? extends IPart> parts) {
Rectangle r = null;
for (IPart p : parts) {
r = Geometry.union(r, getBounds(p));
}
return r;
}
}