/******************************************************************************* * Copyright (c) 2000, 2007 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.ui.actions; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.jface.action.ContributionItem; import org.eclipse.core.runtime.Assert; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IPartService; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.gef.editparts.ZoomListener; import org.eclipse.gef.editparts.ZoomManager; /** * A ControlContribution that uses a {@link org.eclipse.swt.widgets.Combo} as its control * * @author Eric Bordeau */ public class ZoomComboContributionItem extends ContributionItem implements ZoomListener { private boolean forceSetText; private Combo combo; private String[] initStrings; private ToolItem toolitem; private ZoomManager zoomManager; private IPartService service; private IPartListener partListener; /** * Constructor for ComboToolItem. * @param partService used to add a PartListener */ public ZoomComboContributionItem(IPartService partService) { this(partService, "8888%");//$NON-NLS-1$ } /** * Constructor for ComboToolItem. * @param partService used to add a PartListener * @param initString the initial string displayed in the combo */ public ZoomComboContributionItem(IPartService partService, String initString) { this(partService, new String[] {initString}); } /** * Constructor for ComboToolItem. * @param partService used to add a PartListener * @param initStrings the initial string displayed in the combo */ public ZoomComboContributionItem(IPartService partService, String[] initStrings) { super(GEFActionConstants.ZOOM_TOOLBAR_WIDGET); this.initStrings = initStrings; service = partService; Assert.isNotNull(partService); partService.addPartListener(partListener = new IPartListener() { public void partActivated(IWorkbenchPart part) { setZoomManager((ZoomManager) part.getAdapter(ZoomManager.class)); } public void partBroughtToTop(IWorkbenchPart p) { } public void partClosed(IWorkbenchPart p) { } public void partDeactivated(IWorkbenchPart p) { } public void partOpened(IWorkbenchPart p) { } }); } private void refresh(boolean repopulateCombo) { if (combo == null || combo.isDisposed()) return; //$TODO GTK workaround try { if (zoomManager == null) { combo.setEnabled(false); combo.setText(""); //$NON-NLS-1$ } else { if (repopulateCombo) combo.setItems(getZoomManager().getZoomLevelsAsText()); String zoom = getZoomManager().getZoomAsText(); int index = combo.indexOf(zoom); if (index == -1 || forceSetText) combo.setText(zoom); else combo.select(index); combo.setEnabled(true); } } catch (SWTException exception) { if (!SWT.getPlatform().equals("gtk")) //$NON-NLS-1$ throw exception; } } /** * Computes the width required by control * @param control The control to compute width * @return int The width required */ protected int computeWidth(Control control) { return control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x; } /** * Creates and returns the control for this contribution item * under the given parent composite. * * @param parent the parent composite * @return the new control */ protected Control createControl(Composite parent) { combo = new Combo(parent, SWT.DROP_DOWN); combo.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { handleWidgetSelected(e); } public void widgetDefaultSelected(SelectionEvent e) { handleWidgetDefaultSelected(e); } }); combo.addFocusListener(new FocusListener() { public void focusGained(FocusEvent e) { // do nothing } public void focusLost(FocusEvent e) { refresh(false); } }); // Initialize width of combo combo.setItems(initStrings); toolitem.setWidth(computeWidth(combo)); refresh(true); return combo; } /** * @see org.eclipse.jface.action.ContributionItem#dispose() */ public void dispose() { if (partListener == null) return; service.removePartListener(partListener); if (zoomManager != null) { zoomManager.removeZoomListener(this); zoomManager = null; } combo = null; partListener = null; } /** * The control item implementation of this <code>IContributionItem</code> * method calls the <code>createControl</code> framework method. * Subclasses must implement <code>createControl</code> rather than * overriding this method. * * @param parent The parent of the control to fill */ public final void fill(Composite parent) { createControl(parent); } /** * The control item implementation of this <code>IContributionItem</code> * method throws an exception since controls cannot be added to menus. * * @param parent The menu * @param index Menu index */ public final void fill(Menu parent, int index) { Assert.isTrue(false, "Can't add a control to a menu");//$NON-NLS-1$ } /** * The control item implementation of this <code>IContributionItem</code> * method calls the <code>createControl</code> framework method to * create a control under the given parent, and then creates * a new tool item to hold it. * Subclasses must implement <code>createControl</code> rather than * overriding this method. * * @param parent The ToolBar to add the new control to * @param index Index */ public void fill(ToolBar parent, int index) { toolitem = new ToolItem(parent, SWT.SEPARATOR, index); Control control = createControl(parent); toolitem.setControl(control); } /** * 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; refresh(true); if (zoomManager != null) zoomManager.addZoomListener(this); } /** * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(SelectionEvent) */ private void handleWidgetDefaultSelected(SelectionEvent event) { if (zoomManager != null) { if (combo.getSelectionIndex() >= 0) zoomManager.setZoomAsText(combo.getItem(combo.getSelectionIndex())); else zoomManager.setZoomAsText(combo.getText()); } /* * There are several cases where invoking setZoomAsText (above) will not result in * zoomChanged being fired (the method below), such as when the user types "asdf" as * the zoom level and hits enter, or when they type in 1%, which is below the minimum * limit, and the current zoom is already at the minimum level. Hence, there is no * guarantee that refresh() will always be invoked. But we need to invoke it to clear * out the invalid text and show the current zoom level. Hence, an (often redundant) * invocation to refresh() is made below. */ refresh(false); } /** * @see org.eclipse.swt.events.SelectionListener#widgetSelected(SelectionEvent) */ private void handleWidgetSelected(SelectionEvent event) { forceSetText = true; handleWidgetDefaultSelected(event); forceSetText = false; } /** * @see ZoomListener#zoomChanged(double) */ public void zoomChanged(double zoom) { refresh(false); } }