| /******************************************************************************* |
| * Copyright (c) 2001, 2004 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 |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| *******************************************************************************/ |
| package org.eclipse.wst.sse.ui.internal.extension; |
| |
| |
| |
| import com.ibm.icu.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.ActionContributionItem; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IContributionItem; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.wst.sse.ui.internal.IActionValidator; |
| import org.eclipse.wst.sse.ui.internal.Logger; |
| import org.osgi.framework.Bundle; |
| |
| |
| /** |
| * When 'action' tag is found in the registry, an object of this class is |
| * created. It creates the appropriate action object and captures information |
| * that is later used to add this action object into menu/tool bar. This class |
| * is reused for global (workbench) menu/tool bar, popup menu actions, as well |
| * as view's pulldown and local tool bar. |
| */ |
| public class ActionDescriptor { |
| public static final String ATT_ACCELERATOR = "accelerator"; //$NON-NLS-1$ |
| public static final String ATT_CLASS = "class"; //$NON-NLS-1$ |
| public static final String ATT_DEFINITION_ID = "definitionId"; //$NON-NLS-1$ |
| public static final String ATT_DESCRIPTION = "description"; //$NON-NLS-1$ |
| public static final String ATT_DISABLEDICON = "disabledIcon"; //$NON-NLS-1$ |
| public static final String ATT_HELP_CONTEXT_ID = "helpContextId"; //$NON-NLS-1$ |
| public static final String ATT_HOVERICON = "hoverIcon"; //$NON-NLS-1$ |
| public static final String ATT_ICON = "icon"; //$NON-NLS-1$ |
| |
| public static final String ATT_ID = "id"; //$NON-NLS-1$ |
| public static final String ATT_LABEL = "label"; //$NON-NLS-1$ |
| public static final String ATT_MENUBAR_PATH = "menubarPath"; //$NON-NLS-1$ |
| public static final String ATT_POPUPMENU_PATH = "popupmenuPath"; //$NON-NLS-1$ |
| public static final String ATT_STATE = "state"; //$NON-NLS-1$ |
| public static final String ATT_TOOLBAR_PATH = "toolbarPath"; //$NON-NLS-1$ |
| public static final String ATT_TOOLTIP = "tooltip"; //$NON-NLS-1$ |
| |
| /** |
| * Creates an extension. If the extension plugin has not been loaded a |
| * busy cursor will be activated during the duration of the load. |
| * |
| * @param element |
| * the config element defining the extension |
| * @param classAttribute |
| * the name of the attribute carrying the class |
| * @returns the extension object if successful. If an error occurs when |
| * createing executable extension, the exception is logged, and |
| * null returned. |
| */ |
| public static Object createExtension(final IConfigurationElement element, final String classAttribute) { |
| final Object[] result = new Object[1]; |
| // If plugin has been loaded create extension. |
| // Otherwise, show busy cursor then create extension. |
| String pluginId = element.getDeclaringExtension().getNamespace(); |
| Bundle bundle = Platform.getBundle(pluginId); |
| if (bundle.getState() == Bundle.ACTIVE) { |
| try { |
| result[0] = element.createExecutableExtension(classAttribute); |
| } catch (Exception e) { |
| // catch and log ANY exception from extension point |
| handleCreateExecutableException(result, e); |
| } |
| } else { |
| BusyIndicator.showWhile(null, new Runnable() { |
| public void run() { |
| try { |
| result[0] = element.createExecutableExtension(classAttribute); |
| } catch (Exception e) { |
| // catch and log ANY exception from extension point |
| handleCreateExecutableException(result, e); |
| } |
| } |
| }); |
| } |
| return result[0]; |
| } |
| |
| private static void handleCreateExecutableException(final Object[] result, Throwable e) { |
| Logger.logException(e); |
| result[0] = null; |
| } |
| |
| private String id; |
| |
| private ActionContributionItem item; |
| private String menuGroup; |
| private String menuPath; |
| private String popupmenuGroup; |
| private String popupmenuPath; |
| private String toolbarGroup; |
| private String toolbarPath; |
| |
| /** |
| * Creates a new descriptor with the targetType |
| */ |
| public ActionDescriptor(IConfigurationElement actionElement) throws CoreException { |
| |
| // Calculate menu and toolbar paths. |
| String mpath = actionElement.getAttribute(ATT_MENUBAR_PATH); |
| String mgroup = null; |
| if (mpath != null) { |
| int loc = mpath.lastIndexOf('/'); |
| if (loc != -1) { |
| mgroup = mpath.substring(loc + 1); |
| mpath = mpath.substring(0, loc); |
| } else { |
| mgroup = mpath; |
| mpath = null; |
| } |
| } |
| menuPath = mpath; |
| menuGroup = mgroup; |
| |
| String ppath = actionElement.getAttribute(ATT_POPUPMENU_PATH); |
| String pgroup = null; |
| if (ppath != null) { |
| int loc = ppath.lastIndexOf('/'); |
| if (loc != -1) { |
| pgroup = ppath.substring(loc + 1); |
| ppath = ppath.substring(0, loc); |
| } else { |
| pgroup = ppath; |
| ppath = null; |
| } |
| } |
| popupmenuPath = ppath; |
| popupmenuGroup = pgroup; |
| |
| String tpath = actionElement.getAttribute(ATT_TOOLBAR_PATH); |
| String tgroup = null; |
| if (tpath != null) { |
| int loc = tpath.lastIndexOf('/'); |
| if (loc != -1) { |
| tgroup = tpath.substring(loc + 1); |
| tpath = tpath.substring(0, loc); |
| } else { |
| tgroup = tpath; |
| tpath = null; |
| } |
| } |
| toolbarPath = tpath; |
| toolbarGroup = tgroup; |
| |
| // Create action. |
| IAction action = createAction(actionElement); |
| if (action == null) |
| return; |
| |
| String label = actionElement.getAttribute(ATT_LABEL); |
| if (label != null) |
| action.setText(label); |
| |
| id = actionElement.getAttribute(ATT_ID); |
| if (id == null) { |
| id = actionElement.getAttribute(ATT_CLASS); |
| } |
| if (id != null) |
| action.setId(id); |
| |
| String defId = actionElement.getAttribute(ATT_DEFINITION_ID); |
| if (defId != null && defId.length() != 0) { |
| action.setActionDefinitionId(defId); |
| } |
| |
| String tooltip = actionElement.getAttribute(ATT_TOOLTIP); |
| if (tooltip != null) |
| action.setToolTipText(tooltip); |
| |
| String helpContextId = actionElement.getAttribute(ATT_HELP_CONTEXT_ID); |
| if (helpContextId != null) { |
| String fullID = helpContextId; |
| if (helpContextId.indexOf(".") == -1) //$NON-NLS-1$ |
| // For backward compatibility we auto qualify the id if it is |
| // not qualified) |
| fullID = actionElement.getDeclaringExtension().getNamespace() + "." + helpContextId; //$NON-NLS-1$ |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(action, fullID); |
| } |
| |
| String description = actionElement.getAttribute(ATT_DESCRIPTION); |
| if (description != null) |
| action.setDescription(description); |
| |
| String state = actionElement.getAttribute(ATT_STATE); |
| if (state != null) { |
| action.setChecked(state.equals("true")); //$NON-NLS-1$ |
| } |
| |
| String icon = actionElement.getAttribute(ATT_ICON); |
| if (icon != null) { |
| action.setImageDescriptor(ImageUtil.getImageDescriptorFromExtension(actionElement.getDeclaringExtension(), icon)); |
| } |
| |
| String hoverIcon = actionElement.getAttribute(ATT_HOVERICON); |
| if (hoverIcon != null) { |
| action.setHoverImageDescriptor(ImageUtil.getImageDescriptorFromExtension(actionElement.getDeclaringExtension(), hoverIcon)); |
| } |
| |
| String disabledIcon = actionElement.getAttribute(ATT_DISABLEDICON); |
| if (disabledIcon != null) { |
| action.setDisabledImageDescriptor(ImageUtil.getImageDescriptorFromExtension(actionElement.getDeclaringExtension(), disabledIcon)); |
| } |
| |
| String accelerator = actionElement.getAttribute(ATT_ACCELERATOR); |
| if (accelerator != null) |
| processAccelerator(action, accelerator); |
| |
| item = new ActionContributionItem(action); |
| } |
| |
| /** |
| * Parses the given accelerator text, and converts it to an accelerator |
| * key code. |
| * |
| * @param acceleratorText |
| * the accelerator text |
| * @result the SWT key code, or 0 if there is no accelerator |
| */ |
| private int convertAccelerator(String acceleratorText) { |
| int accelerator = 0; |
| StringTokenizer stok = new StringTokenizer(acceleratorText, "+"); //$NON-NLS-1$ |
| |
| int keyCode = -1; |
| |
| boolean hasMoreTokens = stok.hasMoreTokens(); |
| while (hasMoreTokens) { |
| String token = stok.nextToken(); |
| hasMoreTokens = stok.hasMoreTokens(); |
| // Every token except the last must be one of the modifiers |
| // Ctrl, Shift, or Alt. |
| if (hasMoreTokens) { |
| int modifier = Action.findModifier(token); |
| if (modifier != 0) { |
| accelerator |= modifier; |
| } else { //Leave if there are none |
| return 0; |
| } |
| } else { |
| keyCode = Action.findKeyCode(token); |
| } |
| } |
| if (keyCode != -1) { |
| accelerator |= keyCode; |
| } |
| return accelerator; |
| } |
| |
| /** |
| */ |
| private IAction createAction(IConfigurationElement actionElement) { |
| Object action = new ExtendedEditorActionProxyForDelayLoading(actionElement, ATT_CLASS); |
| if (action == null) |
| return null; |
| if (action instanceof IActionValidator) { |
| if (!((IActionValidator) action).isValidAction()) |
| return null; |
| } |
| return (action instanceof IAction ? (IAction) ExtendedEditorActionProxy.newInstance(action) : null); |
| } |
| |
| /** |
| * Returns the action object held in this descriptor. |
| */ |
| public IAction getAction() { |
| return (item != null ? item.getAction() : null); |
| } |
| |
| /** |
| * Returns the IContributionItem object held in this descriptor. |
| */ |
| public IContributionItem getContributionItem() { |
| return item; |
| } |
| |
| /** |
| * Returns action's id as defined in the registry. |
| */ |
| public String getId() { |
| return id; |
| } |
| |
| /** |
| * Returns named slot (group) in the menu where this action should be |
| * added. |
| */ |
| public String getMenuGroup() { |
| return menuGroup; |
| } |
| |
| /** |
| * Returns menu path where this action should be added. If null, the |
| * action will not be added into the menu. |
| */ |
| |
| public String getMenuPath() { |
| return menuPath; |
| } |
| |
| /** |
| * Returns named slot (group) in the popup menu where this action should |
| * be added. |
| */ |
| public String getPopupMenuGroup() { |
| return popupmenuGroup; |
| } |
| |
| /** |
| * Returns popup menu path where this action should be added. If null, the |
| * action will not be added into the popup menu. |
| */ |
| |
| public String getPopupMenuPath() { |
| return popupmenuPath; |
| } |
| |
| /** |
| * Returns the named slot (group) in the tool bar where this action should |
| * be added. |
| */ |
| |
| public String getToolbarGroup() { |
| return toolbarGroup; |
| } |
| |
| /** |
| * Returns path in the tool bar where this action should be added. If |
| * null, action will not be added to the tool bar. |
| */ |
| public String getToolbarPath() { |
| return toolbarPath; |
| } |
| |
| /** |
| * Process the accelerator definition. If it is a number then process the |
| * code directly - if not then parse it and create the code |
| */ |
| private void processAccelerator(IAction action, String acceleratorText) { |
| |
| if (acceleratorText.length() == 0) |
| return; |
| |
| //Is it a numeric definition? |
| if (Character.isDigit(acceleratorText.charAt(0))) { |
| try { |
| action.setAccelerator(Integer.valueOf(acceleratorText).intValue()); |
| } catch (NumberFormatException exception) { |
| Logger.log(Logger.ERROR, "Invalid accelerator declaration: " + id); //$NON-NLS-1$ |
| } |
| } else |
| action.setAccelerator(convertAccelerator(acceleratorText)); |
| } |
| |
| /** |
| * For debugging only. |
| */ |
| public String toString() { |
| return "ActionDescriptor(" + id + ")"; //$NON-NLS-2$//$NON-NLS-1$ |
| } |
| } |