blob: 4f615e71c9ba29987ea0294c2833270adbfe95d5 [file] [log] [blame]
/*******************************************************************************
* 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$
}
}