/*****************************************************************************
* 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.toolbar;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.gef.editparts.ZoomListener;
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.internal.util.IUIConstants;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.infra.core.editor.CoreMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.sasheditor.editor.IPage;
import org.eclipse.papyrus.infra.core.sasheditor.editor.ISashWindowsContainer;
import org.eclipse.papyrus.uml.diagram.common.Activator;
import org.eclipse.papyrus.uml.diagram.menu.actions.ZoomAction;
import org.eclipse.papyrus.uml.diagram.menu.messages.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
/**
* This class provides a Combo box in the toolbar for the Zoom Action
* This Combo is automatically refresh when the zoom changed
*
* A part of this code comes from {@link ZoomContributionItem}
*/
@SuppressWarnings("restriction")
public class ZoomToolbar extends ContributionItem implements ZoomListener, Listener, org.eclipse.papyrus.infra.core.sasheditor.editor.IPageChangedListener {
/** the combo box */
protected Combo combo = null;
/**
* the part service
*/
private IPartService partService = null;
/**
* the listener for the part service
*/
private IPartListener partListener = null;
/**
*
* Constructor.
*
*/
public ZoomToolbar() {
this(""); //$NON-NLS-1$
}
/**
*
* Constructor.
*
* @param id
*/
public ZoomToolbar(String id) {
super(id);
init();
}
/**
*
* @see org.eclipse.jface.action.ContributionItem#dispose()
*
*/
@Override
public void dispose() {
super.dispose();
if(this.partService != null) {
this.partService.removePartListener(this.partListener);
}
}
/**
* Adds a listener on the part Service and refresh the value displayed in the Combo
*
*/
protected void init() {
addPartListener();
refreshCombo();
}
/**
* adds the part listener
*/
protected void addPartListener() {
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow activeWorkbench = workbench.getActiveWorkbenchWindow();
if(activeWorkbench != null) {
partService = activeWorkbench.getPartService();
if(partService != null) {
this.partListener = new CustomPartListener();
partService.addPartListener(this.partListener);
}
}
}
/**
*
* @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.ToolBar, int)
*
* @param parent
* @param index
*/
@Override
public void fill(ToolBar parent, int index) {
ToolItem toolItem = new ToolItem(parent, SWT.SEPARATOR);
Image zoomImage = Activator.getPluginIconImage("org.eclipse.papyrus.uml.diagram.menu", "/icons/zoomplus.gif"); //$NON-NLS-1$ //$NON-NLS-2$
/*
* TODO : the image is not set, when we use SWT.SEPARATOR.
* It's a SWT bug.
* This image is used in the Perspective Customization
* That works fine with SWT.PUSH, SWT.PULL_DOWN, ..., but in this case it's the zoom which doesn't work
*/
toolItem.setImage(zoomImage);
//this text is used in the perspective customization
toolItem.setToolTipText(Messages.ZoomToolbar_Zoom);
combo = new Combo(parent, SWT.DROP_DOWN);
combo.setItems(getZoomLevelsAsText(getZoomManager()));
combo.setVisibleItemCount(IUIConstants.DEFAULT_DROP_DOWN_SIZE);
combo.pack();
toolItem.setWidth(combo.getSize().x);
toolItem.setControl(combo);
combo.addListener(SWT.Selection, this);
combo.addListener(SWT.KeyDown, this);
//the combo is created each time that we change table!
combo.setEnabled(getDiagramEditPart() != null);
refreshCombo();
parent.pack();
}
/**
*
* @see org.eclipse.jface.action.ContributionItem#isDynamic()
*
* @return
*/
@Override
public boolean isDynamic() {
return true;
}
/**
* 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(ZoomManager manager) {
int nNumericZoomLevels = 0;
if(manager != null) {
nNumericZoomLevels = manager.getZoomLevels().length;
}
String[] allZoomLevels = new String[nNumericZoomLevels + 6];
allZoomLevels[0] = ZoomAction.ZOOM_IN;
allZoomLevels[1] = ZoomAction.ZOOM_OUT;
allZoomLevels[2] = ZoomAction.ZOOM_FIT;
allZoomLevels[3] = ZoomAction.ZOOM_WIDTH;
allZoomLevels[4] = ZoomAction.ZOOM_HEIGHT;
allZoomLevels[5] = ZoomAction.ZOOM_SELECTION;
if(manager != null) {
String[] numericZoomLevels = manager.getZoomLevelsAsText();
for(int i = 0; i < manager.getZoomLevels().length; i++) {
allZoomLevels[i + 6] = numericZoomLevels[i];
}
}
return allZoomLevels;
}
/**
* Retrieves the value of the <code>workbenchPart</code> instance
* variable.
*
* @return The value of the <code>workbenchPart</code> instance variable.
*/
protected IDiagramWorkbenchPart getWorkbenchPart() {
IWorkbenchPart part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart();
if(part instanceof IDiagramWorkbenchPart) {
return (IDiagramWorkbenchPart)part;
}
return null;
}
/**
* A utility method to return the active part if it implements the <code>IDiagramWorkbenchPart</code> interface
*
* @return The current part if it implements <code>IDiagramWorkbenchPart</code>; <code>null</code> otherwise
*/
protected IDiagramWorkbenchPart getDiagramWorkbenchPart() {
return getWorkbenchPart() instanceof IDiagramWorkbenchPart ? (IDiagramWorkbenchPart)getWorkbenchPart() : null;
}
/**
* A utility method to return the active <code>DiagramEditPart</code> if the current part implements <code>IDiagramWorkbenchPart</code>
*
* @return The current diagram if the parts implements <code>IDiagramWorkbenchPart</code>; <code>null</code> otherwise
*/
protected DiagramEditPart getDiagramEditPart() {
IDiagramWorkbenchPart editor = getDiagramWorkbenchPart();
return editor != null ? editor.getDiagramEditPart() : null;
}
/**
* Returns the current zoom manager
*
* @return
* the current zoom manager
*/
protected ZoomManager getZoomManager() {
if(getDiagramWorkbenchPart() != null) {
return (ZoomManager)getDiagramWorkbenchPart().getAdapter(ZoomManager.class);
}
return null;
}
/**
*
* @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double)
*
* @param zoom
*/
public void zoomChanged(double zoom) {
refreshCombo();
}
/**
* refresh the combo status
*/
public void refreshCombo() {
if(combo != null && !combo.isDisposed() && combo.isEnabled()) {
ZoomManager zoomManager = getZoomManager();
if(getZoomManager() != null) {
combo.setItems(getZoomLevelsAsText(zoomManager));
if(zoomManager != null) {
String zoomText = zoomManager.getZoomAsText();
int index = combo.indexOf(zoomText);
if(index != -1) {
combo.select(index);
} else {
combo.setText(zoomText);
}
}
}
}
}
/**
* 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) {
String parameter = null;
if(zoomText.equals(ZoomAction.ZOOM_IN)) {
parameter = ZoomAction.ZOOM_IN_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_OUT)) {
parameter = ZoomAction.ZOOM_OUT_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_100)) {
parameter = ZoomAction.ZOOM_100_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_FIT)) {
parameter = ZoomAction.ZOOM_FIT_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_WIDTH)) {
parameter = ZoomAction.ZOOM_WIDTH_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_WIDTH)) {
parameter = ZoomAction.ZOOM_HEIGHT_PARAMETER;
} else if(zoomText.equals(ZoomAction.ZOOM_SELECTION)) {
parameter = ZoomAction.ZOOM_SELECTION_PARAMETER;
} else {
parameter = zoomText;
ZoomManager manager = getZoomManager();
if(manager != null) {
manager.setZoomAsText(parameter);//to set a specific value to zoom
}
}
ZoomAction action = new ZoomAction(parameter, getSelectedElements());
if(action.isEnabled()) {
action.doRun(null);
} else {
refreshCombo();
}
}
/**
*
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*
* @param event
*/
public void handleEvent(Event event) {
if(event.type == SWT.KeyDown && event.character != '\r') {
return;
}
setZoomAsText(combo.getText());
}
/**
* Iterate over current selection and build a list of the {@link IGraphicalEditPart} contained in
* the selection.
*
* @return the currently selected {@link IGraphicalEditPart}
*/
protected List<IGraphicalEditPart> getSelectedElements() {
List<IGraphicalEditPart> editparts = new ArrayList<IGraphicalEditPart>();
ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
if(selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection)selection;
Iterator<?> it = structuredSelection.iterator();
while(it.hasNext()) {
Object object = it.next();
if(object instanceof IGraphicalEditPart) {
editparts.add((IGraphicalEditPart)object);
}
}
} else if(selection instanceof IGraphicalEditPart) {
editparts.add((IGraphicalEditPart)selection);
}
return editparts;
}
/**
*
* @see org.eclipse.papyrus.sasheditor.editor.IPageChangedListener#pageChanged(org.eclipse.papyrus.sasheditor.editor.IPage)
*
* @param newPage
*/
public void pageChanged(IPage newPage) {
refreshCombo();
//we update the listeners
removeListeners(partService.getActivePart());
addListeners(partService.getActivePart());
}
/**
* Removes the listeners on the zoom manager and on the ISashWindowsContainer
*
* @param part
* the part owning the listener to remove
*/
protected void removeListeners(IWorkbenchPart part) {
//we remove the zoom listener
ZoomManager manager = (ZoomManager)part.getAdapter(ZoomManager.class);
if(manager != null) {
manager.removeZoomListener(getInstance());
}
//we remove the page changed listener
ISashWindowsContainer windowContainer = (ISashWindowsContainer)part.getAdapter(ISashWindowsContainer.class);
if(windowContainer != null) {
windowContainer.removePageChangedListener(getInstance());
}
refreshStatusCombo(part);
}
/**
* Adds the listeners on the zoom manager and on the ISashWindowsContainer
*
* @param part
* the part owning the listener to add
*/
protected void addListeners(IWorkbenchPart part) {
//we add listener on the zoom manager
ZoomManager manager = (ZoomManager)part.getAdapter(ZoomManager.class);
if(manager != null) {
manager.addZoomListener(getInstance());
}
//we add listener on the window container
ISashWindowsContainer windowContainer = (ISashWindowsContainer)part.getAdapter(ISashWindowsContainer.class);
if(windowContainer != null) {
windowContainer.addPageChangedListener(getInstance());
}
refreshStatusCombo(part);
}
/**
*
* @param part
* refresh the state of the combo
*/
protected void refreshStatusCombo(IWorkbenchPart part) {
ZoomManager zoomManager = (ZoomManager)part.getAdapter(ZoomManager.class);
if(combo != null && !combo.isDisposed()) {
if(zoomManager == null) {
combo.setEnabled(false);
} else {
combo.setEnabled(true && getDiagramEditPart() != null);
refreshCombo();
}
}
}
/**
* Returns the current instance of {@link ZoomToolbar} (this)
*
* @return
* the current instance of {@link ZoomToolbar} (this)
*/
protected ZoomToolbar getInstance() {
return this;
}
/**
*
* This listener is used to listen the part changes
*
*
*/
public class CustomPartListener implements IPartListener {
/**
*
* @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
*
* @param part
*/
public void partActivated(IWorkbenchPart part) {
if(part instanceof CoreMultiDiagramEditor) {
removeListeners(part);
addListeners(part);
}
refreshStatusCombo(part);
}
/**
*
* @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
*
* @param part
*/
public void partBroughtToTop(IWorkbenchPart part) {
refreshStatusCombo(part);
}
/**
*
* @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
*
* @param part
*/
public void partClosed(IWorkbenchPart part) {
refreshStatusCombo(part);
}
/**
*
* @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
*
* @param part
*/
public void partDeactivated(IWorkbenchPart part) {
if(part instanceof CoreMultiDiagramEditor) {
}
refreshStatusCombo(part);
}
/**
*
* @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
*
* @param part
*/
public void partOpened(IWorkbenchPart part) {
if(part instanceof CoreMultiDiagramEditor) {
removeListeners(part);
addListeners(part);
}
refreshStatusCombo(part);
}
}
}