0001: /*******************************************************************************
0002: * Copyright (c) 2005, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.ui.internal.menus;
0011:
0012: import java.util.ArrayList;
0013: import java.util.Collection;
0014: import java.util.HashMap;
0015: import java.util.HashSet;
0016: import java.util.Iterator;
0017: import java.util.List;
0018: import java.util.Map;
0019:
0020: import org.eclipse.core.commands.Category;
0021: import org.eclipse.core.commands.Command;
0022: import org.eclipse.core.commands.CommandEvent;
0023: import org.eclipse.core.commands.ICommandListener;
0024: import org.eclipse.core.commands.IHandler;
0025: import org.eclipse.core.commands.ParameterizedCommand;
0026: import org.eclipse.core.commands.State;
0027: import org.eclipse.core.expressions.Expression;
0028: import org.eclipse.core.runtime.IConfigurationElement;
0029: import org.eclipse.core.runtime.IExtensionRegistry;
0030: import org.eclipse.core.runtime.IRegistryChangeEvent;
0031: import org.eclipse.core.runtime.Platform;
0032: import org.eclipse.jface.action.Action;
0033: import org.eclipse.jface.action.LegacyActionTools;
0034: import org.eclipse.jface.bindings.Binding;
0035: import org.eclipse.jface.bindings.Scheme;
0036: import org.eclipse.jface.bindings.keys.IKeyLookup;
0037: import org.eclipse.jface.bindings.keys.KeyBinding;
0038: import org.eclipse.jface.bindings.keys.KeyLookupFactory;
0039: import org.eclipse.jface.bindings.keys.KeySequence;
0040: import org.eclipse.jface.bindings.keys.KeyStroke;
0041: import org.eclipse.jface.commands.RadioState;
0042: import org.eclipse.jface.commands.ToggleState;
0043: import org.eclipse.jface.contexts.IContextIds;
0044: import org.eclipse.jface.menus.IMenuStateIds;
0045: import org.eclipse.ui.IWorkbenchWindow;
0046: import org.eclipse.ui.PlatformUI;
0047: import org.eclipse.ui.SelectionEnabler;
0048: import org.eclipse.ui.commands.ICommandService;
0049: import org.eclipse.ui.handlers.IHandlerActivation;
0050: import org.eclipse.ui.handlers.IHandlerService;
0051: import org.eclipse.ui.internal.ActionExpression;
0052: import org.eclipse.ui.internal.WorkbenchMessages;
0053: import org.eclipse.ui.internal.WorkbenchPlugin;
0054: import org.eclipse.ui.internal.expressions.LegacyActionExpressionWrapper;
0055: import org.eclipse.ui.internal.expressions.LegacyActionSetExpression;
0056: import org.eclipse.ui.internal.expressions.LegacyEditorContributionExpression;
0057: import org.eclipse.ui.internal.expressions.LegacySelectionEnablerWrapper;
0058: import org.eclipse.ui.internal.expressions.LegacyViewContributionExpression;
0059: import org.eclipse.ui.internal.expressions.LegacyViewerContributionExpression;
0060: import org.eclipse.ui.internal.handlers.ActionDelegateHandlerProxy;
0061: import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
0062: import org.eclipse.ui.internal.keys.BindingService;
0063: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
0064: import org.eclipse.ui.internal.services.RegistryPersistence;
0065: import org.eclipse.ui.keys.IBindingService;
0066:
0067: /**
0068: * <p>
0069: * A static class for reading actions from the registry. Actions were the
0070: * mechanism in 3.1 and earlier for contributing to menus and tool bars in the
0071: * Eclipse workbench. They have since been replaced with commands.
0072: * </p>
0073: * <p>
0074: * This class is not intended for use outside of the
0075: * <code>org.eclipse.ui.workbench</code> plug-in.
0076: * </p>
0077: *
0078: * @since 3.2
0079: */
0080: public final class LegacyActionPersistence extends RegistryPersistence {
0081:
0082: /**
0083: * The index of the action set elements in the indexed array.
0084: *
0085: * @see LegacyActionPersistence#read()
0086: */
0087: private static final int INDEX_ACTION_SETS = 0;
0088:
0089: /**
0090: * The index of the editor contribution elements in the indexed array.
0091: *
0092: * @see LegacyActionPersistence#read()
0093: */
0094: private static final int INDEX_EDITOR_CONTRIBUTIONS = 1;
0095:
0096: /**
0097: * The index of the object contribution elements in the indexed array.
0098: *
0099: * @see LegacyActionPersistence#read()
0100: */
0101: private static final int INDEX_OBJECT_CONTRIBUTIONS = 2;
0102:
0103: /**
0104: * The index of the view contribution elements in the indexed array.
0105: *
0106: * @see LegacyActionPersistence#read()
0107: */
0108: private static final int INDEX_VIEW_CONTRIBUTIONS = 3;
0109:
0110: /**
0111: * The index of the viewer contribution elements in the indexed array.
0112: *
0113: * @see LegacyActionPersistence#read()
0114: */
0115: private static final int INDEX_VIEWER_CONTRIBUTIONS = 4;
0116:
0117: /**
0118: * Reads the visibility element for a contribution from the
0119: * <code>org.eclipse.ui.popupMenus</code> extension point.
0120: *
0121: * @param parentElement
0122: * The contribution element which contains a visibility
0123: * expression; must not be <code>null</code>.
0124: * @param parentId
0125: * The identifier of the parent contribution; may be
0126: * <code>null</code>.
0127: * @param warningsToLog
0128: * The list of warnings to be logged; must not be
0129: * <code>null</code>.
0130: * @return An expression representing the visibility element; may be
0131: * <code>null</code>.
0132: */
0133: private static final Expression readVisibility(
0134: final IConfigurationElement parentElement,
0135: final String parentId, final List warningsToLog) {
0136: final IConfigurationElement[] visibilityElements = parentElement
0137: .getChildren(TAG_VISIBILITY);
0138: if ((visibilityElements == null)
0139: || (visibilityElements.length == 0)) {
0140: return null;
0141: }
0142:
0143: if (visibilityElements.length != 1) {
0144: addWarning(
0145: warningsToLog,
0146: "There can only be one visibility element", parentElement, //$NON-NLS-1$
0147: parentId);
0148: }
0149:
0150: final IConfigurationElement visibilityElement = visibilityElements[0];
0151: final ActionExpression visibilityActionExpression = new ActionExpression(
0152: visibilityElement);
0153: final LegacyActionExpressionWrapper wrapper = new LegacyActionExpressionWrapper(
0154: visibilityActionExpression, null);
0155: return wrapper;
0156: }
0157:
0158: /**
0159: * The binding manager which should be populated with bindings from actions;
0160: * must not be <code>null</code>.
0161: */
0162: private final BindingService bindingService;
0163:
0164: /**
0165: * The command service which is providing the commands for the workbench;
0166: * must not be <code>null</code>.
0167: */
0168: private final ICommandService commandService;
0169:
0170: /**
0171: * The handler activations that have come from the registry. This is used to
0172: * flush the activations when the registry is re-read. This value is never
0173: * <code>null</code>
0174: */
0175: private final Collection handlerActivations = new ArrayList();
0176:
0177: /**
0178: * The menu contributions that have come from the registry. This is used to
0179: * flush the contributions when the registry is re-read. This value is never
0180: * <code>null</code>
0181: */
0182: private final Collection menuContributions = new ArrayList();
0183:
0184: /**
0185: * The service locator from which services can be retrieved in the future;
0186: * must not be <code>null</code>.
0187: */
0188: private final IWorkbenchWindow window;
0189:
0190: /**
0191: * Help action sets with enable/disable.
0192: */
0193: private ICommandListener actionSetListener = new ICommandListener() {
0194: public void commandChanged(CommandEvent commandEvent) {
0195: Command cmd = commandEvent.getCommand();
0196: String commandId = cmd.getId();
0197: Binding binding = (Binding) commandIdToBinding
0198: .get(commandId);
0199: if (binding != null) {
0200: if (cmd.isEnabled()) {
0201: if (!actionSetActiveBindings.contains(binding)) {
0202: bindingService.addBinding(binding);
0203: actionSetActiveBindings.add(binding);
0204: }
0205: } else if (actionSetActiveBindings.contains(binding)) {
0206: bindingService.removeBinding(binding);
0207: actionSetActiveBindings.remove(binding);
0208: }
0209: }
0210: }
0211: };
0212:
0213: /**
0214: * Map every commandId to its binding.
0215: */
0216: private HashMap commandIdToBinding = new HashMap();
0217:
0218: /**
0219: * Which bindings do we currently have outstanding.
0220: */
0221: private HashSet actionSetActiveBindings = new HashSet();
0222:
0223: /**
0224: * Constructs a new instance of {@link LegacyActionPersistence}.
0225: *
0226: * @param window
0227: * The window from which the services should be retrieved; must
0228: * not be <code>null</code>.
0229: */
0230: public LegacyActionPersistence(final IWorkbenchWindow window) {
0231: // TODO Blind casts are bad.
0232: this .bindingService = (BindingService) window
0233: .getService(IBindingService.class);
0234:
0235: this .commandService = (ICommandService) window
0236: .getService(ICommandService.class);
0237: this .window = window;
0238: }
0239:
0240: /**
0241: * Deactivates all of the activations made by this class, and then clears
0242: * the collection. This should be called before every read.
0243: */
0244: private final void clearActivations() {
0245: final IHandlerService service = (IHandlerService) window
0246: .getService(IHandlerService.class);
0247: service.deactivateHandlers(handlerActivations);
0248: final Iterator activationItr = handlerActivations.iterator();
0249: while (activationItr.hasNext()) {
0250: final IHandlerActivation activation = (IHandlerActivation) activationItr
0251: .next();
0252: final IHandler handler = activation.getHandler();
0253: if (handler != null) {
0254: handler.dispose();
0255: }
0256: }
0257: handlerActivations.clear();
0258: }
0259:
0260: /**
0261: * Removes all of the bindings made by this class, and then clears the
0262: * collection. This should be called before every read.
0263: */
0264: private final void clearBindings() {
0265: Iterator i = commandIdToBinding.entrySet().iterator();
0266: while (i.hasNext()) {
0267: Map.Entry entry = (Map.Entry) i.next();
0268: String commandId = (String) entry.getKey();
0269: Binding binding = (Binding) entry.getValue();
0270: commandService.getCommand(commandId).removeCommandListener(
0271: actionSetListener);
0272: if (binding != null
0273: && actionSetActiveBindings.contains(binding)) {
0274: bindingService.removeBinding(binding);
0275: }
0276: }
0277: commandIdToBinding.clear();
0278: actionSetActiveBindings.clear();
0279: }
0280:
0281: /**
0282: * Removes all of the image bindings made by this class, and then clears the
0283: * collection. This should be called before every read.
0284: *
0285: */
0286: private final void clearImages() {
0287: // TODO Implement
0288: }
0289:
0290: /**
0291: * Removes all of the contributions made by this class, and then clears the
0292: * collection. This should be called before every read.
0293: */
0294: private final void clearMenus() {
0295: menuContributions.clear();
0296: }
0297:
0298: /**
0299: * Extracts any key bindings from the action. If such a binding exists, it
0300: * is added to the binding manager.
0301: *
0302: * @param element
0303: * The action from which the binding should be read; must not be
0304: * <code>null</code>.
0305: * @param command
0306: * The fully-parameterized command for which a binding should be
0307: * made; must not be <code>null</code>.
0308: */
0309: private final void convertActionToBinding(
0310: final IConfigurationElement element,
0311: final ParameterizedCommand command, final List warningsToLog) {
0312: // Figure out which accelerator text to use.
0313: String acceleratorText = readOptional(element, ATT_ACCELERATOR);
0314: if (acceleratorText == null) {
0315: final String label = readOptional(element, ATT_LABEL);
0316: if (label != null) {
0317: acceleratorText = LegacyActionTools
0318: .extractAcceleratorText(label);
0319: }
0320: }
0321:
0322: // If there is some accelerator text, generate a key sequence from it.
0323: if (acceleratorText != null) {
0324: final IKeyLookup lookup = KeyLookupFactory
0325: .getSWTKeyLookup();
0326: final int acceleratorInt = LegacyActionTools
0327: .convertAccelerator(acceleratorText);
0328: final int modifierMask = lookup.getAlt()
0329: | lookup.getCommand() | lookup.getCtrl()
0330: | lookup.getShift();
0331: final int modifierKeys = acceleratorInt & modifierMask;
0332: final int naturalKey = acceleratorInt & ~modifierMask;
0333: final KeyStroke keyStroke = KeyStroke.getInstance(
0334: modifierKeys, naturalKey);
0335: final KeySequence keySequence = KeySequence
0336: .getInstance(keyStroke);
0337:
0338: final Scheme activeScheme = bindingService
0339: .getActiveScheme();
0340:
0341: try {
0342: final Binding binding = new KeyBinding(keySequence,
0343: command, activeScheme.getId(),
0344: IContextIds.CONTEXT_ID_WINDOW, null, null,
0345: null, Binding.SYSTEM);
0346: commandIdToBinding.put(command.getCommand().getId(),
0347: binding);
0348:
0349: if (command.getCommand().isEnabled()) {
0350: bindingService.addBinding(binding);
0351: actionSetActiveBindings.add(binding);
0352: }
0353:
0354: command.getCommand().addCommandListener(
0355: actionSetListener);
0356: } catch (IllegalArgumentException e) {
0357: addWarning(
0358: warningsToLog,
0359: "invalid keybinding: " + e.getMessage(), element, //$NON-NLS-1$
0360: command.getCommand().getId());
0361: }
0362: }
0363: }
0364:
0365: /**
0366: * Determine which command to use. This is slightly complicated as actions
0367: * do not have to have commands, but the new architecture requires it. As
0368: * such, we will auto-generate a command for the action if the definitionId
0369: * is missing or points to a command that does not yet exist. All such
0370: * command identifiers are prefixed with AUTOGENERATED_COMMAND_ID_PREFIX.
0371: *
0372: * @param element
0373: * The action element from which a command must be generated;
0374: * must not be <code>null</code>.
0375: * @param primaryId
0376: * The primary identifier to use when auto-generating a command;
0377: * must not be <code>null</code>.
0378: * @param secondaryId
0379: * The secondary identifier to use when auto-generating a
0380: * command; must not be <code>null</code>.
0381: * @param warningsToLog
0382: * The collection of warnings logged while reading the extension
0383: * point; must not be <code>null</code>.
0384: * @return the fully-parameterized command; <code>null</code> if an error
0385: * occurred.
0386: */
0387: private final ParameterizedCommand convertActionToCommand(
0388: final IConfigurationElement element,
0389: final String primaryId, final String secondaryId,
0390: final List warningsToLog) {
0391: String commandId = readOptional(element, ATT_DEFINITION_ID);
0392: Command command = null;
0393: if (commandId != null) {
0394: command = commandService.getCommand(commandId);
0395: }
0396:
0397: final IActionCommandMappingService mappingService = (IActionCommandMappingService) window
0398: .getService(IActionCommandMappingService.class);
0399:
0400: String label = null;
0401: if ((commandId == null) || (!command.isDefined())) {
0402: // Add a mapping from this action id to the command id.
0403: if (commandId == null && mappingService != null) {
0404: commandId = mappingService.getGeneratedCommandId(
0405: primaryId, secondaryId);
0406: }
0407: if (commandId == null) {
0408: WorkbenchPlugin.log("MappingService unavailable"); //$NON-NLS-1$
0409: return null;
0410: }
0411:
0412: // Read the label attribute.
0413: label = readRequired(
0414: element,
0415: ATT_LABEL,
0416: warningsToLog,
0417: "Actions require a non-empty label or definitionId", //$NON-NLS-1$
0418: commandId);
0419: if (label == null) {
0420: label = WorkbenchMessages.LegacyActionPersistence_AutogeneratedCommandName;
0421: }
0422:
0423: /*
0424: * Read the tooltip attribute. The tooltip is really the description
0425: * of the command.
0426: */
0427: final String tooltip = readOptional(element, ATT_TOOLTIP);
0428:
0429: // Define the command.
0430: command = commandService.getCommand(commandId);
0431: final Category category = commandService.getCategory(null);
0432: final String name = LegacyActionTools
0433: .removeAcceleratorText(Action
0434: .removeMnemonics(label));
0435: command.define(name, tooltip, category, null);
0436:
0437: // TODO Decide the command state.
0438: final String style = readOptional(element, ATT_STYLE);
0439: if (STYLE_RADIO.equals(style)) {
0440: final State state = new RadioState();
0441: // TODO How to set the id?
0442: final boolean checked = readBoolean(element, ATT_STATE,
0443: false);
0444: state
0445: .setValue((checked) ? Boolean.TRUE
0446: : Boolean.FALSE);
0447: command.addState(IMenuStateIds.STYLE, state);
0448:
0449: } else if (STYLE_TOGGLE.equals(style)) {
0450: final State state = new ToggleState();
0451: final boolean checked = readBoolean(element, ATT_STATE,
0452: false);
0453: state
0454: .setValue((checked) ? Boolean.TRUE
0455: : Boolean.FALSE);
0456: command.addState(IMenuStateIds.STYLE, state);
0457: }
0458: }
0459: // this allows us to look up a "commandId" give the contributionId
0460: // and the actionId
0461: if (mappingService != null && commandId != null) {
0462: mappingService.map(mappingService.getGeneratedCommandId(
0463: primaryId, secondaryId), commandId);
0464: }
0465:
0466: return new ParameterizedCommand(command, null);
0467: }
0468:
0469: /**
0470: * <p>
0471: * Extracts the handler information from the given action element. These are
0472: * registered with the handler service. They are always active.
0473: * </p>
0474: *
0475: * @param element
0476: * The action element from which the handler should be read; must
0477: * not be <code>null</code>.
0478: * @param actionId
0479: * The identifier of the action for which a handler is being
0480: * created; must not be <code>null</code>.
0481: * @param command
0482: * The command for which this handler applies; must not be
0483: * <code>null</code>.
0484: * @param activeWhenExpression
0485: * The expression controlling when the handler is active; may be
0486: * <code>null</code>.
0487: * @param viewId
0488: * The view to which this handler is associated. This value is
0489: * required if this is a view action; otherwise it can be
0490: * <code>null</code>.
0491: * @param warningsToLog
0492: * The collection of warnings while parsing this extension point;
0493: * must not be <code>null</code>.
0494: */
0495: private final void convertActionToHandler(
0496: final IConfigurationElement element, final String actionId,
0497: final ParameterizedCommand command,
0498: final Expression activeWhenExpression, final String viewId,
0499: final List warningsToLog) {
0500: // Check to see if this is a retargettable action.
0501: final boolean retarget = readBoolean(element, ATT_RETARGET,
0502: false);
0503:
0504: final boolean classAvailable = (element.getAttribute(ATT_CLASS) != null)
0505: || (element.getChildren(TAG_CLASS).length != 0);
0506: // Read the class attribute.
0507: String classString = readOptional(element, ATT_CLASS);
0508: if (classAvailable && classString == null) {
0509: classString = readOptional(
0510: element.getChildren(TAG_CLASS)[0], ATT_CLASS);
0511: }
0512:
0513: if (retarget) {
0514: if (classAvailable && !isPulldown(element)) {
0515: addWarning(
0516: warningsToLog,
0517: "The class was not null but retarget was set to true", //$NON-NLS-1$
0518: element, actionId, ATT_CLASS, classString);
0519: }
0520:
0521: // Add a mapping from this action id to the command id.
0522: final IActionCommandMappingService mappingService = (IActionCommandMappingService) window
0523: .getService(IActionCommandMappingService.class);
0524: if (mappingService != null) {
0525: mappingService.map(actionId, command.getId());
0526: } else {
0527: // this is probably the shutdown case where the service has
0528: // already disposed.
0529: addWarning(warningsToLog,
0530: "Retarget service unavailable", //$NON-NLS-1$
0531: element, actionId);
0532: }
0533: return; // This is nothing more to be done.
0534:
0535: } else if (!classAvailable) {
0536: addWarning(
0537: warningsToLog,
0538: "There was no class provided, and the action is not retargettable", //$NON-NLS-1$
0539: element, actionId);
0540: return; // There is nothing to be done.
0541: }
0542:
0543: // Read the enablesFor attribute, and enablement and selection elements.
0544: SelectionEnabler enabler = null;
0545: if (element.getAttribute(ATT_ENABLES_FOR) != null) {
0546: enabler = new SelectionEnabler(element);
0547: } else {
0548: IConfigurationElement[] kids = element
0549: .getChildren(TAG_ENABLEMENT);
0550: if (kids.length > 0) {
0551: enabler = new SelectionEnabler(element);
0552: }
0553: }
0554: final Expression enabledWhenExpression;
0555: if (enabler == null) {
0556: enabledWhenExpression = null;
0557: } else {
0558: enabledWhenExpression = new LegacySelectionEnablerWrapper(
0559: enabler, window);
0560: }
0561:
0562: /*
0563: * Create the handler. TODO The image style is read at the workbench
0564: * level, but it is hard to communicate this information to this point.
0565: * For now, I'll pass null, but this ultimately won't work.
0566: */
0567: final ActionDelegateHandlerProxy handler = new ActionDelegateHandlerProxy(
0568: element, ATT_CLASS, actionId, command, window, null,
0569: enabledWhenExpression, viewId);
0570:
0571: // Read the help context id.
0572: final String helpContextId = readOptional(element,
0573: ATT_HELP_CONTEXT_ID);
0574: if (helpContextId != null) {
0575: commandService.setHelpContextId(handler, helpContextId);
0576: }
0577:
0578: // Activate the handler.
0579: final String commandId = command.getId();
0580: final IHandlerService service = (IHandlerService) window
0581: .getService(IHandlerService.class);
0582: final IHandlerActivation handlerActivation;
0583: if (activeWhenExpression == null) {
0584: handlerActivation = service.activateHandler(commandId,
0585: handler);
0586: } else {
0587: handlerActivation = service.activateHandler(commandId,
0588: handler, activeWhenExpression);
0589: }
0590: handlerActivations.add(handlerActivation);
0591: }
0592:
0593: public final void dispose() {
0594: super .dispose();
0595: clear();
0596: }
0597:
0598: private void clear() {
0599: clearActivations();
0600: clearBindings();
0601: clearImages();
0602: clearMenus();
0603: }
0604:
0605: protected final boolean isChangeImportant(
0606: final IRegistryChangeEvent event) {
0607: return !((event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
0608: IWorkbenchRegistryConstants.PL_ACTION_SETS).length == 0)
0609: && (event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
0610: IWorkbenchRegistryConstants.PL_EDITOR_ACTIONS).length == 0)
0611: && (event.getExtensionDeltas(PlatformUI.PLUGIN_ID,
0612: IWorkbenchRegistryConstants.PL_POPUP_MENU).length == 0) && (event
0613: .getExtensionDeltas(PlatformUI.PLUGIN_ID,
0614: IWorkbenchRegistryConstants.PL_VIEW_ACTIONS).length == 0));
0615: }
0616:
0617: /**
0618: * <p>
0619: * Reads all of the actions from the deprecated extension points. Actions
0620: * have been replaced with commands, command images, handlers, menu elements
0621: * and action sets.
0622: * </p>
0623: * <p>
0624: * TODO Before this method is called, all of the extension points must be
0625: * cleared.
0626: * </p>
0627: */
0628: public final void read() {
0629: clear();
0630: LegacyActionPersistence.super .read();
0631:
0632: // Create the extension registry mementos.
0633: final IExtensionRegistry registry = Platform
0634: .getExtensionRegistry();
0635: int actionSetCount = 0;
0636: int editorContributionCount = 0;
0637: int objectContributionCount = 0;
0638: int viewContributionCount = 0;
0639: int viewerContributionCount = 0;
0640: final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[5][];
0641:
0642: // Sort the actionSets extension point.
0643: final IConfigurationElement[] actionSetsExtensionPoint = registry
0644: .getConfigurationElementsFor(EXTENSION_ACTION_SETS);
0645: for (int i = 0; i < actionSetsExtensionPoint.length; i++) {
0646: final IConfigurationElement element = actionSetsExtensionPoint[i];
0647: final String name = element.getName();
0648: if (TAG_ACTION_SET.equals(name)) {
0649: addElementToIndexedArray(element,
0650: indexedConfigurationElements,
0651: INDEX_ACTION_SETS, actionSetCount++);
0652: }
0653: }
0654:
0655: // Sort the editorActions extension point.
0656: final IConfigurationElement[] editorActionsExtensionPoint = registry
0657: .getConfigurationElementsFor(EXTENSION_EDITOR_ACTIONS);
0658: for (int i = 0; i < editorActionsExtensionPoint.length; i++) {
0659: final IConfigurationElement element = editorActionsExtensionPoint[i];
0660: final String name = element.getName();
0661: if (TAG_EDITOR_CONTRIBUTION.equals(name)) {
0662: addElementToIndexedArray(element,
0663: indexedConfigurationElements,
0664: INDEX_EDITOR_CONTRIBUTIONS,
0665: editorContributionCount++);
0666: }
0667: }
0668:
0669: // Sort the popupMenus extension point.
0670: final IConfigurationElement[] popupMenusExtensionPoint = registry
0671: .getConfigurationElementsFor(EXTENSION_POPUP_MENUS);
0672: for (int i = 0; i < popupMenusExtensionPoint.length; i++) {
0673: final IConfigurationElement element = popupMenusExtensionPoint[i];
0674: final String name = element.getName();
0675: if (TAG_OBJECT_CONTRIBUTION.equals(name)) {
0676: addElementToIndexedArray(element,
0677: indexedConfigurationElements,
0678: INDEX_OBJECT_CONTRIBUTIONS,
0679: objectContributionCount++);
0680: } else if (TAG_VIEWER_CONTRIBUTION.equals(name)) {
0681: addElementToIndexedArray(element,
0682: indexedConfigurationElements,
0683: INDEX_VIEWER_CONTRIBUTIONS,
0684: viewerContributionCount++);
0685: }
0686: }
0687:
0688: // Sort the viewActions extension point.
0689: final IConfigurationElement[] viewActionsExtensionPoint = registry
0690: .getConfigurationElementsFor(EXTENSION_VIEW_ACTIONS);
0691: for (int i = 0; i < viewActionsExtensionPoint.length; i++) {
0692: final IConfigurationElement element = viewActionsExtensionPoint[i];
0693: final String name = element.getName();
0694: if (TAG_VIEW_CONTRIBUTION.equals(name)) {
0695: addElementToIndexedArray(element,
0696: indexedConfigurationElements,
0697: INDEX_VIEW_CONTRIBUTIONS,
0698: viewContributionCount++);
0699: }
0700: }
0701:
0702: readActionSets(indexedConfigurationElements[INDEX_ACTION_SETS],
0703: actionSetCount);
0704: readEditorContributions(
0705: indexedConfigurationElements[INDEX_EDITOR_CONTRIBUTIONS],
0706: editorContributionCount);
0707: readObjectContributions(
0708: indexedConfigurationElements[INDEX_OBJECT_CONTRIBUTIONS],
0709: objectContributionCount);
0710: readViewContributions(
0711: indexedConfigurationElements[INDEX_VIEW_CONTRIBUTIONS],
0712: viewContributionCount);
0713: readViewerContributions(
0714: indexedConfigurationElements[INDEX_VIEWER_CONTRIBUTIONS],
0715: viewerContributionCount);
0716:
0717: }
0718:
0719: /**
0720: * Reads the actions, and defines all the necessary subcomponents in terms
0721: * of the command architecture. For each action, there could be a command, a
0722: * command image binding, a handler and a menu item.
0723: *
0724: * @param primaryId
0725: * The identifier of the primary object to which this action
0726: * belongs. This is used to auto-generate command identifiers
0727: * when required. The <code>primaryId</code> must not be
0728: * <code>null</code>.
0729: * @param elements
0730: * The action elements to be read; must not be <code>null</code>.
0731: * @param warningsToLog
0732: * The collection of warnings while parsing this extension point;
0733: * must not be <code>null</code>.
0734: * @param visibleWhenExpression
0735: * The expression controlling visibility of the corresponding
0736: * menu elements; may be <code>null</code>.
0737: * @param viewId
0738: * The view to which this handler is associated. This value is
0739: * required if this is a view action; otherwise it can be
0740: * <code>null</code>.
0741: * @return References to the created menu elements; may be <code>null</code>,
0742: * and may be empty.
0743: */
0744: private final void readActions(final String primaryId,
0745: final IConfigurationElement[] elements,
0746: final List warningsToLog,
0747: final Expression visibleWhenExpression, final String viewId) {
0748: for (int i = 0; i < elements.length; i++) {
0749: final IConfigurationElement element = elements[i];
0750:
0751: /*
0752: * We might need the identifier to generate the command, so we'll
0753: * read it out now.
0754: */
0755: final String id = readRequired(element, ATT_ID,
0756: warningsToLog, "Actions require an id"); //$NON-NLS-1$
0757: if (id == null) {
0758: continue;
0759: }
0760:
0761: // Try to break out the command part of the action.
0762: final ParameterizedCommand command = convertActionToCommand(
0763: element, primaryId, id, warningsToLog);
0764: if (command == null) {
0765: continue;
0766: }
0767:
0768: convertActionToHandler(element, id, command,
0769: visibleWhenExpression, viewId, warningsToLog);
0770: // TODO Read the overrideActionId attribute
0771:
0772: convertActionToBinding(element, command, warningsToLog);
0773:
0774: }
0775: }
0776:
0777: /**
0778: * Reads all of the action and menu child elements from the given element.
0779: *
0780: * @param element
0781: * The configuration element from which the actions and menus
0782: * should be read; must not be <code>null</code>, but may be
0783: * empty.
0784: * @param id
0785: * The identifier of the contribution being made. This could be
0786: * an action set, an editor contribution, a view contribution, a
0787: * viewer contribution or an object contribution. This value must
0788: * not be <code>null</code>.
0789: * @param warningsToLog
0790: * The list of warnings already logged for this extension point;
0791: * must not be <code>null</code>.
0792: * @param visibleWhenExpression
0793: * The expression controlling visibility of the corresponding
0794: * menu elements; may be <code>null</code>.
0795: * @param viewId
0796: * The view to which this handler is associated. This value is
0797: * required if this is a view action; otherwise it can be
0798: * <code>null</code>.
0799: * @return An array of references to the created menu elements. This value
0800: * may be <code>null</code> if there was a problem parsing the
0801: * configuration element.
0802: */
0803: private final void readActionsAndMenus(
0804: final IConfigurationElement element, final String id,
0805: final List warningsToLog,
0806: final Expression visibleWhenExpression, final String viewId) {
0807:
0808: // Read its child elements.
0809: final IConfigurationElement[] actionElements = element
0810: .getChildren(TAG_ACTION);
0811: readActions(id, actionElements, warningsToLog,
0812: visibleWhenExpression, viewId);
0813:
0814: }
0815:
0816: /**
0817: * Reads the deprecated actions from an array of elements from the action
0818: * sets extension point.
0819: *
0820: * @param configurationElements
0821: * The configuration elements in the extension point; must not be
0822: * <code>null</code>, but may be empty.
0823: * @param configurationElementCount
0824: * The number of configuration elements that are really in the
0825: * array.
0826: */
0827: private final void readActionSets(
0828: final IConfigurationElement[] configurationElements,
0829: final int configurationElementCount) {
0830: //
0831: // this was an even dumber fix than modifying the path
0832: //
0833: // stupid navigate group
0834: // SGroup nav = menuService.getGroup(STUPID_NAVIGATE);
0835: // if (!nav.isDefined()) {
0836: // nav.define(new SLocation(new SBar(SBar.TYPE_MENU, null)));
0837: // }
0838: // stupid navigate group
0839:
0840: final List warningsToLog = new ArrayList(1);
0841:
0842: for (int i = 0; i < configurationElementCount; i++) {
0843: final IConfigurationElement element = configurationElements[i];
0844:
0845: // Read the action set identifier.
0846: final String id = readRequired(element, ATT_ID,
0847: warningsToLog, "Action sets need an id"); //$NON-NLS-1$
0848: if (id == null) {
0849: continue;
0850: }
0851:
0852: // Read the label.
0853: final String label = readRequired(element, ATT_LABEL,
0854: warningsToLog, "Actions set need a label", //$NON-NLS-1$
0855: id);
0856: if (label == null) {
0857: continue;
0858: }
0859:
0860: // Restrict the handler to when the action set is active.
0861: final LegacyActionSetExpression expression = new LegacyActionSetExpression(
0862: id, window);
0863:
0864: // Read all of the child elements.
0865: readActionsAndMenus(element, id, warningsToLog, expression,
0866: null);
0867: // Define the action set.
0868: }
0869:
0870: logWarnings(
0871: warningsToLog,
0872: "Warnings while parsing the action sets from the 'org.eclipse.ui.actionSets' extension point"); //$NON-NLS-1$
0873: }
0874:
0875: /**
0876: * Reads the deprecated editor contributions from an array of elements from
0877: * the editor actions extension point.
0878: *
0879: * @param configurationElements
0880: * The configuration elements in the extension point; must not be
0881: * <code>null</code>, but may be empty.
0882: * @param configurationElementCount
0883: * The number of configuration elements that are really in the
0884: * array.
0885: */
0886: private final void readEditorContributions(
0887: final IConfigurationElement[] configurationElements,
0888: final int configurationElementCount) {
0889: final List warningsToLog = new ArrayList(1);
0890:
0891: for (int i = 0; i < configurationElementCount; i++) {
0892: final IConfigurationElement element = configurationElements[i];
0893:
0894: // Read the editor contribution identifier.
0895: final String id = readRequired(element, ATT_ID,
0896: warningsToLog, "Editor contributions need an id"); //$NON-NLS-1$
0897: if (id == null) {
0898: continue;
0899: }
0900:
0901: /*
0902: * Read the target id. This is the identifier of the editor with
0903: * which these contributions are associated.
0904: */
0905: final String targetId = readRequired(element,
0906: ATT_TARGET_ID, warningsToLog,
0907: "Editor contributions need a target id", id); //$NON-NLS-1$
0908: if (targetId == null) {
0909: continue;
0910: }
0911: final Expression visibleWhenExpression = new LegacyEditorContributionExpression(
0912: targetId, window);
0913:
0914: // Read all of the child elements from the registry.
0915: readActionsAndMenus(element, id, warningsToLog,
0916: visibleWhenExpression, null);
0917: }
0918:
0919: logWarnings(
0920: warningsToLog,
0921: "Warnings while parsing the editor contributions from the 'org.eclipse.ui.editorActions' extension point"); //$NON-NLS-1$
0922: }
0923:
0924: /**
0925: * Reads the deprecated object contributions from an array of elements from
0926: * the popup menus extension point.
0927: *
0928: * @param configurationElements
0929: * The configuration elements in the extension point; must not be
0930: * <code>null</code>, but may be empty.
0931: * @param configurationElementCount
0932: * The number of configuration elements that are really in the
0933: * array.
0934: */
0935: private final void readObjectContributions(
0936: final IConfigurationElement[] configurationElements,
0937: final int configurationElementCount) {
0938: final List warningsToLog = new ArrayList(1);
0939:
0940: for (int i = 0; i < configurationElementCount; i++) {
0941: final IConfigurationElement element = configurationElements[i];
0942:
0943: // Read the object contribution identifier.
0944: final String id = readRequired(element, ATT_ID,
0945: warningsToLog, "Object contributions need an id"); //$NON-NLS-1$
0946: if (id == null) {
0947: continue;
0948: }
0949:
0950: // Read the object class. This influences the visibility.
0951: final String objectClass = readRequired(element,
0952: ATT_OBJECTCLASS, warningsToLog,
0953: "Object contributions need an object class", id); //$NON-NLS-1$
0954: if (objectClass == null) {
0955: continue;
0956: }
0957:
0958: // TODO Read the name filter. This influences the visibility.
0959: // final String nameFilter = readOptional(element,
0960: // ATT_NAME_FILTER);
0961:
0962: // TODO Read the object class. This influences the visibility.
0963: // final boolean adaptable = readBoolean(element,
0964: // ATT_ADAPTABLE,
0965: // false);
0966:
0967: // TODO Read the filter elements.
0968: // TODO Read the enablement elements.
0969:
0970: // TODO Figure out an appropriate visibility expression.
0971: // Read the visibility element, if any.
0972: final Expression visibleWhenExpression = readVisibility(
0973: element, id, warningsToLog);
0974:
0975: // Read all of the child elements from the registry.
0976: readActionsAndMenus(element, id, warningsToLog,
0977: visibleWhenExpression, null);
0978: }
0979:
0980: logWarnings(
0981: warningsToLog,
0982: "Warnings while parsing the object contributions from the 'org.eclipse.ui.popupMenus' extension point"); //$NON-NLS-1$
0983: }
0984:
0985: /**
0986: * Reads the deprecated view contributions from an array of elements from
0987: * the view actions extension point.
0988: *
0989: * @param configurationElements
0990: * The configuration elements in the extension point; must not be
0991: * <code>null</code>, but may be empty.
0992: * @param configurationElementCount
0993: * The number of configuration elements that are really in the
0994: * array.
0995: */
0996: private final void readViewContributions(
0997: final IConfigurationElement[] configurationElements,
0998: final int configurationElementCount) {
0999: final List warningsToLog = new ArrayList(1);
1000:
1001: for (int i = 0; i < configurationElementCount; i++) {
1002: final IConfigurationElement element = configurationElements[i];
1003:
1004: // Read the view contribution identifier.
1005: final String id = readRequired(element, ATT_ID,
1006: warningsToLog, "View contributions need an id"); //$NON-NLS-1$
1007: if (id == null) {
1008: continue;
1009: }
1010:
1011: /*
1012: * Read the target id. This is the identifier of the view with which
1013: * these contributions are associated.
1014: */
1015: final String targetId = readRequired(element,
1016: ATT_TARGET_ID, warningsToLog,
1017: "View contributions need a target id", id); //$NON-NLS-1$
1018: if (targetId == null) {
1019: continue;
1020: }
1021: final Expression visibleWhenExpression = new LegacyViewContributionExpression(
1022: targetId, window);
1023:
1024: // Read all of the child elements from the registry.
1025: readActionsAndMenus(element, id, warningsToLog,
1026: visibleWhenExpression, targetId);
1027: }
1028:
1029: logWarnings(
1030: warningsToLog,
1031: "Warnings while parsing the view contributions from the 'org.eclipse.ui.viewActions' extension point"); //$NON-NLS-1$
1032: }
1033:
1034: /**
1035: * Reads the deprecated viewer contributions from an array of elements from
1036: * the popup menus extension point.
1037: *
1038: * @param configurationElements
1039: * The configuration elements in the extension point; must not be
1040: * <code>null</code>, but may be empty.
1041: * @param configurationElementCount
1042: * The number of configuration elements that are really in the
1043: * array.
1044: */
1045: private final void readViewerContributions(
1046: final IConfigurationElement[] configurationElements,
1047: final int configurationElementCount) {
1048: final List warningsToLog = new ArrayList(1);
1049:
1050: for (int i = 0; i < configurationElementCount; i++) {
1051: final IConfigurationElement element = configurationElements[i];
1052:
1053: // Read the viewer contribution identifier.
1054: final String id = readRequired(element, ATT_ID,
1055: warningsToLog, "Viewer contributions need an id"); //$NON-NLS-1$
1056: if (id == null) {
1057: continue;
1058: }
1059:
1060: /*
1061: * Read the target id. This is the identifier of the view with which
1062: * these contributions are associated.
1063: */
1064: final String targetId = readRequired(element,
1065: ATT_TARGET_ID, warningsToLog,
1066: "Viewer contributions need a target id", id); //$NON-NLS-1$
1067: if (targetId == null) {
1068: continue;
1069: }
1070:
1071: // Read the visibility element, if any.
1072: final Expression visibleWhenExpression = readVisibility(
1073: element, id, warningsToLog);
1074: final Expression menuVisibleWhenExpression = new LegacyViewerContributionExpression(
1075: targetId, window, visibleWhenExpression);
1076:
1077: // Read all of the child elements from the registry.
1078: readActionsAndMenus(element, id, warningsToLog,
1079: menuVisibleWhenExpression, targetId);
1080: }
1081:
1082: logWarnings(
1083: warningsToLog,
1084: "Warnings while parsing the viewer contributions from the 'org.eclipse.ui.popupMenus' extension point"); //$NON-NLS-1$
1085: }
1086: }
|