Package org.eclipse.ui.menus

Source Code of org.eclipse.ui.menus.CommandContributionItem

/*******************************************************************************
* Copyright (c) 2006, 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.ui.menus;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.ICommandListener;
import org.eclipse.core.commands.IParameter;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.Parameterization;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.bindings.TriggerSequence;
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.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.IWorkbench;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.commands.IElementReference;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.commands.ICommandImageService;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.services.IServiceLocator;

/**
* A contribution item which delegates to a command. It can be used in
* {@link AbstractContributionFactory#createContributionItems(IServiceLocator, IContributionRoot)}.
* <p>
* It currently supports placement in menus and toolbars.
* </p>
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
*
* @since 3.3
*/
public final class CommandContributionItem extends ContributionItem {
  /**
   * 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;

  private LocalResourceManager localResourceManager;

  private Listener menuItemListener;

  private Widget widget;

  private IMenuService menuService;

  private ICommandService commandService;

  private IHandlerService handlerService;
 
  private IBindingService bindingService;

  private ParameterizedCommand command;

  private ImageDescriptor icon;

  private String label;

  private String tooltip;

  private ImageDescriptor disabledIcon;

  private ImageDescriptor hoverIcon;

  private String mnemonic;

  private IElementReference elementRef;

  private boolean checkedState;

  private int style;

  private ICommandListener commandListener;

  private String dropDownMenuOverride;

  /**
   * Create a CommandContributionItem to place in a ContributionManager.
   *
   * @param serviceLocator
   *            a service locator that is most appropriate for this
   *            contribution. Typically the local {@link IWorkbenchWindow} or
   *            {@link IWorkbenchPartSite} will be sufficient.
   * @param id
   *            The id for this item. May be <code>null</code>. Items
   *            without an id cannot be referenced later.
   * @param commandId
   *            A command id for a defined command. Must not be
   *            <code>null</code>.
   * @param parameters
   *            A map of strings to strings which represent parameter names to
   *            values. The parameter names must match those in the command
   *            definition.
   * @param icon
   *            An icon for this item. May be <code>null</code>.
   * @param disabledIcon
   *            A disabled icon for this item. May be <code>null</code>.
   * @param hoverIcon
   *            A hover icon for this item. May be <code>null</code>.
   * @param label
   *            A label for this item. May be <code>null</code>.
   * @param mnemonic
   *            A mnemonic for this item to be applied to the label. May be
   *            <code>null</code>.
   * @param tooltip
   *            A tooltip for this item. May be <code>null</code>. Tooltips
   *            are currently only valid for toolbar contributions.
   * @param style
   *            The style of this menu contribution. See the STYLE_* contants.
   */
  public CommandContributionItem(IServiceLocator serviceLocator, String id,
      String commandId, Map parameters, ImageDescriptor icon,
      ImageDescriptor disabledIcon, ImageDescriptor hoverIcon,
      String label, String mnemonic, String tooltip, int style) {
    super(id);
    this.icon = icon;
    this.disabledIcon = disabledIcon;
    this.hoverIcon = hoverIcon;
    this.label = label;
    this.mnemonic = mnemonic;
    this.tooltip = tooltip;
    this.style = style;
    menuService = (IMenuService) serviceLocator
        .getService(IMenuService.class);
    commandService = (ICommandService) serviceLocator
        .getService(ICommandService.class);
    handlerService = (IHandlerService) serviceLocator
        .getService(IHandlerService.class);
    bindingService = (IBindingService) serviceLocator
        .getService(IBindingService.class);
    createCommand(commandId, parameters);

    if (command != null) {
      try {
        UIElement callback = new UIElement(serviceLocator) {

          public void setChecked(boolean checked) {
            CommandContributionItem.this.setChecked(checked);
          }

          public void setDisabledIcon(ImageDescriptor desc) {
            CommandContributionItem.this.setDisabledIcon(desc);
          }

          public void setHoverIcon(ImageDescriptor desc) {
            CommandContributionItem.this.setHoverIcon(desc);
          }

          public void setIcon(ImageDescriptor desc) {
            CommandContributionItem.this.setIcon(desc);
          }

          public void setText(String text) {
            CommandContributionItem.this.setText(text);
          }

          public void setTooltip(String text) {
            CommandContributionItem.this.setTooltip(text);
          }

          public void setDropDownId(String id) {
            dropDownMenuOverride = id;
          }
        };
        elementRef = commandService.registerElementForCommand(command,
            callback);
        command.getCommand().addCommandListener(getCommandListener());
        setImages(serviceLocator);
      } catch (NotDefinedException e) {
        WorkbenchPlugin.log("Unable to register menu item \"" + getId() //$NON-NLS-1$
            + "\", command \"" + commandId + "\" not defined"); //$NON-NLS-1$ //$NON-NLS-2$
      }
    }
  }
 
