/*=============================================================================#
 # 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();
	}
	
}
