| /******************************************************************************* |
| * Copyright (c) 2000, 2016 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Remy Chi Jian Suen <remy.suen@gmail.com> - Bug 12116 [Contributions] widgets: MenuManager.setImageDescriptor() method needed |
| * Lars Vogel <Lars.Vogel@gmail.com> - Bug 440252 |
| * Andrey Loskutov <loskutov@gmx.de> - Bug 436225 |
| * Dirk Fauth <dirk.fauth@googlemail.com> - Bug 488500, Bug 488978 |
| *******************************************************************************/ |
| package org.eclipse.jface.action; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.ListenerList; |
| import org.eclipse.jface.internal.MenuManagerEventHelper; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.resource.LocalResourceManager; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.MenuAdapter; |
| import org.eclipse.swt.events.MenuEvent; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.CoolBar; |
| import org.eclipse.swt.widgets.Decorations; |
| import org.eclipse.swt.widgets.Item; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.MenuItem; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.ToolBar; |
| |
| /** |
| * A menu manager is a contribution manager which realizes itself and its items |
| * in a menu control; either as a menu bar, a sub-menu, or a context menu. |
| * <p> |
| * This class may be instantiated; it may also be subclassed. |
| * </p> |
| */ |
| public class MenuManager extends ContributionManager implements IMenuManager { |
| /** |
| * The key under which the {@link MenuManager} is added to the data properties |
| * of the {@link Menu} created by the manager. |
| * |
| * @since 3.12 |
| */ |
| public static final String MANAGER_KEY = "org.eclipse.jface.action.MenuManager.managerKey"; //$NON-NLS-1$ |
| |
| /** |
| * The menu id. |
| */ |
| private String id; |
| |
| /** |
| * List of registered menu listeners (element type: <code>IMenuListener</code>). |
| */ |
| private ListenerList<IMenuListener> listeners = new ListenerList<>(); |
| |
| /** |
| * The menu control; <code>null</code> before creation and after disposal. |
| */ |
| private Menu menu = null; |
| |
| /** |
| * The menu item widget; <code>null</code> before creation and after disposal. |
| * This field is used when this menu manager is a sub-menu. |
| */ |
| private MenuItem menuItem; |
| |
| /** |
| * The text for a sub-menu. |
| */ |
| private String menuText; |
| |
| /** |
| * The image for a sub-menu. |
| */ |
| private ImageDescriptor image; |
| |
| /** |
| * A resource manager to remember all of the images that have been used by this |
| * menu. |
| */ |
| private LocalResourceManager imageManager; |
| |
| /** |
| * The overrides for items of this manager |
| */ |
| private IContributionManagerOverrides overrides; |
| |
| /** |
| * The parent contribution manager. |
| */ |
| private IContributionManager parent; |
| |
| /** |
| * Indicates whether <code>removeAll</code> should be called just before the |
| * menu is displayed. |
| */ |
| private boolean removeAllWhenShown = false; |
| |
| /** |
| * Indicates this item is visible in its manager; <code>true</code> by default. |
| * |
| * @since 3.3 |
| */ |
| protected boolean visible = true; |
| |
| /** |
| * allows a submenu to display a shortcut key. This is often used with the |
| * QuickMenu command or action which can pop up a menu using the shortcut. |
| */ |
| private String definitionId = null; |
| |
| /** |
| * Creates a menu manager. The text and id are <code>null</code>. Typically used |
| * for creating a context menu, where it doesn't need to be referred to by id. |
| */ |
| public MenuManager() { |
| this(null, null, null); |
| } |
| |
| /** |
| * Creates a menu manager with the given text. The id of the menu is |
| * <code>null</code>. Typically used for creating a sub-menu, where it doesn't |
| * need to be referred to by id. |
| * |
| * @param text the text for the menu, or <code>null</code> if none |
| */ |
| public MenuManager(String text) { |
| this(text, null, null); |
| } |
| |
| /** |
| * Creates a menu manager with the given text and id. Typically used for |
| * creating a sub-menu, where it needs to be referred to by id. |
| * |
| * @param text the text for the menu, or <code>null</code> if none |
| * @param id the menu id, or <code>null</code> if it is to have no id |
| */ |
| public MenuManager(String text, String id) { |
| this(text, null, id); |
| } |
| |
| /** |
| * Creates a menu manager with the given text, image, and id. Typically used for |
| * creating a sub-menu, where it needs to be referred to by id. |
| * |
| * @param text the text for the menu, or <code>null</code> if none |
| * @param image the image for the menu, or <code>null</code> if none |
| * @param id the menu id, or <code>null</code> if it is to have no id |
| * @since 3.4 |
| */ |
| public MenuManager(String text, ImageDescriptor image, String id) { |
| this.menuText = text; |
| this.image = image; |
| this.id = id; |
| } |
| |
| @Override |
| public void addMenuListener(IMenuListener listener) { |
| listeners.add(listener); |
| } |
| |
| /** |
| * Creates and returns an SWT context menu control for this menu, and installs |
| * all registered contributions. Does not create a new control if one already |
| * exists. |
| * <p> |
| * Note that the menu is not expected to be dynamic. |
| * </p> |
| * |
| * @param parent the parent control |
| * @return the menu control |
| */ |
| public Menu createContextMenu(Control parent) { |
| if (!menuExist()) { |
| menu = new Menu(parent); |
| menu.setData(MANAGER_KEY, this); |
| initializeMenu(); |
| } |
| return menu; |
| } |
| |
| /** |
| * Creates and returns an SWT menu bar control for this menu, for use in the |
| * given <code>Decorations</code>, and installs all registered contributions. |
| * Does not create a new control if one already exists. |
| * |
| * @param parent the parent decorations |
| * @return the menu control |
| * @since 2.1 |
| */ |
| public Menu createMenuBar(Decorations parent) { |
| if (!menuExist()) { |
| menu = new Menu(parent, SWT.BAR); |
| menu.setData(MANAGER_KEY, this); |
| update(false); |
| } |
| return menu; |
| } |
| |
| /** |
| * Creates and returns an SWT menu bar control for this menu, for use in the |
| * given <code>Shell</code>, and installs all registered contributions. Does not |
| * create a new control if one already exists. This implementation simply calls |
| * the <code>createMenuBar(Decorations)</code> method |
| * |
| * @param parent the parent decorations |
| * @return the menu control |
| * @deprecated use <code>createMenuBar(Decorations)</code> instead. |
| */ |
| @Deprecated |
| public Menu createMenuBar(Shell parent) { |
| return createMenuBar((Decorations) parent); |
| } |
| |
| /** |
| * Disposes of this menu manager and frees all allocated SWT resources. Notifies |
| * all contribution items of the dispose. |
| */ |
| @Override |
| public void dispose() { |
| if (menuExist()) { |
| menu.dispose(); |
| } |
| menu = null; |
| |
| if (menuItem != null) { |
| menuItem.dispose(); |
| menuItem = null; |
| } |
| |
| disposeOldImages(); |
| // remember items for disposal before removing them all |
| IContributionItem[] items = getItems(); |
| removeAll(); |
| for (IContributionItem item : items) { |
| item.dispose(); |
| } |
| markDirty(); |
| parent = null; |
| } |
| |
| @Override |
| public void fill(Composite parent) { |
| } |
| |
| @Override |
| public void fill(CoolBar parent, int index) { |
| } |
| |
| @Override |
| public void fill(Menu parent, int index) { |
| if (menuItem == null || menuItem.isDisposed()) { |
| if (index >= 0) { |
| menuItem = new MenuItem(parent, SWT.CASCADE, index); |
| } else { |
| menuItem = new MenuItem(parent, SWT.CASCADE); |
| } |
| |
| String text = getMenuText(); |
| if (text != null) { |
| menuItem.setText(text); |
| } |
| |
| if (image != null) { |
| LocalResourceManager localManager = new LocalResourceManager(JFaceResources.getResources()); |
| menuItem.setImage(localManager.createImage(image)); |
| disposeOldImages(); |
| imageManager = localManager; |
| } |
| |
| if (!menuExist()) { |
| menu = new Menu(parent); |
| menu.setData(MANAGER_KEY, this); |
| } |
| |
| menuItem.setMenu(menu); |
| |
| initializeMenu(); |
| |
| setDirty(true); |
| } |
| } |
| |
| @Override |
| public void fill(ToolBar parent, int index) { |
| } |
| |
| @Override |
| public IMenuManager findMenuUsingPath(String path) { |
| IContributionItem item = findUsingPath(path); |
| if (item instanceof IMenuManager) { |
| return (IMenuManager) item; |
| } |
| return null; |
| } |
| |
| @Override |
| public IContributionItem findUsingPath(String path) { |
| String id = path; |
| String rest = null; |
| int separator = path.indexOf('/'); |
| if (separator != -1) { |
| id = path.substring(0, separator); |
| rest = path.substring(separator + 1); |
| } else { |
| return super.find(path); |
| } |
| |
| IContributionItem item = super.find(id); |
| if (item instanceof IMenuManager) { |
| IMenuManager manager = (IMenuManager) item; |
| return manager.findUsingPath(rest); |
| } |
| return null; |
| } |
| |
| /** |
| * Notifies any menu listeners that a menu is about to show. Only listeners |
| * registered at the time this method is called are notified. |
| * |
| * @param manager the menu manager |
| * |
| * @see IMenuListener#menuAboutToShow |
| */ |
| private void fireAboutToShow(IMenuManager manager) { |
| for (IMenuListener listener : this.listeners) { |
| listener.menuAboutToShow(manager); |
| } |
| } |
| |
| /** |
| * Notifies any menu listeners that a menu is about to hide. Only listeners |
| * registered at the time this method is called are notified. |
| * |
| * @param manager the menu manager |
| * |
| */ |
| private void fireAboutToHide(IMenuManager manager) { |
| for (IMenuListener listener : this.listeners) { |
| if (listener instanceof IMenuListener2) { |
| ((IMenuListener2) listener).menuAboutToHide(manager); |
| } |
| } |
| } |
| |
| /** |
| * Returns the menu id. The menu id is used when creating a contribution item |
| * for adding this menu as a sub menu of another. |
| * |
| * @return the menu id |
| */ |
| @Override |
| public String getId() { |
| return id; |
| } |
| |
| /** |
| * Returns the SWT menu control for this menu manager. |
| * |
| * @return the menu control |
| */ |
| public Menu getMenu() { |
| return menu; |
| } |
| |
| /** |
| * Returns the text shown in the menu, potentially with a shortcut appended. |
| * |
| * @return the menu text |
| */ |
| public String getMenuText() { |
| if (definitionId == null) { |
| return menuText; |
| } |
| ExternalActionManager.ICallback callback = ExternalActionManager.getInstance().getCallback(); |
| if (callback != null) { |
| String shortCut = callback.getAcceleratorText(definitionId); |
| if (shortCut == null) { |
| return menuText; |
| } |
| return menuText + "\t" + shortCut; //$NON-NLS-1$ |
| } |
| return menuText; |
| } |
| |
| /** |
| * Returns the image for this menu as an image descriptor. |
| * |
| * @return the image, or <code>null</code> if this menu has no image |
| * @since 3.4 |
| */ |
| public ImageDescriptor getImageDescriptor() { |
| return image; |
| } |
| |
| @Override |
| public IContributionManagerOverrides getOverrides() { |
| if (overrides == null) { |
| if (parent == null) { |
| overrides = new IContributionManagerOverrides() { |
| @Override |
| public Integer getAccelerator(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public String getAcceleratorText(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public Boolean getEnabled(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public String getText(IContributionItem item) { |
| return null; |
| } |
| |
| @Override |
| public Boolean getVisible(IContributionItem item) { |
| return null; |
| } |
| }; |
| } else { |
| overrides = parent.getOverrides(); |
| } |
| super.setOverrides(overrides); |
| } |
| return overrides; |
| } |
| |
| /** |
| * Returns the parent contribution manager of this manger. |
| * |
| * @return the parent contribution manager |
| * @since 2.0 |
| */ |
| public IContributionManager getParent() { |
| return parent; |
| } |
| |
| @Override |
| public boolean getRemoveAllWhenShown() { |
| return removeAllWhenShown; |
| } |
| |
| /** |
| * Notifies all listeners that this menu is about to appear. |
| */ |
| private void handleAboutToShow() { |
| if (removeAllWhenShown) { |
| removeAll(); |
| } |
| MenuManagerEventHelper.getInstance().showEventPreHelper(this); |
| fireAboutToShow(this); |
| MenuManagerEventHelper.getInstance().showEventPostHelper(this); |
| update(false, false); |
| } |
| |
| /** |
| * Notifies all listeners that this menu is about to disappear. |
| */ |
| private void handleAboutToHide() { |
| MenuManagerEventHelper.getInstance().hideEventPreHelper(this); |
| fireAboutToHide(this); |
| MenuManagerEventHelper.getInstance().hideEventPostHelper(this); |
| } |
| |
| /** |
| * Initializes the menu control. |
| */ |
| private void initializeMenu() { |
| menu.addMenuListener(new MenuAdapter() { |
| @Override |
| public void menuHidden(MenuEvent e) { |
| // ApplicationWindow.resetDescription(e.widget); |
| handleAboutToHide(); |
| } |
| |
| @Override |
| public void menuShown(MenuEvent e) { |
| handleAboutToShow(); |
| } |
| }); |
| // Don't do an update(true) here, in case menu is never opened. |
| // Always do it lazily in handleAboutToShow(). |
| } |
| |
| @Override |
| public boolean isDynamic() { |
| return false; |
| } |
| |
| /** |
| * Returns whether this menu should be enabled or not. Used to enable the menu |
| * item containing this menu when it is realized as a sub-menu. |
| * <p> |
| * The default implementation of this framework method returns |
| * <code>true</code>. Subclasses may reimplement. |
| * </p> |
| * |
| * @return <code>true</code> if enabled, and <code>false</code> if disabled |
| */ |
| @Override |
| public boolean isEnabled() { |
| return true; |
| } |
| |
| @Override |
| public boolean isGroupMarker() { |
| return false; |
| } |
| |
| @Override |
| public boolean isSeparator() { |
| return false; |
| } |
| |
| /** |
| * Check if the contribution is item is a subsitute for ourselves |
| * |
| * @param item the contribution item |
| * @return <code>true</code> if give item is a substitution for ourselves |
| * @deprecated this method is no longer a part of the |
| * {@link org.eclipse.jface.action.IContributionItem} API. |
| */ |
| @Deprecated |
| public boolean isSubstituteFor(IContributionItem item) { |
| return this.equals(item); |
| } |
| |
| @Override |
| public boolean isVisible() { |
| if (!visible) { |
| return false; // short circuit calculations in this case |
| } |
| |
| if (removeAllWhenShown) { |
| // we have no way of knowing if the menu has children |
| return true; |
| } |
| |
| // menus aren't visible if all of its children are invisible (or only contains |
| // visible separators). |
| IContributionItem[] childItems = getItems(); |
| boolean visibleChildren = false; |
| for (IContributionItem childItem : childItems) { |
| if (isChildVisible(childItem) && !childItem.isSeparator()) { |
| visibleChildren = true; |
| break; |
| } |
| } |
| |
| return visibleChildren; |
| } |
| |
| /** |
| * The <code>MenuManager</code> implementation of this |
| * <code>ContributionManager</code> method also propagates the dirty flag up the |
| * parent chain. |
| * |
| * @since 3.1 |
| */ |
| @Override |
| public void markDirty() { |
| super.markDirty(); |
| // Can't optimize by short-circuiting when the first dirty manager is |
| // encountered, |
| // since non-visible children are not even processed. |
| // That is, it's possible to have a dirty sub-menu under a non-dirty parent menu |
| // even after the parent menu has been updated. |
| // If items are added/removed in the sub-menu, we still need to propagate the |
| // dirty flag up, |
| // even if the sub-menu is already dirty, since the result of isVisible() may |
| // change |
| // due to the added/removed items. |
| IContributionManager parent = getParent(); |
| if (parent != null) { |
| parent.markDirty(); |
| } |
| } |
| |
| /** |
| * Returns whether the menu control is created and not disposed. |
| * |
| * @return <code>true</code> if the control is created and not disposed, |
| * <code>false</code> otherwise |
| * @since 3.4 protected, was added in 3.1 as private method |
| */ |
| protected boolean menuExist() { |
| return menu != null && !menu.isDisposed(); |
| } |
| |
| @Override |
| public void removeMenuListener(IMenuListener listener) { |
| listeners.remove(listener); |
| } |
| |
| @Override |
| public void saveWidgetState() { |
| } |
| |
| /** |
| * Sets the overrides for this contribution manager |
| * |
| * @param newOverrides the overrides for the items of this manager |
| * @since 2.0 |
| */ |
| @Override |
| public void setOverrides(IContributionManagerOverrides newOverrides) { |
| overrides = newOverrides; |
| super.setOverrides(overrides); |
| } |
| |
| @Override |
| public void setParent(IContributionManager manager) { |
| parent = manager; |
| } |
| |
| @Override |
| public void setRemoveAllWhenShown(boolean removeAll) { |
| this.removeAllWhenShown = removeAll; |
| } |
| |
| @Override |
| public void setVisible(boolean visible) { |
| this.visible = visible; |
| } |
| |
| /** |
| * Sets the action definition id of this action. This simply allows the menu |
| * item text to include a short cut if available. It can be used to notify a |
| * user of a key combination that will open a quick menu. |
| * |
| * @param definitionId the command definition id |
| * @since 3.4 |
| */ |
| public void setActionDefinitionId(String definitionId) { |
| this.definitionId = definitionId; |
| } |
| |
| @Override |
| public void update() { |
| updateMenuItem(); |
| } |
| |
| /** |
| * The <code>MenuManager</code> implementation of this |
| * <code>IContributionManager</code> updates this menu, but not any of its |
| * submenus. |
| * |
| * @see #updateAll |
| */ |
| @Override |
| public void update(boolean force) { |
| update(force, false); |
| } |
| |
| /** |
| * Get all the items from the implementation's widget. |
| * |
| * @return the menu items |
| * @since 3.4 |
| */ |
| protected Item[] getMenuItems() { |
| if (menu != null) { |
| return menu.getItems(); |
| } |
| return null; |
| } |
| |
| /** |
| * Get an item from the implementation's widget. |
| * |
| * @param index of the item |
| * @return the menu item |
| * @since 3.4 |
| */ |
| protected Item getMenuItem(int index) { |
| if (menu != null) { |
| return menu.getItem(index); |
| } |
| return null; |
| } |
| |
| /** |
| * Get the menu item count for the implementation's widget. |
| * |
| * @return the number of items |
| * @since 3.4 |
| */ |
| protected int getMenuItemCount() { |
| if (menu != null) { |
| return menu.getItemCount(); |
| } |
| return 0; |
| } |
| |
| /** |
| * Call an <code>IContributionItem</code>'s fill method with the |
| * implementation's widget. The default is to use the <code>Menu</code> |
| * widget.<br> |
| * <code>fill(Menu menu, int index)</code> |
| * |
| * @param ci An <code>IContributionItem</code> whose <code>fill()</code> |
| * method should be called. |
| * @param index The position the <code>fill()</code> method should start |
| * inserting at. |
| * @since 3.4 |
| */ |
| protected void doItemFill(IContributionItem ci, int index) { |
| ci.fill(menu, index); |
| } |
| |
| /** |
| * Incrementally builds the menu from the contribution items. This method leaves |
| * out double separators and separators in the first or last position. |
| * |
| * @param force <code>true</code> means update even if not dirty, and |
| * <code>false</code> for normal incremental updating |
| * @param recursive <code>true</code> means recursively update all submenus, and |
| * <code>false</code> means just this menu |
| */ |
| protected void update(boolean force, boolean recursive) { |
| if (isDirty() || force) { |
| if (menuExist()) { |
| // clean contains all active items without double separators |
| IContributionItem[] items = getItems(); |
| List<IContributionItem> clean = new ArrayList<>(items.length); |
| IContributionItem separator = null; |
| for (IContributionItem item : items) { |
| IContributionItem ci = item; |
| if (!isChildVisible(ci)) { |
| continue; |
| } |
| if (ci.isSeparator()) { |
| // delay creation until necessary |
| // (handles both adjacent separators, and separator at end) |
| separator = ci; |
| } else { |
| if (separator != null) { |
| if (clean.size() > 0) { |
| clean.add(separator); |
| } |
| separator = null; |
| } |
| clean.add(ci); |
| } |
| } |
| |
| // remove obsolete (removed or non active) |
| Item[] mi = getMenuItems(); |
| |
| for (Item element : mi) { |
| Object data = element.getData(); |
| |
| if (data == null || !clean.contains(data)) { |
| element.dispose(); |
| } else if (data instanceof IContributionItem && ((IContributionItem) data).isDynamic() |
| && ((IContributionItem) data).isDirty()) { |
| element.dispose(); |
| } |
| } |
| |
| // add new |
| mi = getMenuItems(); |
| int srcIx = 0; |
| int destIx = 0; |
| |
| for (IContributionItem src : clean) { |
| IContributionItem dest; |
| |
| // get corresponding item in SWT widget |
| if (srcIx < mi.length) { |
| dest = (IContributionItem) mi[srcIx].getData(); |
| } else { |
| dest = null; |
| } |
| |
| if (dest != null && src.equals(dest)) { |
| srcIx++; |
| destIx++; |
| } else if (dest != null && dest.isSeparator() && src.isSeparator()) { |
| mi[srcIx].setData(src); |
| srcIx++; |
| destIx++; |
| } else { |
| int start = getMenuItemCount(); |
| doItemFill(src, destIx); |
| int newItems = getMenuItemCount() - start; |
| for (int i = 0; i < newItems; i++) { |
| Item item = getMenuItem(destIx++); |
| item.setData(src); |
| } |
| } |
| |
| // May be we can optimize this call. If the menu has just |
| // been created via the call src.fill(fMenuBar, destIx) then |
| // the menu has already been updated with update(true) |
| // (see MenuManager). So if force is true we do it again. But |
| // we can't set force to false since then information for the |
| // sub sub menus is lost. |
| if (recursive) { |
| IContributionItem item = src; |
| if (item instanceof SubContributionItem) { |
| item = ((SubContributionItem) item).getInnerItem(); |
| } |
| if (item instanceof IMenuManager) { |
| ((IMenuManager) item).updateAll(force); |
| } |
| } |
| |
| } |
| |
| // remove any old menu items not accounted for |
| for (; srcIx < mi.length; srcIx++) { |
| mi[srcIx].dispose(); |
| } |
| |
| setDirty(false); |
| } |
| } else { |
| // I am not dirty. Check if I must recursivly walk down the hierarchy. |
| if (recursive) { |
| IContributionItem[] items = getItems(); |
| for (IContributionItem ci : items) { |
| if (ci instanceof IMenuManager) { |
| IMenuManager mm = (IMenuManager) ci; |
| if (isChildVisible(mm)) { |
| mm.updateAll(force); |
| } |
| } |
| } |
| } |
| } |
| updateMenuItem(); |
| } |
| |
| @Override |
| public void update(String property) { |
| IContributionItem items[] = getItems(); |
| |
| for (IContributionItem item : items) { |
| item.update(property); |
| } |
| |
| if (menu != null && !menu.isDisposed() && menu.getParentItem() != null) { |
| if (IAction.TEXT.equals(property)) { |
| String text = getOverrides().getText(this); |
| |
| if (text == null) { |
| text = getMenuText(); |
| } |
| |
| if (text != null) { |
| ExternalActionManager.ICallback callback = ExternalActionManager.getInstance().getCallback(); |
| |
| if (callback != null) { |
| int index = text.indexOf('&'); |
| |
| if (index >= 0 && index < text.length() - 1) { |
| char character = Character.toUpperCase(text.charAt(index + 1)); |
| |
| if (callback.isAcceleratorInUse(SWT.ALT | character) && isTopLevelMenu()) { |
| if (index == 0) { |
| text = text.substring(1); |
| } else { |
| text = text.substring(0, index) + text.substring(index + 1); |
| } |
| } |
| } |
| } |
| |
| menu.getParentItem().setText(text); |
| } |
| } else if (IAction.IMAGE.equals(property) && image != null) { |
| LocalResourceManager localManager = new LocalResourceManager(JFaceResources.getResources()); |
| menu.getParentItem().setImage(localManager.createImage(image)); |
| disposeOldImages(); |
| imageManager = localManager; |
| } |
| } |
| } |
| |
| private boolean isTopLevelMenu() { |
| if (menu != null && !menu.isDisposed() && menuItem != null && !menuItem.isDisposed()) { |
| Menu parentMenu = menuItem.getParent(); |
| return parentMenu != null && ((parentMenu.getStyle() & SWT.BAR) == SWT.BAR); |
| } |
| return false; |
| } |
| |
| /** |
| * Dispose any images allocated for this menu |
| */ |
| private void disposeOldImages() { |
| if (imageManager != null) { |
| imageManager.dispose(); |
| imageManager = null; |
| } |
| } |
| |
| @Override |
| public void updateAll(boolean force) { |
| update(force, true); |
| } |
| |
| /** |
| * Updates the menu item for this sub menu. The menu item is disabled if this |
| * sub menu is empty. Does nothing if this menu is not a submenu. |
| */ |
| private void updateMenuItem() { |
| /* |
| * Commented out until proper solution to enablement of menu item for a sub-menu |
| * is found. See bug 30833 for more details. |
| * |
| * if (menuItem != null && !menuItem.isDisposed() && menuExist()) { |
| * IContributionItem items[] = getItems(); boolean enabled = false; for (int i = |
| * 0; i < items.length; i++) { IContributionItem item = items[i]; enabled = |
| * item.isEnabled(); if(enabled) break; } // Workaround for 1GDDCN2: SWT:Linux - |
| * MenuItem.setEnabled() always causes a redraw if (menuItem.getEnabled() != |
| * enabled) menuItem.setEnabled(enabled); } |
| */ |
| // Partial fix for bug #34969 - diable the menu item if no |
| // items in sub-menu (for context menus). |
| if (menuItem != null && !menuItem.isDisposed() && menuExist()) { |
| boolean enabled = removeAllWhenShown || menu.getItemCount() > 0; |
| // Workaround for 1GDDCN2: SWT:Linux - MenuItem.setEnabled() always causes a |
| // redraw |
| if (menuItem.getEnabled() != enabled) { |
| // We only do this for context menus (for bug #34969) |
| Menu topMenu = menu; |
| while (topMenu.getParentMenu() != null) { |
| topMenu = topMenu.getParentMenu(); |
| } |
| if ((topMenu.getStyle() & SWT.BAR) == 0) { |
| menuItem.setEnabled(enabled); |
| } |
| } |
| } |
| } |
| |
| private boolean isChildVisible(IContributionItem item) { |
| Boolean v = getOverrides().getVisible(item); |
| if (v != null) { |
| return v.booleanValue(); |
| } |
| return item.isVisible(); |
| } |
| |
| /** |
| * @param menuText The text (label) of the menu. |
| * @since 3.10 |
| */ |
| public void setMenuText(String menuText) { |
| this.menuText = menuText; |
| } |
| |
| /** |
| * @param imageDescriptor The image descriptor to set. |
| * @since 3.10 |
| */ |
| public void setImageDescriptor(ImageDescriptor imageDescriptor) { |
| this.image = imageDescriptor; |
| } |
| |
| @Override |
| public String toString() { |
| return "MenuManager [" + (menuText != null ? "text=" + menuText + ", " : "") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| + (id != null ? "id=" + id + ", " : "") + "visible=" + visible + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| } |
| |
| } |