| /*=============================================================================# |
| # Copyright (c) 2006, 2021 IBM Corporation and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 |
| # |
| # Contributors: |
| # IBM Corporation - org.eclipse.platform: initial API and implementation |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation (direct use of handler) |
| #=============================================================================*/ |
| |
| // org.eclipse.ui.menus.CommandContributionItem |
| |
| package org.eclipse.statet.ecommons.ui.actions; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import java.util.Collections; |
| import java.util.Map; |
| |
| import org.eclipse.core.commands.Command; |
| import org.eclipse.core.commands.ExecutionEvent; |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.commands.HandlerEvent; |
| import org.eclipse.core.commands.IHandler2; |
| import org.eclipse.core.commands.IHandlerListener; |
| import org.eclipse.core.commands.ParameterizedCommand; |
| import org.eclipse.core.commands.common.NotDefinedException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.action.ContributionItem; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.bindings.BindingManagerEvent; |
| import org.eclipse.jface.bindings.IBindingManagerListener; |
| import org.eclipse.jface.bindings.TriggerSequence; |
| import org.eclipse.jface.resource.DeviceResourceException; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.resource.LocalResourceManager; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| 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.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.commands.ICommandImageService; |
| import org.eclipse.ui.commands.ICommandService; |
| import org.eclipse.ui.commands.IElementReference; |
| import org.eclipse.ui.commands.IElementUpdater; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.help.IWorkbenchHelpSystem; |
| import org.eclipse.ui.internal.services.IWorkbenchLocationService; |
| import org.eclipse.ui.keys.IBindingService; |
| import org.eclipse.ui.menus.CommandContributionItemParameter; |
| import org.eclipse.ui.menus.IMenuService; |
| import org.eclipse.ui.menus.UIElement; |
| import org.eclipse.ui.services.IServiceLocator; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.lang.ObjectUtils; |
| |
| import org.eclipse.statet.ecommons.ui.SharedUIResources; |
| import org.eclipse.statet.ecommons.ui.util.MenuUtils; |
| import org.eclipse.statet.ecommons.ui.workbench.WorkbenchUIUtils; |
| |
| |
| /** |
| * A contribution item which delegates to a handler of a command (not using all service). |
| * It was created as workaround for toolbars in views (wrong enablement when lost focus). |
| * <p> |
| * It currently supports placement in menus and toolbars. |
| * </p> |
| * <p> |
| * This class may be instantiated; it is not intended to be subclassed. |
| * </p> |
| */ |
| @NonNullByDefault |
| public class HandlerContributionItem extends ContributionItem { |
| |
| |
| public static final String NO_COMMAND_ID= "NO_COMMAND"; //$NON-NLS-1$ |
| |
| |
| /** |
| * A push button tool item or menu item. |
| */ |
| public static final int STYLE_PUSH= SWT.PUSH; |
| |
| /** |
| * A checked tool item or menu item. |
| */ |
| public static final int STYLE_CHECK= SWT.CHECK; |
| |
| /** |
| * A radio-button style menu item. |
| */ |
| public static final int STYLE_RADIO= SWT.RADIO; |
| |
| /** |
| * A ToolBar pulldown item. |
| */ |
| public static final int STYLE_PULLDOWN= SWT.DROP_DOWN; |
| |
| /** |
| * Mode bit: Show text on tool items or buttons, even if an image is |
| * present. If this mode bit is not set, text is only shown on tool items if |
| * there is no image present. |
| * |
| * @since 3.4 |
| */ |
| public static final int MODE_FORCE_TEXT= 1; |
| |
| private static final int MODE_NO_COMMAND= 1 << 28; |
| |
| private static final int MODE_CALLBACK_CALL= 1 << 24; |
| private static final int MODE_CALLBACK_EXPL= 1 << 25; |
| |
| |
| private LocalResourceManager localResourceManager; |
| |
| private @Nullable Widget widget; |
| |
| private @Nullable Listener menuItemListener; |
| |
| |
| private IMenuService menuService; |
| |
| private final IServiceLocator serviceLocator; |
| |
| private ICommandService commandService; |
| private IHandlerService handlerService; |
| private IBindingService bindingService; |
| |
| protected final Display display; |
| |
| private @Nullable ParameterizedCommand command; |
| private IHandler2 commandHandler; |
| |
| private @Nullable String label; |
| |
| private @Nullable String mnemonic; |
| |
| private @Nullable String tooltip; |
| |
| private @Nullable ImageDescriptor icon; |
| private @Nullable ImageDescriptor disabledIcon; |
| private @Nullable ImageDescriptor hoverIcon; |
| |
| private IElementReference elementRef; |
| |
| private boolean checkedState; |
| |
| private int style; |
| |
| private IHandlerListener commandListener; |
| |
| private @Nullable String dropDownMenuOverride; |
| |
| private @Nullable IWorkbenchHelpSystem workbenchHelpSystem; |
| private @Nullable String helpContextId; |
| |
| private int mode= 0; |
| |
| private boolean visibleEnabled; |
| |
| // items contributed |
| private @Nullable String contributedLabel; |
| |
| private @Nullable String contributedTooltip; |
| |
| private @Nullable ImageDescriptor contributedIcon; |
| private @Nullable ImageDescriptor contributedDisabledIcon; |
| private @Nullable ImageDescriptor contributedHoverIcon; |
| |
| private final @Nullable UIElement callback; |
| |
| private final IBindingManagerListener bindingManagerListener= new IBindingManagerListener() { |
| @Override |
| public void bindingManagerChanged(final BindingManagerEvent event) { |
| if (event.isActiveBindingsChanged() |
| && event.isActiveBindingsChangedFor(getCommand())) { |
| update(); |
| } |
| } |
| }; |
| |
| |
| /** |
| * Create a CommandContributionItem to place in a ContributionManager. |
| * |
| * @param contributionParameters |
| * paramters necessary to render this contribution item. |
| */ |
| public HandlerContributionItem( |
| final CommandContributionItemParameter contributionParameters, final IHandler2 handler) { |
| super(contributionParameters.id); |
| |
| this.serviceLocator= ObjectUtils.nonNullAssert(contributionParameters.serviceLocator); |
| |
| this.contributedLabel= this.label= contributionParameters.label; |
| this.mnemonic= contributionParameters.mnemonic; |
| this.contributedTooltip= this.tooltip= contributionParameters.tooltip; |
| this.contributedIcon= this.icon= contributionParameters.icon; |
| this.contributedDisabledIcon= this.disabledIcon= contributionParameters.disabledIcon; |
| this.contributedHoverIcon= this.hoverIcon= contributionParameters.hoverIcon; |
| this.style= contributionParameters.style; |
| this.helpContextId= contributionParameters.helpContextId; |
| this.visibleEnabled= contributionParameters.visibleEnabled; |
| |
| try { |
| this.menuService= this.serviceLocator.getService(IMenuService.class); |
| } |
| catch (final NullPointerException e) {} |
| this.commandService= this.serviceLocator.getService(ICommandService.class); |
| this.handlerService= this.serviceLocator.getService(IHandlerService.class); |
| this.bindingService= this.serviceLocator.getService(IBindingService.class); |
| final IWorkbenchLocationService workbenchLocationService= this.serviceLocator |
| .getService(IWorkbenchLocationService.class); |
| this.display= workbenchLocationService.getWorkbench().getDisplay(); |
| |
| createCommand(contributionParameters.commandId, contributionParameters.parameters); |
| this.commandHandler= nonNullAssert(handler); |
| |
| this.callback= (handler instanceof IElementUpdater) ? |
| new UIElement(contributionParameters.serviceLocator) { |
| |
| private boolean beginCallback() { |
| if ((HandlerContributionItem.this.mode & (MODE_NO_COMMAND | MODE_CALLBACK_EXPL)) != 0 |
| || WorkbenchUIUtils.getCommandElementsUpdater() == HandlerContributionItem.this.commandHandler |
| || HandlerContributionItem.this.command.getCommand().getHandler() == HandlerContributionItem.this.commandHandler ) { // no longer works |
| HandlerContributionItem.this.mode |= MODE_CALLBACK_CALL; |
| return true; |
| } |
| return false; |
| } |
| |
| private void endCallback() { |
| HandlerContributionItem.this.mode &= ~MODE_CALLBACK_CALL; |
| } |
| |
| @Override |
| public void setText(final @Nullable String text) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setText(text); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setTooltip(final @Nullable String text) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setTooltip(text); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setIcon(final @Nullable ImageDescriptor desc) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setIcon(desc); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setDisabledIcon(final @Nullable ImageDescriptor desc) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setDisabledIcon(desc); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setHoverIcon(final @Nullable ImageDescriptor desc) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setHoverIcon(desc); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setChecked(final boolean checked) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.setChecked(checked); |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| |
| @Override |
| public void setDropDownId(final String id) { |
| if (beginCallback()) { |
| try { |
| HandlerContributionItem.this.dropDownMenuOverride= id; |
| } |
| finally { |
| endCallback(); |
| } |
| } |
| } |
| } : null; |
| |
| if (this.command != null) { |
| setImages(contributionParameters.serviceLocator, |
| contributionParameters.iconStyle); |
| } |
| } |
| |
| @SuppressWarnings("null") |
| public HandlerContributionItem(final CommandContributionItemParameter contributionParameters, |
| final HandlerCollection handlers) { |
| this(contributionParameters, |
| handlers.get(contributionParameters.commandId) ); |
| } |
| |
| |
| protected IServiceLocator getServiceLocator() { |
| return this.serviceLocator; |
| } |
| |
| private void setImages(final IServiceLocator locator, final String iconStyle) { |
| if (this.icon == null && this.command != null) { |
| final ICommandImageService service= locator.getService(ICommandImageService.class); |
| this.icon= service.getImageDescriptor(this.command.getId(), |
| ICommandImageService.TYPE_DEFAULT, iconStyle); |
| this.disabledIcon= service.getImageDescriptor(this.command.getId(), |
| ICommandImageService.TYPE_DISABLED, iconStyle); |
| this.hoverIcon= service.getImageDescriptor(this.command.getId(), |
| ICommandImageService.TYPE_HOVER, iconStyle); |
| |
| if (this.contributedIcon == null) { |
| this.contributedIcon= this.icon; |
| } |
| if (this.contributedDisabledIcon == null) { |
| this.contributedDisabledIcon= this.disabledIcon; |
| } |
| if (this.contributedHoverIcon == null) { |
| this.contributedHoverIcon= this.hoverIcon; |
| } |
| } |
| } |
| |
| private IHandlerListener getHandlerListener() { |
| if (this.commandListener == null) { |
| this.commandListener= new IHandlerListener() { |
| @Override |
| public void handlerChanged(final HandlerEvent commandEvent) { |
| if (commandEvent.isHandledChanged() |
| || commandEvent.isEnabledChanged() |
| ) { |
| updateCommandProperties(commandEvent); |
| } |
| } |
| }; |
| } |
| return this.commandListener; |
| } |
| |
| private void updateCommandProperties(final HandlerEvent commandEvent) { |
| if (commandEvent.isHandledChanged()) { |
| this.dropDownMenuOverride= null; |
| } |
| final Runnable update= new Runnable() { |
| @Override |
| public void run() { |
| update(null); |
| } |
| }; |
| if (this.display.getThread() == Thread.currentThread()) { |
| update.run(); |
| } |
| else { |
| this.display.asyncExec(update); |
| } |
| } |
| |
| /** |
| * Returns the ParameterizedCommand for this contribution. |
| * <p> |
| * <strong>NOTE:</strong> The returned object should be treated |
| * as 'read-only', do <b>not</b> execute this instance or attempt |
| * to modify its state. |
| * </p> |
| * @return The parameterized command for this contribution. May be |
| * <code>null</code>. |
| */ |
| public @Nullable ParameterizedCommand getCommand() { |
| return this.command; |
| } |
| |
| void createCommand(final @Nullable String commandId, final @Nullable Map parameters) { |
| if (commandId == null) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Unable to create menu item \"" + getId() + "\", no command id")); //$NON-NLS-1$ //$NON-NLS-2$ |
| return; |
| } |
| if (commandId == NO_COMMAND_ID) { |
| this.mode |= MODE_NO_COMMAND; |
| return; |
| } |
| final Command cmd= this.commandService.getCommand(commandId); |
| if (!cmd.isDefined()) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Unable to create menu item \"" + getId() + "\", command \"" + commandId + "\" not defined")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| return; |
| } |
| this.command= ParameterizedCommand.generateCommand(cmd, parameters); |
| } |
| |
| /** |
| * Provide info on the rendering data contained in this item. |
| * |
| * @return a {@link CommandContributionItemParameter}. Valid fields are |
| * serviceLocator, id, style, icon, disabledIcon, hoverIcon, label, |
| * helpContextId, mnemonic, tooltip. The Object will never be |
| * <code>null</code>, although any of the fields may be |
| * <code>null</code>. |
| * @since 3.7 |
| */ |
| public CommandContributionItemParameter getData() { |
| final CommandContributionItemParameter data= new CommandContributionItemParameter( |
| this.serviceLocator, getId(), null, this.style); |
| data.label= this.contributedLabel; |
| data.mnemonic= this.mnemonic; |
| data.tooltip= this.contributedTooltip; |
| data.icon= this.contributedIcon; |
| data.disabledIcon= this.contributedDisabledIcon; |
| data.hoverIcon= this.contributedHoverIcon; |
| data.helpContextId= this.helpContextId; |
| return data; |
| } |
| |
| @Override |
| public void fill(final Menu parent, final int index) { |
| if (this.command == null && (this.mode & MODE_NO_COMMAND) == 0) { |
| return; |
| } |
| if (this.widget != null || parent == null) { |
| return; |
| } |
| |
| // Menus don't support the pulldown style |
| int tmpStyle= this.style; |
| if (tmpStyle == STYLE_PULLDOWN) { |
| tmpStyle= STYLE_PUSH; |
| } |
| |
| MenuItem item= null; |
| if (index >= 0) { |
| item= new MenuItem(parent, tmpStyle, index); |
| } else { |
| item= new MenuItem(parent, tmpStyle); |
| } |
| item.setData(this); |
| if (this.workbenchHelpSystem != null) { |
| this.workbenchHelpSystem.setHelp(item, this.helpContextId); |
| } |
| item.addListener(SWT.Dispose, getItemListener()); |
| item.addListener(SWT.Selection, getItemListener()); |
| this.widget= item; |
| |
| update(null); |
| updateIcons(); |
| |
| establishReferences(); |
| } |
| |
| @Override |
| public void fill(final ToolBar parent, final int index) { |
| if (this.command == null && (this.mode & MODE_NO_COMMAND) == 0) { |
| return; |
| } |
| if (this.widget != null || parent == null) { |
| return; |
| } |
| |
| ToolItem item= null; |
| if (index >= 0) { |
| item= new ToolItem(parent, this.style, index); |
| } else { |
| item= new ToolItem(parent, this.style); |
| } |
| |
| item.setData(this); |
| |
| item.addListener(SWT.Selection, getItemListener()); |
| item.addListener(SWT.Dispose, getItemListener()); |
| this.widget= item; |
| |
| update(null); |
| updateIcons(); |
| |
| establishReferences(); |
| } |
| |
| @Override |
| public void fill(final Composite parent) { |
| if (this.command == null && (this.mode & MODE_NO_COMMAND) == 0) { |
| return; |
| } |
| if (this.widget != null || parent == null) { |
| return; |
| } |
| |
| // Buttons don't support the pulldown style |
| int tmpStyle= this.style; |
| if (tmpStyle == STYLE_PULLDOWN) { |
| tmpStyle= STYLE_PUSH; |
| } |
| |
| final Button item= new Button(parent, tmpStyle); |
| item.setData(this); |
| if (this.workbenchHelpSystem != null) { |
| this.workbenchHelpSystem.setHelp(item, this.helpContextId); |
| } |
| item.addListener(SWT.Dispose, getItemListener()); |
| item.addListener(SWT.Selection, getItemListener()); |
| this.widget= item; |
| |
| update(null); |
| updateIcons(); |
| |
| establishReferences(); |
| } |
| |
| @Override |
| public void update() { |
| update(null); |
| } |
| |
| @Override |
| public void update(final @Nullable String id) { |
| if (this.widget != null) { |
| if ((this.mode & MODE_CALLBACK_EXPL) != 0) { |
| return; |
| } |
| if ((this.mode & (MODE_NO_COMMAND | MODE_CALLBACK_CALL)) == (MODE_NO_COMMAND) |
| && this.callback != null) { |
| this.mode |= MODE_CALLBACK_EXPL; |
| try { |
| this.label= this.contributedLabel; |
| this.tooltip= this.contributedTooltip; |
| this.icon= this.contributedIcon; |
| this.disabledIcon= this.contributedDisabledIcon; |
| this.hoverIcon= this.contributedHoverIcon; |
| ((IElementUpdater) this.commandHandler).updateElement(this.callback, Collections.EMPTY_MAP); |
| } |
| finally { |
| this.mode &= ~MODE_CALLBACK_EXPL; |
| } |
| } |
| |
| if (this.widget instanceof MenuItem) { |
| updateMenuItem((MenuItem) this.widget); |
| } |
| else if (this.widget instanceof ToolItem) { |
| updateToolItem((ToolItem) this.widget); |
| } |
| else if (this.widget instanceof Button) { |
| updateButton((Button) this.widget); |
| } |
| } |
| } |
| |
| private void updateMenuItem(final MenuItem item) { |
| final boolean shouldBeEnabled= isEnabled(); |
| |
| // disabled command + visibility follows enablement == disposed |
| if (item.isDisposed()) { |
| return; |
| } |
| |
| String text= this.label; |
| if (text == null) { |
| if (this.command != null) { |
| try { |
| text= this.command.getCommand().getName(); |
| } catch (final NotDefinedException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Update item failed " + getId(), e)); //$NON-NLS-1$ |
| } |
| } |
| } |
| text= updateMnemonic(text); |
| |
| String keyBindingText= null; |
| if (this.command != null) { |
| final TriggerSequence binding= this.bindingService.getBestActiveBindingFor(this.command); |
| if (binding != null) { |
| keyBindingText= binding.format(); |
| } |
| } |
| if (text != null) { |
| if (keyBindingText == null) { |
| item.setText(text); |
| } |
| else { |
| item.setText(text + '\t' + keyBindingText); |
| } |
| } |
| |
| if (item.getSelection() != this.checkedState) { |
| item.setSelection(this.checkedState); |
| } |
| |
| if (item.getEnabled() != shouldBeEnabled) { |
| item.setEnabled(shouldBeEnabled); |
| } |
| } |
| |
| private void updateToolItem(final ToolItem item) { |
| final boolean shouldBeEnabled= isEnabled(); |
| |
| // disabled command + visibility follows enablement == disposed |
| if (item.isDisposed()) { |
| return; |
| } |
| |
| String text= this.label; |
| if (text == null) { |
| if (this.command != null) { |
| try { |
| text= this.command.getCommand().getName(); |
| } catch (final NotDefinedException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Update item failed " + getId(), e)); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| if ((this.icon == null || (this.mode & MODE_FORCE_TEXT) != 0) |
| && text != null) { |
| item.setText(text); |
| } |
| |
| final String toolTipText= getToolTipText(text); |
| item.setToolTipText(toolTipText); |
| |
| if (item.getSelection() != this.checkedState) { |
| item.setSelection(this.checkedState); |
| } |
| |
| if (item.getEnabled() != shouldBeEnabled) { |
| item.setEnabled(shouldBeEnabled); |
| } |
| } |
| |
| private void updateButton(final Button item) { |
| final boolean shouldBeEnabled= isEnabled(); |
| |
| // disabled command + visibility follows enablement == disposed |
| if (item.isDisposed()) { |
| return; |
| } |
| |
| String text= this.label; |
| if (text == null) { |
| if (this.command != null) { |
| try { |
| text= this.command.getCommand().getName(); |
| } |
| catch (final NotDefinedException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Update item failed " + getId(), e)); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| if (text != null) { |
| item.setText(text); |
| } |
| |
| final String toolTipText= getToolTipText(text); |
| item.setToolTipText(toolTipText); |
| |
| if (item.getSelection() != this.checkedState) { |
| item.setSelection(this.checkedState); |
| } |
| |
| if (item.getEnabled() != shouldBeEnabled) { |
| item.setEnabled(shouldBeEnabled); |
| } |
| } |
| |
| private String getToolTipText(final @Nullable String text) { |
| String tooltipText= this.tooltip; |
| if (tooltipText == null) { |
| if (text != null) { |
| tooltipText= text; |
| } else { |
| tooltipText= ""; //$NON-NLS-1$ |
| } |
| } |
| |
| if (this.command != null) { |
| final TriggerSequence activeBinding= this.bindingService.getBestActiveBindingFor(this.command); |
| if (activeBinding != null && !activeBinding.isEmpty()) { |
| final String acceleratorText= activeBinding.format(); |
| if (acceleratorText != null |
| && acceleratorText.length() != 0) { |
| tooltipText= NLS.bind("{0} ({1})", tooltipText, acceleratorText); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| return tooltipText; |
| } |
| |
| private String updateMnemonic(final String s) { |
| if (this.mnemonic == null || s == null) { |
| return s; |
| } |
| final int idx= s.indexOf(this.mnemonic); |
| if (idx == -1) { |
| return s; |
| } |
| |
| return s.substring(0, idx) + '&' + s.substring(idx); |
| } |
| |
| private void handleWidgetDispose(final Event event) { |
| if (event.widget == this.widget) { |
| disconnectReferences(); |
| this.widget.removeListener(SWT.Selection, getItemListener()); |
| this.widget.removeListener(SWT.Dispose, getItemListener()); |
| this.widget= null; |
| disposeOldImages(); |
| } |
| } |
| |
| private void establishReferences() { |
| if (this.command != null || (this.mode & MODE_NO_COMMAND) != 0) { |
| this.commandHandler.addHandlerListener(getHandlerListener()); |
| } |
| if (this.command != null && this.callback != null) { |
| WorkbenchUIUtils.registerCommandElement(this.command.getId(), this.callback); |
| try { |
| this.elementRef= this.commandService.registerElementForCommand(this.command, this.callback); |
| } |
| catch (final NotDefinedException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Unable to register menu item \"" + getId() + "\", command \"" + this.command.getId() + "\" not defined")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| this.bindingService.addBindingManagerListener(this.bindingManagerListener); |
| } |
| |
| private void disconnectReferences() { |
| if (this.bindingService != null) { |
| this.bindingService.removeBindingManagerListener(this.bindingManagerListener); |
| } |
| if (this.elementRef != null) { |
| this.commandService.unregisterElement(this.elementRef); |
| this.elementRef= null; |
| } |
| if (this.command != null && this.callback != null) { |
| WorkbenchUIUtils.unregisterCommandElement(this.command.getId(), this.callback); |
| } |
| if (this.commandListener != null) { |
| this.commandHandler.removeHandlerListener(this.commandListener); |
| this.commandListener= null; |
| } |
| } |
| |
| @Override |
| public void dispose() { |
| if (this.widget != null) { |
| this.widget.dispose(); |
| this.widget= null; |
| } |
| |
| disconnectReferences(); |
| |
| this.command= null; |
| this.commandHandler= null; |
| this.commandService= null; |
| this.bindingService= null; |
| this.menuService= null; |
| this.handlerService= null; |
| disposeOldImages(); |
| super.dispose(); |
| } |
| |
| private void disposeOldImages() { |
| if (this.localResourceManager != null) { |
| this.localResourceManager.dispose(); |
| this.localResourceManager= null; |
| } |
| } |
| |
| private Listener getItemListener() { |
| if (this.menuItemListener == null) { |
| this.menuItemListener= new Listener() { |
| @Override |
| public void handleEvent(final Event event) { |
| switch (event.type) { |
| case SWT.Dispose: |
| handleWidgetDispose(event); |
| break; |
| case SWT.Selection: |
| if (event.widget != null) { |
| handleWidgetSelection(event); |
| } |
| break; |
| } |
| } |
| }; |
| } |
| return this.menuItemListener; |
| } |
| |
| private void handleWidgetSelection(final Event event) { |
| // Special check for ToolBar dropdowns... |
| if (openDropDownMenu(event)) { |
| return; |
| } |
| |
| if ((this.style & (SWT.TOGGLE | SWT.CHECK)) != 0) { |
| if (event.widget instanceof ToolItem) { |
| this.checkedState= ((ToolItem) event.widget).getSelection(); |
| } |
| else if (event.widget instanceof MenuItem) { |
| this.checkedState= ((MenuItem) event.widget).getSelection(); |
| } |
| } |
| |
| try { |
| final ExecutionEvent executionEvent= (this.command != null) ? |
| this.handlerService.createExecutionEvent(this.command, event) : |
| new ExecutionEvent(null, Collections.EMPTY_MAP, null, this.handlerService.createContextSnapshot(true)); |
| this.commandHandler.execute(executionEvent); |
| } |
| catch (final ExecutionException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Failed to execute item " + getId(), e)); //$NON-NLS-1$ |
| // } catch (NotDefinedException e) { |
| // WorkbenchPlugin.log("Failed to execute item " //$NON-NLS-1$ |
| // + getId(), e); |
| // } catch (NotEnabledException e) { |
| // WorkbenchPlugin.log("Failed to execute item " //$NON-NLS-1$ |
| // + getId(), e); |
| // } catch (NotHandledException e) { |
| // WorkbenchPlugin.log("Failed to execute item " //$NON-NLS-1$ |
| // + getId(), e); |
| } |
| } |
| |
| /** |
| * Determines if the selection was on the dropdown affordance and, if so, |
| * opens the drop down menu (populated using the same id as this item... |
| * |
| * @param event |
| * The <code>SWT.Selection</code> event to be tested |
| * |
| * @return <code>true</code> iff a drop down menu was opened |
| */ |
| private boolean openDropDownMenu(final Event event) { |
| final Widget item= event.widget; |
| if (item != null) { |
| final int style= item.getStyle(); |
| if ((style & SWT.DROP_DOWN) != 0) { |
| if (event.detail == 4) { // on drop-down button |
| final ToolItem ti= (ToolItem) item; |
| |
| final MenuManager menuManager= new MenuManager(); |
| final Menu menu= menuManager.createContextMenu(ti.getParent()); |
| if (this.workbenchHelpSystem != null) { |
| this.workbenchHelpSystem.setHelp(menu, this.helpContextId); |
| } |
| initDropDownMenu(menuManager); |
| |
| // position the menu below the drop down item |
| final Point point= ti.getParent().toDisplay(new Point(event.x, event.y)); |
| menu.setLocation(point.x, point.y); // waiting for SWT |
| // 0.42 |
| menu.setVisible(true); |
| return true; // we don't fire the action |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| protected void initDropDownMenu(final MenuManager menuManager) { |
| String id= this.dropDownMenuOverride; |
| if (id == null) { |
| id= getId(); |
| } |
| MenuUtils.registerOneWayMenu(menuManager, id); |
| } |
| |
| private void updateIcons() { |
| if (this.widget instanceof MenuItem) { |
| final MenuItem item= (MenuItem) this.widget; |
| final LocalResourceManager m= new LocalResourceManager(JFaceResources.getResources()); |
| try { |
| item.setImage((this.icon == null) ? null : m.createImage(this.icon)); |
| } |
| catch (final DeviceResourceException e) { |
| this.icon= ImageDescriptor.getMissingImageDescriptor(); |
| item.setImage(m.createImage(this.icon)); |
| // as we replaced the failed icon, log the message once. |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, SharedUIResources.BUNDLE_ID, |
| "Failed to load image", e )); //$NON-NLS-1$ |
| } |
| disposeOldImages(); |
| this.localResourceManager= m; |
| } |
| else if (this.widget instanceof ToolItem) { |
| final ToolItem item= (ToolItem) this.widget; |
| final LocalResourceManager m= new LocalResourceManager(JFaceResources.getResources()); |
| item.setDisabledImage((this.disabledIcon == null) ? null : |
| m.createImage(this.disabledIcon) ); |
| item.setHotImage((this.hoverIcon == null) ? null : |
| m.createImage(this.hoverIcon) ); |
| item.setImage((this.icon == null) ? null : |
| m.createImage(this.icon) ); |
| disposeOldImages(); |
| this.localResourceManager= m; |
| } |
| } |
| |
| public void setText(final @Nullable String text) { |
| this.label= text; |
| update(null); |
| } |
| |
| public void setTooltip(final @Nullable String text) { |
| this.tooltip= text; |
| if (this.widget instanceof ToolItem) { |
| ((ToolItem) this.widget).setToolTipText(text); |
| } |
| } |
| |
| public void setIcon(final @Nullable ImageDescriptor desc) { |
| this.icon= desc; |
| updateIcons(); |
| } |
| |
| public void setDisabledIcon(final @Nullable ImageDescriptor desc) { |
| this.disabledIcon= desc; |
| updateIcons(); |
| } |
| |
| public void setHoverIcon(final @Nullable ImageDescriptor desc) { |
| this.hoverIcon= desc; |
| updateIcons(); |
| } |
| |
| public void setChecked(final boolean checked) { |
| if (this.checkedState == checked) { |
| return; |
| } |
| this.checkedState= checked; |
| if (this.widget instanceof MenuItem) { |
| ((MenuItem) this.widget).setSelection(this.checkedState); |
| } |
| else if (this.widget instanceof ToolItem) { |
| ((ToolItem) this.widget).setSelection(this.checkedState); |
| } |
| } |
| |
| @Override |
| public boolean isEnabled() { |
| if (this.commandHandler != null) { |
| this.commandHandler.setEnabled((this.menuService != null) ? this.menuService.getCurrentState() : null); |
| return this.commandHandler.isEnabled(); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isVisible() { |
| if (this.visibleEnabled) { |
| return super.isVisible() && isEnabled(); |
| } |
| return super.isVisible(); |
| } |
| |
| } |