/*****************************************************************************
* Copyright (c) 2010 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:
* Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.menu.actions;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.editparts.ZoomManager;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.internal.actions.ZoomContributionItem;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
/**
*
* A part of this code comes from {@link ZoomContributionItem}
*
*
*/
@SuppressWarnings("restriction")
public class ZoomAction extends AbstractParametricAction {//extends Action
/**
* Custom zoom operations
*/
public static final String ZOOM_IN = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomIn;
public static final String ZOOM_OUT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomOut;
public static final String ZOOM_100 = DiagramUIMessages.ZoomAction_ZoomCombo_Zoom100;
public static final String ZOOM_FIT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToFit;
public static final String ZOOM_WIDTH = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToWidth;
public static final String ZOOM_HEIGHT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToHeight;
public static final String ZOOM_SELECTION = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToSelection;
/**
* Zoom parameters
*/
public static final String ZOOM_IN_PARAMETER = "parameter_zoom_in"; //$NON-NLS-1$
public static final String ZOOM_OUT_PARAMETER = "parameter_zoom_out";//$NON-NLS-1$
public static final String ZOOM_100_PARAMETER = "parameter_zoom_100";//$NON-NLS-1$
public static final String ZOOM_FIT_PARAMETER = "parameter_zoom_fit";//$NON-NLS-1$
public static final String ZOOM_WIDTH_PARAMETER = "parameter_zoom_width";//$NON-NLS-1$
public static final String ZOOM_HEIGHT_PARAMETER = "parameter_zoom_height";//$NON-NLS-1$
public static final String ZOOM_SELECTION_PARAMETER = "parameter_zoom_selection";//$NON-NLS-1$
/**
*
* Constructor.
*
* @param parameter
* parameter for the zoom action
* Parameters can value :
* <ul>
* <li>#ZOOM_IN_PARAMETER</li>
* <li>#ZOOM_OUT_PARAMETER</li>
* <li>#ZOOM_100_PARAMETER</li>
* <li>#ZOOM_FIT_PARAMETER</li>
* <li>#ZOOM_WIDTH_PARAMETER</li>
* <li>#ZOOM_HEIGHT_PARAMETER</li>
* <li>#ZOOM_SELECTION_PARAMETER</li>
* <li>a number as String (with % at end or not)</li>
* </ul>
*
* @param selectedElements
* the selected element for the zoom action
*/
public ZoomAction(String parameter, List<IGraphicalEditPart> selectedElements) {
super(parameter, selectedElements);
}
/**
*
* @see org.eclipse.jface.action.Action#isEnabled()
*
* @return
*/
@Override
public boolean isEnabled() {
return isValid(getParameter());
}
/**
* <code>false</code> if not
*
* @param zoomText
* the new zoom value
* @return
* <code>true</code> if the zoomText is a correct value
*/
protected boolean isValid(String zoomText) {
//we test if we are in a diagram
DiagramEditPart diagramEP = getDiagramEditPart();
if(diagramEP == null) {
return false;
}
if(zoomText.equals(ZoomAction.ZOOM_IN_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_OUT_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_100_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_FIT_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_WIDTH_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_HEIGHT_PARAMETER)) {
return true;
} else if(zoomText.equals(ZOOM_SELECTION_PARAMETER)) {
return true;
} else {
StringBuffer buffer = new StringBuffer(zoomText);
while(buffer.indexOf("%") != -1) {//$NON-NLS-1$
int index = buffer.indexOf("%");//$NON-NLS-1$
buffer.deleteCharAt(index);
}
try {
Double.parseDouble(buffer.toString());
} catch (Exception e) {
return false;
}
return true;
}
}
/**
*
* @see org.eclipse.jface.action.Action#run()
*
*/
@Override
public void doRun(IProgressMonitor progressMonitor) {
if(isEnabled()) {
String parameter = getParameter();
getZoomManager();
if(parameter.equals(ZOOM_IN_PARAMETER)) {
getZoomManager().zoomIn();
} else if(parameter.equals(ZOOM_OUT_PARAMETER)) {
getZoomManager().zoomOut();
} else if(parameter.equals(ZOOM_100_PARAMETER)) {
getZoomManager().setZoom(1);
} else if(parameter.equals(ZOOM_FIT_PARAMETER)) {
zoomToFit(true, true, false);
} else if(parameter.equals(ZOOM_WIDTH_PARAMETER)) {
zoomToFit(true, false, false);
} else if(parameter.equals(ZOOM_HEIGHT_PARAMETER)) {
zoomToFit(false, true, false);
} else if(parameter.equals(ZOOM_SELECTION_PARAMETER)) {
zoomToFit(true, true, true);
} else {
getZoomManager().setZoomAsText(parameter);//to set a specific value to zoom
}
}
}
/**
* Performs the zoom operation. Always zooms when possible.
*
* @param onWidth
* true to perform zoom on the width
* @param onHeight
* true to perform zoom on the height
* @param selectionOnly
* true to only zoom the selected items, false to zoom the entire
* diagram
*/
protected void zoomToFit(boolean onWidth, boolean onHeight, boolean selectionOnly) {
zoomToFit(onWidth, onHeight, selectionOnly, false);
}
/**
* Performs the zoom operation.
*
* @param onWidth
* true to perform zoom on the width
* @param onHeight
* true to perform zoom on the height
* @param selectionOnly
* true to only zoom the selected items, false to zoom the entire
* diagram
* @param zoomOutOnly
* true to only zoom out and avoid zooming to greater than 100%,
* false to always zoom even if it could make the shapes on the
* diagram very large
*/
@SuppressWarnings("unchecked")
protected void zoomToFit(boolean onWidth, boolean onHeight, boolean selectionOnly, boolean zoomOutOnly) {
Iterator<?> editParts;
if(selectionOnly) {
editParts = getSelection().iterator();
} else {
List<?> allEditParts = getDiagramEditPart().getConnections();
allEditParts.addAll(getDiagramEditPart().getChildrenAffectingZoom());
editParts = allEditParts.iterator();
}
Rectangle targetRegion = null;
while(editParts.hasNext()) {
IFigure f = ((GraphicalEditPart)editParts.next()).getFigure();
targetRegion = targetRegion == null ? f.getBounds().getCopy() : targetRegion.getUnion(f.getBounds());
}
// IF nothing to Zoom...
if(targetRegion == null) {
// do nothing
return;
}
// Translate the region into pixels
MapModeUtil.getMapMode(getDiagramEditPart().getFigure()).LPtoDP(targetRegion);
Viewport viewport = getZoomManager().getViewport();
float xratio = viewport.getHorizontalRangeModel().getExtent() / (float)targetRegion.width;
float yratio = viewport.getVerticalRangeModel().getExtent() / (float)targetRegion.height;
double zoom = 1.0;
if(onHeight && onWidth) {
zoom = (yratio < xratio) ? Math.floor(yratio * 100) : Math.floor(xratio * 100);
} else if(onWidth) {
zoom = Math.floor(xratio * 100);
} else if(onHeight) {
zoom = Math.floor(yratio * 100);
}
if(zoomOutOnly && zoom >= 100) {
// we should always continue in order to set the viewport
// location
zoom = 100;
}
// apply thresholds
Point topLeft = targetRegion.getTopLeft();
zoom = Math.min((int)(getZoomManager().getMaxZoom() * 100), Math.max((int)(getZoomManager().getMinZoom() * 100), zoom));
int viewX = Math.round(topLeft.x * (float)zoom / 100.0f);
int viewY = Math.round(topLeft.y * (float)zoom / 100.0f);
getZoomManager().setZoom(zoom / 100);
viewport.setHorizontalLocation(viewX);
viewport.setVerticalLocation(viewY);
}
/**
* Returns the current zoom manager
*
* @return
* the current zoom manager
*/
protected ZoomManager getZoomManager() {
return (ZoomManager)getDiagramWorkbenchPart().getAdapter(ZoomManager.class);
}
}