| /****************************************************************************** |
| * Copyright (c) 2002, 2009 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.internal.actions; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| 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.Request; |
| import org.eclipse.gef.editparts.ZoomListener; |
| import org.eclipse.gef.editparts.ZoomManager; |
| import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds; |
| import org.eclipse.gmf.runtime.diagram.ui.internal.l10n.DiagramUIPluginImages; |
| import org.eclipse.gmf.runtime.diagram.ui.internal.util.IUIConstants; |
| import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; |
| import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.MenuItem; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| |
| /** |
| * @author melaasar |
| * @canBeSeenBy %level1 |
| * |
| * To change the template for this generated type comment go to |
| * Window>Preferences>Java>Code Generation>Code and Comments |
| */ |
| public class ZoomContributionItem extends CustomContributionItem implements ZoomListener, Listener { |
| |
| /** |
| * Custom zoom operations |
| */ |
| private static final String ZOOM_IN = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomIn; |
| |
| private static final String ZOOM_OUT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomOut; |
| |
| private static final String ZOOM_100 = DiagramUIMessages.ZoomAction_ZoomCombo_Zoom100; |
| |
| private static final String ZOOM_FIT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToFit; |
| |
| private static final String ZOOM_WIDTH = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToWidth; |
| |
| private static final String ZOOM_HEIGHT = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToHeight; |
| |
| private static final String ZOOM_SELECTION = DiagramUIMessages.ZoomAction_ZoomCombo_ZoomToSelection; |
| |
| private static final String ZOOM_IN_ACTION = DiagramUIMessages.ZoomAction_ZoomIn; |
| |
| private static final String ZOOM_OUT_ACTION = DiagramUIMessages.ZoomAction_ZoomOut; |
| |
| private static final String ZOOM_100_ACTION = DiagramUIMessages.ZoomAction_Zoom100; |
| |
| private static final String ZOOM_FIT_ACTION = DiagramUIMessages.ZoomAction_ZoomToFit; |
| |
| private static final String ZOOM_WIDTH_ACTION = DiagramUIMessages.ZoomAction_ZoomToWidth; |
| |
| private static final String ZOOM_HEIGHT_ACTION = DiagramUIMessages.ZoomAction_ZoomToHeight; |
| |
| private static final String ZOOM_SELECTION_ACTION = DiagramUIMessages.ZoomAction_ZoomToSelection; |
| |
| /** |
| * The part's zoom manager |
| */ |
| private ZoomManager zoomManager; |
| |
| /** |
| * The zoom image |
| */ |
| private List<Image> zoomImages = new ArrayList<Image>(); |
| |
| /** |
| * constructor |
| * |
| * @param workbenchPage |
| * the workbench page |
| */ |
| public ZoomContributionItem(IWorkbenchPage workbenchPage) { |
| super(workbenchPage, ActionIds.CUSTOM_ZOOM); |
| setLabel(DiagramUIMessages.ZoomActionMenu_ZoomLabel); |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.diagram.ui.internal.actions.CustomContributionItem#createTargetRequest() |
| */ |
| protected Request createTargetRequest() { |
| return null; |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.common.ui.action.AbstractContributionItem#setWorkbenchPart(org.eclipse.ui.IWorkbenchPart) |
| */ |
| protected void setWorkbenchPart(IWorkbenchPart workbenchPart) { |
| super.setWorkbenchPart(workbenchPart); |
| if (workbenchPart != null) |
| setZoomManager((ZoomManager) workbenchPart.getAdapter(ZoomManager.class)); |
| } |
| |
| /** |
| * Returns true if the operation set is not empty and only if the diagram is |
| * selected. |
| * |
| * @see org.eclipse.gmf.runtime.common.ui.action.AbstractContributionItem#calculateEnabled() |
| */ |
| protected boolean calculateEnabled() { |
| return getZoomManager() != null; |
| } |
| |
| /** |
| * Returns the zoomManager. |
| * |
| * @return ZoomManager |
| */ |
| public ZoomManager getZoomManager() { |
| return zoomManager; |
| } |
| |
| /** |
| * Sets the ZoomManager |
| * |
| * @param zm |
| * The ZoomManager |
| */ |
| public void setZoomManager(ZoomManager zm) { |
| if (zoomManager == zm) |
| return; |
| if (zoomManager != null) |
| zoomManager.removeZoomListener(this); |
| |
| zoomManager = zm; |
| update(); |
| |
| if (zoomManager != null) |
| zoomManager.addZoomListener(this); |
| } |
| |
| /** |
| * @see org.eclipse.jface.action.ContributionItem#dispose() |
| */ |
| public void dispose() { |
| if (getZoomManager() != null) { |
| getZoomManager().removeZoomListener(this); |
| zoomManager = null; |
| } |
| for (Image image : zoomImages) { |
| image.dispose(); |
| } |
| zoomImages.clear(); |
| super.dispose(); |
| } |
| |
| /** |
| * @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double) |
| */ |
| public void zoomChanged(double zoom) { |
| update(); |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.common.ui.action.AbstractContributionItem#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| protected Control createControl(Composite parent) { |
| Combo combo = new Combo(parent, SWT.DROP_DOWN); |
| combo.addListener(SWT.Selection, this); |
| combo.addListener(SWT.KeyDown, this); |
| combo.setItems(getZoomLevelsAsText()); |
| combo.setVisibleItemCount(IUIConstants.DEFAULT_DROP_DOWN_SIZE); |
| return combo; |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.common.ui.action.AbstractContributionItem#createMenuItem(org.eclipse.swt.widgets.Menu, |
| * int) |
| */ |
| protected MenuItem createMenuItem(Menu parent, int index) { |
| MenuItem mi = index >= 0 ? new MenuItem(parent, SWT.CASCADE, index) : new MenuItem(parent, SWT.CASCADE); |
| createMenu(mi); |
| mi.setImage(DiagramUIPluginImages.get(DiagramUIPluginImages.IMG_ZOOM_IN)); |
| return mi; |
| } |
| |
| /** |
| * Creates the zoom menu |
| * |
| * @param mi |
| */ |
| private void createMenu(MenuItem mi) { |
| Menu menu = new Menu(mi.getParent()); |
| createMenuItem(menu, ZOOM_IN_ACTION, ZOOM_IN, DiagramUIPluginImages.DESC_ZOOM_IN); |
| createMenuItem(menu, ZOOM_OUT_ACTION, ZOOM_OUT, DiagramUIPluginImages.DESC_ZOOM_OUT); |
| createMenuItem(menu, ZOOM_100_ACTION, ZOOM_100, DiagramUIPluginImages.DESC_ZOOM_100); |
| createMenuItem(menu, ZOOM_FIT_ACTION, ZOOM_FIT, DiagramUIPluginImages.DESC_ZOOM_TOFIT); |
| createMenuItem(menu, ZOOM_WIDTH_ACTION, ZOOM_WIDTH, DiagramUIPluginImages.DESC_ZOOM_TOFIT); |
| createMenuItem(menu, ZOOM_HEIGHT_ACTION, ZOOM_HEIGHT, DiagramUIPluginImages.DESC_ZOOM_TOFIT); |
| createMenuItem(menu, ZOOM_SELECTION_ACTION, ZOOM_SELECTION, DiagramUIPluginImages.DESC_ZOOM_TOFIT); |
| mi.setMenu(menu); |
| } |
| |
| /** |
| * Creates a menu item with a given text and image with the push style |
| * |
| * @param menu |
| * The menu |
| * @param text |
| * The menu item text |
| * @param data |
| * The callback data to determine which zoom action to take |
| * @param imageDescriptor |
| * The menu item image |
| * @return mentu item |
| */ |
| private MenuItem createMenuItem(Menu menu, String text, String data, ImageDescriptor imageDescriptor) { |
| MenuItem mi = new MenuItem(menu, SWT.PUSH); |
| mi.setText(text); |
| mi.setData(data); |
| if (imageDescriptor != null) |
| mi.setImage(createImage(imageDescriptor)); |
| mi.addListener(SWT.Selection, this); |
| return mi; |
| } |
| |
| /** |
| * Get the zoom levels as text string array from the zoom manager. |
| * |
| * @return String array with zoom levels. |
| * |
| * @see org.eclipse.gef.editparts.ZoomManager#getZoomLevelsAsText() |
| */ |
| public String[] getZoomLevelsAsText() { |
| int nNumericZoomLevels = (getZoomManager() != null) ? getZoomManager().getZoomLevels().length : 0; |
| String[] allZoomLevels = new String[nNumericZoomLevels + 6]; |
| |
| allZoomLevels[0] = ZOOM_IN; |
| allZoomLevels[1] = ZOOM_OUT; |
| allZoomLevels[2] = ZOOM_FIT; |
| allZoomLevels[3] = ZOOM_WIDTH; |
| allZoomLevels[4] = ZOOM_HEIGHT; |
| allZoomLevels[5] = ZOOM_SELECTION; |
| |
| if (getZoomManager() != null) { |
| String[] numericZoomLevels = getZoomManager().getZoomLevelsAsText(); |
| for (int i = 0; i < getZoomManager().getZoomLevels().length; i++) { |
| allZoomLevels[i + 6] = numericZoomLevels[i]; |
| } |
| } |
| |
| return allZoomLevels; |
| } |
| |
| /** |
| * @see org.eclipse.gmf.runtime.common.ui.action.AbstractContributionItem#refreshItem() |
| */ |
| protected void refreshItem() { |
| if (getZoomManager() != null) { |
| if (getControl() != null) { |
| Combo combo = (Combo) getControl(); |
| combo.setItems(getZoomLevelsAsText()); |
| String zoom = getZoomManager().getZoomAsText(); |
| int index = combo.indexOf(zoom); |
| if (index != -1) |
| combo.select(index); |
| else |
| combo.setText(zoom); |
| } |
| } |
| super.refreshItem(); |
| } |
| |
| /** |
| * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) |
| */ |
| public void handleEvent(Event event) { |
| // Enter is commonly known as ascii 13 on all platforms. To prevent |
| // casting, this is the same as \r. |
| if (event.type == SWT.KeyDown && event.character != '\r') |
| return; |
| if (getControl() != null) |
| setZoomAsText(((Combo) getControl()).getText()); |
| else |
| setZoomAsText((String) event.widget.getData()); |
| } |
| |
| /** |
| * Sets the zoom level to the zoom string using the zoom manager. First, it |
| * checks for the special cases. If it isn't one of the special cases, it |
| * uses the zoom manager to do the zooming. There are six special cases, |
| * zoom to fit, zoom in, zoom out, zoom to width, zoom to height, and zoom |
| * to selected shapes. |
| * |
| * @param zoomText |
| * the zoom string which we will zoom to. |
| * @see org.eclipse.gef.editparts.ZoomManager#setZoomAsText(java.lang.String) |
| */ |
| public void setZoomAsText(String zoomText) { |
| if (ZOOM_IN.equals(zoomText)) |
| getZoomManager().zoomIn(); |
| else if (ZOOM_OUT.equals(zoomText)) |
| getZoomManager().zoomOut(); |
| else if (ZOOM_100.equals(zoomText)) |
| getZoomManager().setZoom(1); |
| else if (ZOOM_FIT.equals(zoomText)) |
| zoomToFit(true, true, false); |
| else if (ZOOM_WIDTH.equals(zoomText)) |
| zoomToFit(true, false, false); |
| else if (ZOOM_HEIGHT.equals(zoomText)) |
| zoomToFit(false, true, false); |
| else if (ZOOM_SELECTION.equals(zoomText)) |
| zoomToFit(true, true, true); |
| else |
| getZoomManager().setZoomAsText(zoomText); |
| } |
| |
| /** |
| * 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 |
| */ |
| protected void zoomToFit(boolean onWidth, boolean onHeight, boolean selectionOnly, boolean zoomOutOnly) { |
| |
| Iterator editParts; |
| if (selectionOnly) { |
| editParts = getStructuredSelection().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) (zoomManager.getMaxZoom() * 100), Math.max((int) (zoomManager.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); |
| |
| // always refresh the zoom text when zoom to fit, |
| // required when the zoom percentage did not change but we wish |
| // to display the text as a percentage. |
| update(); |
| } |
| |
| /** |
| * Creates an image and caches it |
| * |
| * @param descriptor |
| * @return image |
| */ |
| private Image createImage(ImageDescriptor descriptor) { |
| int index = zoomImages.indexOf(descriptor); |
| if (index != -1) |
| return zoomImages.get(index); |
| Image image = descriptor.createImage(); |
| zoomImages.add(image); |
| return image; |
| } |
| |
| } |