  private void setImages(IServiceLocator locator) {
    if (icon == null) {
      ICommandImageService service = (ICommandImageService) locator
          .getService(ICommandImageService.class);
      icon = service.getImageDescriptor(command.getId(),
          ICommandImageService.TYPE_DEFAULT);
      disabledIcon = service.getImageDescriptor(command.getId(),
          ICommandImageService.TYPE_DISABLED);
      hoverIcon = service.getImageDescriptor(command.getId(),
          ICommandImageService.TYPE_HOVER);
    }
  }

  /**
   * @return
   */
  private ICommandListener getCommandListener() {
    if (commandListener == null) {
      commandListener = new ICommandListener() {
        public void commandChanged(CommandEvent commandEvent) {
          if (commandEvent.isHandledChanged()
              || commandEvent.isEnabledChanged()
              || commandEvent.isDefinedChanged()) {
            if (commandEvent.isHandledChanged()) {
              dropDownMenuOverride = null;
            }
            if (commandEvent.getCommand().isDefined()) {
              update(null);
            }
          }
        }
      };
    }
    return commandListener;
  }

  ParameterizedCommand getCommand() {
    return command;
  }

  void createCommand(String commandId, Map parameters) {
    if (commandId == null) {
      WorkbenchPlugin.log("Unable to create menu item \"" + getId() //$NON-NLS-1$
          + "\", no command id"); //$NON-NLS-1$
      return;
    }
    Command cmd = commandService.getCommand(commandId);
    if (!cmd.isDefined()) {
      WorkbenchPlugin.log("Unable to create menu item \"" + getId() //$NON-NLS-1$
          + "\", command \"" + commandId + "\" not defined"); //$NON-NLS-1$ //$NON-NLS-2$
      return;
    }

    if (parameters == null || parameters.size() == 0) {
      command = new ParameterizedCommand(cmd, null);
      return;
    }

    try {
      ArrayList parmList = new ArrayList();
      Iterator i = parameters.entrySet().iterator();
      while (i.hasNext()) {
        Map.Entry entry = (Map.Entry) i.next();
        String parmName = (String) entry.getKey();
        IParameter parm;
        parm = cmd.getParameter(parmName);
        if (parm == null) {
          WorkbenchPlugin
              .log("Unable to create menu item \"" + getId() //$NON-NLS-1$
                  + "\", parameter \"" + parmName + "\" for command \"" //$NON-NLS-1$ //$NON-NLS-2$
                  + commandId + "\" is not defined"); //$NON-NLS-1$
          return;
        }
        parmList.add(new Parameterization(parm, (String) entry
            .getValue()));
      }
      command = new ParameterizedCommand(cmd,
          (Parameterization[]) parmList
              .toArray(new Parameterization[parmList.size()]));
    } catch (NotDefinedException e) {
      // this shouldn't happen as we checked for !defined, but we
      // won't take the chance
      WorkbenchPlugin.log("Failed to create menu item " //$NON-NLS-1$
          + getId(), e);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.Menu,
   *      int)
   */
  public void fill(Menu parent, int index) {
    if (command == null) {
      return;
    }
    if (widget != null || parent == null) {
      return;
    }

    // Menus don't support the pulldown style
    int tmpStyle = 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);

    item.addListener(SWT.Dispose, getItemListener());
    item.addListener(SWT.Selection, getItemListener());
    widget = item;
   
    String helpContextId = null;
    try {
      helpContextId = commandService.getHelpContextId(command
          .getCommand().getId());
    } catch (NotDefinedException e) {
      // No helpContextId
    }

    IWorkbench workbench = PlatformUI.getWorkbench();
    if (workbench != null && helpContextId != null) {
      workbench.getHelpSystem().setHelp(item, helpContextId);
    }
   
    update(null);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.ToolBar,
   *      int)
   */
  public void fill(ToolBar parent, int index) {
    if (command == null) {
      return;
    }
    if (widget != null || parent == null) {
      return;
    }

    ToolItem item = null;
    if (index >= 0) {
      item = new ToolItem(parent, style, index);
    } else {
      item = new ToolItem(parent, style);
    }

    item.setData(this);

    item.addListener(SWT.Selection, getItemListener());
    item.addListener(SWT.Dispose, getItemListener());
    widget = item;

    update(null);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#update()
   */
  public void update() {
    update(null);
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#update(java.lang.String)
   */
  public void update(String id) {
    if (widget != null) {
      if (widget instanceof MenuItem) {
        MenuItem item = (MenuItem) widget;

        String text = label;
        if (text == null) {
          if (command != null) {
            try {
              text = command.getCommand().getName();
            } catch (NotDefinedException e) {
              WorkbenchPlugin.log("Update item failed " //$NON-NLS-1$
                  + getId(), e);
            }
          }
        }
        text = updateMnemonic(text);

        String keyBindingText = null;
        if (command != null) {
          TriggerSequence[] bindings = bindingService
              .getActiveBindingsFor(command);
          if (bindings.length > 0) {
            keyBindingText = bindings[0].format();
          }
        }
        if (text != null) {
          if (keyBindingText == null) {
            item.setText(text);
          } else {
            item.setText(text + '\t' + keyBindingText);
          }
        }

        updateIcons();
        if (item.getSelection() != checkedState) {
          item.setSelection(checkedState);
        }

        boolean shouldBeEnabled = isEnabled();
        if (item.getEnabled() != shouldBeEnabled) {
          item.setEnabled(shouldBeEnabled);
        }
      } else if (widget instanceof ToolItem) {
        ToolItem item = (ToolItem) widget;

        if (icon != null) {
          updateIcons();
        } else if (label != null) {
          item.setText(label);
        }

        if (tooltip != null)
          item.setToolTipText(tooltip);
        else {
          String text = label;
          if (text == null) {
            if (command != null) {
              try {
                text = command.getCommand().getName();
              } catch (NotDefinedException e) {
                WorkbenchPlugin.log("Update item failed " //$NON-NLS-1$
                    + getId(), e);
              }
            }
          }
          if (text != null) {
            item.setToolTipText(text);
          }
        }

        if (item.getSelection() != checkedState) {
          item.setSelection(checkedState);
        }

        boolean shouldBeEnabled = isEnabled();
        if (item.getEnabled() != shouldBeEnabled) {
          item.setEnabled(shouldBeEnabled);
        }
      }
    }
  }
 
  private String updateMnemonic(String s) {
    if (mnemonic==null || s==null) {
      return s;
    }
    int idx = s.indexOf(mnemonic);
    if (idx==-1) {
      return s;
    }
   
    return s.substring(0, idx) + '&' + s.substring(idx);
  }

  private void handleWidgetDispose(Event event) {
    if (event.widget == widget) {
      widget.removeListener(SWT.Selection, getItemListener());
      widget.removeListener(SWT.Dispose, getItemListener());
      widget = null;
      disposeOldImages();
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#dispose()
   */
  public void dispose() {
    if (elementRef != null) {
      commandService.unregisterElement(elementRef);
      elementRef = null;
    }
    if (commandListener != null) {
      command.getCommand().removeCommandListener(commandListener);
      commandListener = null;
    }
    command = null;
    commandService = null;
    disposeOldImages();
    super.dispose();
  }

  private void disposeOldImages() {
    if (localResourceManager != null) {
      localResourceManager.dispose();
      localResourceManager = null;
    }
  }

  private Listener getItemListener() {
    if (menuItemListener == null) {
      menuItemListener = new Listener() {
        public void handleEvent(Event event) {
          switch (event.type) {
          case SWT.Dispose:
            handleWidgetDispose(event);
            break;
          case SWT.Selection:
            if (event.widget != null) {
              handleWidgetSelection(event);
            }
            break;
          }
        }
      };
    }
    return menuItemListener;
  }

  private void handleWidgetSelection(Event event) {
    // Special check for ToolBar dropdowns...
    if (openDropDownMenu(event))
      return;

    if ((style & (SWT.TOGGLE | SWT.CHECK)) != 0) {
      if (event.widget instanceof ToolItem) {
        checkedState = ((ToolItem)event.widget).getSelection();
      } else if (event.widget instanceof MenuItem) {
        checkedState = ((MenuItem)event.widget).getSelection();
      }
    }
   
    try {
      handlerService.executeCommand(command, event);
    } catch (ExecutionException e) {
      WorkbenchPlugin.log("Failed to execute item " //$NON-NLS-1$
          + getId(), e);
    } 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(Event event) {
    Widget item = event.widget;
    if (item != null) {
      int style = item.getStyle();
      if ((style & SWT.DROP_DOWN) != 0) {
        if (event.detail == 4) { // on drop-down button
          ToolItem ti = (ToolItem) item;

          final MenuManager menuManager = new MenuManager();
          Menu menu = menuManager.createContextMenu(ti.getParent());
         
          String helpContextId = null;
          try {
            helpContextId = commandService.getHelpContextId(command
                .getCommand().getId());
          } catch (NotDefinedException e) {
            // No helpContextId
          }

          IWorkbench workbench = PlatformUI.getWorkbench();
          if (workbench != null && helpContextId != null) {
            workbench.getHelpSystem().setHelp(menu, helpContextId);
          }
         
          menuManager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
              String id = getId();
              if (dropDownMenuOverride != null) {
                id = dropDownMenuOverride;
              }
              menuService.populateContributionManager(
                  menuManager, "menu:" + id); //$NON-NLS-1$
            }
          });
         
          // position the menu below the drop down item
          Rectangle b = ti.getBounds();
          Point p = ti.getParent().toDisplay(
              new Point(b.x, b.y + b.height));
          menu.setLocation(p.x, p.y); // waiting for SWT
          // 0.42
          menu.setVisible(true);
          return true; // we don't fire the action
        }
      }
    }

    return false;
  }

  private void setIcon(ImageDescriptor desc) {
    icon = desc;
    updateIcons();
  }

  private void updateIcons() {
    if (widget instanceof MenuItem) {
      MenuItem item = (MenuItem) widget;
      LocalResourceManager m = new LocalResourceManager(JFaceResources
          .getResources());
      item.setImage(icon == null ? null : m.createImage(icon));
      disposeOldImages();
      localResourceManager = m;
    } else if (widget instanceof ToolItem) {
      ToolItem item = (ToolItem) widget;
      LocalResourceManager m = new LocalResourceManager(JFaceResources
          .getResources());
      item.setDisabledImage(disabledIcon == null ? null : m
          .createImage(disabledIcon));
      item.setHotImage(hoverIcon == null ? null : m
          .createImage(hoverIcon));
      item.setImage(icon == null ? null : m.createImage(icon));
      disposeOldImages();
      localResourceManager = m;
    }
  }

  private void setText(String text) {
    label = text;
    update(null);
  }

  private void setChecked(boolean checked) {
    if (checkedState == checked) {
      return;
    }
    checkedState = checked;
    if (widget instanceof MenuItem) {
      ((MenuItem) widget).setSelection(checkedState);
    } else if (widget instanceof ToolItem) {
      ((ToolItem) widget).setSelection(checkedState);
    }
  }

  private void setTooltip(String text) {
    tooltip = text;
    if (widget instanceof ToolItem) {
      ((ToolItem) widget).setToolTipText(text);
    }
  }

  private void setDisabledIcon(ImageDescriptor desc) {
    disabledIcon = desc;
    updateIcons();
  }

  private void setHoverIcon(ImageDescriptor desc) {
    hoverIcon = desc;
    updateIcons();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.jface.action.ContributionItem#isEnabled()
   */
  public boolean isEnabled() {
    if (command != null) {
      return command.getCommand().isEnabled();
    }
    return false;
  }
}
TOP

Related Classes of org.eclipse.ui.menus.CommandContributionItem

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.