001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: ******************************************************************************/package org.eclipse.ui.actions;
011:
012: import java.util.Collections;
013:
014: import org.eclipse.core.commands.ExecutionException;
015: import org.eclipse.core.commands.IHandler;
016: import org.eclipse.core.commands.NotEnabledException;
017: import org.eclipse.core.commands.NotHandledException;
018: import org.eclipse.core.commands.common.NotDefinedException;
019: import org.eclipse.core.expressions.EvaluationContext;
020: import org.eclipse.core.expressions.IEvaluationContext;
021: import org.eclipse.core.runtime.IConfigurationElement;
022: import org.eclipse.jface.viewers.StructuredSelection;
023: import org.eclipse.swt.widgets.Event;
024: import org.eclipse.ui.IEditorSite;
025: import org.eclipse.ui.IPartListener;
026: import org.eclipse.ui.ISources;
027: import org.eclipse.ui.IWorkbench;
028: import org.eclipse.ui.IWorkbenchPart;
029: import org.eclipse.ui.IWorkbenchPartSite;
030: import org.eclipse.ui.IWorkbenchWindow;
031: import org.eclipse.ui.handlers.IHandlerService;
032: import org.eclipse.ui.internal.actions.CommandAction;
033: import org.eclipse.ui.internal.handlers.ActionDelegateHandlerProxy;
034: import org.eclipse.ui.internal.handlers.HandlerService;
035: import org.eclipse.ui.internal.handlers.IActionCommandMappingService;
036: import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
037: import org.eclipse.ui.part.MultiPageEditorSite;
038: import org.eclipse.ui.services.IServiceLocator;
039:
040: /**
041: * For a declarative editor action, see if we can link it to a command.
042: * <p>
043: * This is a legacy bridge class, and should not be used outside of the Eclipse
044: * SDK. Please use menu contributions to display a command in a menu or toolbar.
045: * </p>
046: * <p>
047: * <b>Note:</b> Clients may instantiate.
048: * </p>
049: *
050: * @since 3.3
051: */
052: public final class ContributedAction extends CommandAction {
053: private IEvaluationContext appContext;
054:
055: private IHandler partHandler;
056:
057: private boolean localHandler = false;
058:
059: private IPartListener partListener;
060:
061: /**
062: * Create an action that can call a command.
063: *
064: * @param locator
065: * The appropriate service locator to use. If you use a part site
066: * as your locator, this action will be tied to your part.
067: * @param element
068: * the contributed action element
069: */
070: public ContributedAction(IServiceLocator locator,
071: IConfigurationElement element)
072: throws CommandNotMappedException {
073:
074: String actionId = element
075: .getAttribute(IWorkbenchRegistryConstants.ATT_ID);
076: String commandId = element
077: .getAttribute(IWorkbenchRegistryConstants.ATT_DEFINITION_ID);
078:
079: // TODO throw some more exceptions here :-)
080:
081: String contributionId = null;
082: if (commandId == null) {
083:
084: Object obj = element.getParent();
085: if (obj instanceof IConfigurationElement) {
086: contributionId = ((IConfigurationElement) obj)
087: .getAttribute(IWorkbenchRegistryConstants.ATT_ID);
088: if (contributionId == null) {
089: throw new CommandNotMappedException("Action " //$NON-NLS-1$
090: + actionId
091: + " configuration element invalid"); //$NON-NLS-1$
092: }
093: }
094: // legacy bridge part
095: IActionCommandMappingService mapping = (IActionCommandMappingService) locator
096: .getService(IActionCommandMappingService.class);
097: if (mapping == null) {
098: throw new CommandNotMappedException(
099: "No action mapping service available"); //$NON-NLS-1$
100: }
101:
102: commandId = mapping.getCommandId(mapping
103: .getGeneratedCommandId(contributionId, actionId));
104: }
105: // what, still no command?
106: if (commandId == null) {
107: throw new CommandNotMappedException("Action " + actionId //$NON-NLS-1$
108: + " in contribution " + contributionId //$NON-NLS-1$
109: + " not mapped to a command"); //$NON-NLS-1$
110: }
111:
112: init(locator, commandId, null);
113:
114: if (locator instanceof IWorkbenchPartSite) {
115: updateSiteAssociations((IWorkbenchPartSite) locator,
116: commandId, actionId, element);
117: }
118:
119: setId(actionId);
120: }
121:
122: private void updateSiteAssociations(IWorkbenchPartSite site,
123: String commandId, String actionId,
124: IConfigurationElement element) {
125: IWorkbench workbench = (IWorkbench) site
126: .getService(IWorkbench.class);
127: IWorkbenchWindow window = (IWorkbenchWindow) site
128: .getService(IWorkbenchWindow.class);
129: IHandlerService serv = (IHandlerService) workbench
130: .getService(IHandlerService.class);
131: appContext = new EvaluationContext(serv.getCurrentState(),
132: Collections.EMPTY_LIST);
133:
134: // set up the appContext as we would want it.
135: appContext.addVariable(ISources.ACTIVE_CURRENT_SELECTION_NAME,
136: StructuredSelection.EMPTY);
137: appContext.addVariable(ISources.ACTIVE_PART_NAME, site
138: .getPart());
139: appContext.addVariable(ISources.ACTIVE_PART_ID_NAME, site
140: .getId());
141: appContext.addVariable(ISources.ACTIVE_SITE_NAME, site);
142: if (site instanceof IEditorSite) {
143: appContext.addVariable(ISources.ACTIVE_EDITOR_NAME, site
144: .getPart());
145: appContext.addVariable(ISources.ACTIVE_EDITOR_ID_NAME, site
146: .getId());
147: }
148: appContext.addVariable(ISources.ACTIVE_WORKBENCH_WINDOW_NAME,
149: window);
150: appContext.addVariable(
151: ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME, window
152: .getShell());
153:
154: HandlerService realService = (HandlerService) serv;
155: partHandler = realService.findHandler(commandId, appContext);
156: if (partHandler == null) {
157: localHandler = true;
158: // if we can't find the handler, then at least we can
159: // call the action delegate run method
160: partHandler = new ActionDelegateHandlerProxy(element,
161: IWorkbenchRegistryConstants.ATT_CLASS, actionId,
162: getParameterizedCommand(), site
163: .getWorkbenchWindow(), null, null, null);
164: }
165:
166: if (getParameterizedCommand() != null) {
167: getParameterizedCommand().getCommand()
168: .removeCommandListener(getCommandListener());
169: }
170: site.getPage().addPartListener(getPartListener());
171: }
172:
173: /*
174: * (non-Javadoc)
175: *
176: * @see org.eclipse.ui.internal.actions.CommandAction#runWithEvent(org.eclipse.swt.widgets.Event)
177: */
178: public void runWithEvent(Event event) {
179: if (partHandler != null) {
180: IHandler oldHandler = getParameterizedCommand()
181: .getCommand().getHandler();
182: try {
183: getParameterizedCommand().getCommand().setHandler(
184: partHandler);
185: getParameterizedCommand().executeWithChecks(event,
186: appContext);
187: } catch (ExecutionException e) {
188: // TODO some logging, perhaps?
189: } catch (NotDefinedException e) {
190: // TODO some logging, perhaps?
191: } catch (NotEnabledException e) {
192: // TODO some logging, perhaps?
193: } catch (NotHandledException e) {
194: // TODO some logging, perhaps?
195: } finally {
196: getParameterizedCommand().getCommand().setHandler(
197: oldHandler);
198: }
199: } else {
200: super .runWithEvent(event);
201: }
202: }
203:
204: /*
205: * (non-Javadoc)
206: *
207: * @see org.eclipse.jface.action.Action#isEnabled()
208: */
209: public boolean isEnabled() {
210: if (partHandler != null) {
211: if (partHandler instanceof ActionDelegateHandlerProxy) {
212: return ((ActionDelegateHandlerProxy) partHandler)
213: .isEnabled(appContext);
214: }
215: return partHandler.isEnabled();
216: }
217: return false;
218: }
219:
220: private IPartListener getPartListener() {
221: if (partListener == null) {
222: final IWorkbenchPartSite site = (IWorkbenchPartSite) appContext
223: .getVariable(ISources.ACTIVE_SITE_NAME);
224:
225: final IWorkbenchPart currentPart;
226: if (site instanceof MultiPageEditorSite) {
227: currentPart = ((MultiPageEditorSite) site)
228: .getMultiPageEditor();
229: } else {
230: currentPart = site.getPart();
231: }
232:
233: partListener = new IPartListener() {
234: public void partActivated(IWorkbenchPart part) {
235: }
236:
237: public void partBroughtToTop(IWorkbenchPart part) {
238: }
239:
240: public void partClosed(IWorkbenchPart part) {
241: if (part == currentPart) {
242: ContributedAction.this .disposeAction();
243: }
244: }
245:
246: public void partDeactivated(IWorkbenchPart part) {
247: }
248:
249: public void partOpened(IWorkbenchPart part) {
250: }
251: };
252: }
253: return partListener;
254: }
255:
256: // TODO make public in 3.4
257: private void disposeAction() {
258: if (appContext != null) {
259: if (localHandler) {
260: partHandler.dispose();
261: }
262: if (partListener != null) {
263: IWorkbenchPartSite site = (IWorkbenchPartSite) appContext
264: .getVariable(ISources.ACTIVE_SITE_NAME);
265: site.getPage().removePartListener(partListener);
266: partListener = null;
267: }
268: appContext = null;
269: partHandler = null;
270: }
271: dispose();
272: }
273: }
|