001: /*******************************************************************************
002: * Copyright (c) 2005, 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.internal.handlers;
011:
012: import java.util.Collection;
013: import java.util.Collections;
014: import java.util.Iterator;
015:
016: import org.eclipse.core.commands.Command;
017: import org.eclipse.core.commands.ExecutionEvent;
018: import org.eclipse.core.commands.ExecutionException;
019: import org.eclipse.core.commands.IHandler;
020: import org.eclipse.core.commands.NotEnabledException;
021: import org.eclipse.core.commands.NotHandledException;
022: import org.eclipse.core.commands.ParameterizedCommand;
023: import org.eclipse.core.commands.common.NotDefinedException;
024: import org.eclipse.core.expressions.Expression;
025: import org.eclipse.core.expressions.IEvaluationContext;
026: import org.eclipse.swt.widgets.Event;
027: import org.eclipse.swt.widgets.Shell;
028: import org.eclipse.ui.ISourceProvider;
029: import org.eclipse.ui.ISources;
030: import org.eclipse.ui.commands.ICommandService;
031: import org.eclipse.ui.handlers.IHandlerActivation;
032: import org.eclipse.ui.handlers.IHandlerService;
033: import org.eclipse.ui.internal.misc.Policy;
034: import org.eclipse.ui.internal.services.IEvaluationService;
035:
036: /**
037: * <p>
038: * Provides services related to activating and deactivating handlers within the
039: * workbench.
040: * </p>
041: *
042: * @since 3.1
043: */
044: public final class HandlerService implements IHandlerService {
045:
046: static {
047: Command.DEBUG_HANDLERS = Policy.DEBUG_HANDLERS_VERBOSE;
048: Command.DEBUG_HANDLERS_COMMAND_ID = Policy.DEBUG_HANDLERS_VERBOSE_COMMAND_ID;
049: }
050:
051: /**
052: * The command service for this handler service. This value is never
053: * <code>null</code>.
054: */
055: private final ICommandService commandService;
056:
057: /**
058: * The central authority for determining which handler we should use.
059: */
060: private final HandlerAuthority handlerAuthority;
061:
062: /**
063: * The class providing persistence for this service.
064: */
065: private final HandlerPersistence handlerPersistence;
066:
067: /**
068: * Constructs a new instance of <code>CommandService</code> using a
069: * command manager.
070: *
071: * @param commandService
072: * The command service to use; must not be <code>null</code>.
073: * @param evaluationService
074: * The evaluation service to use; must not be <code>null</code>.
075: */
076: public HandlerService(final ICommandService commandService,
077: final IEvaluationService evaluationService) {
078: if (commandService == null) {
079: throw new NullPointerException(
080: "A handler service requires a command service"); //$NON-NLS-1$
081: }
082: this .commandService = commandService;
083: this .handlerAuthority = new HandlerAuthority(commandService);
084: this .handlerPersistence = new HandlerPersistence(this ,
085: evaluationService);
086: }
087:
088: public final IHandlerActivation activateHandler(
089: final IHandlerActivation childActivation) {
090: final String commandId = childActivation.getCommandId();
091: final IHandler handler = childActivation.getHandler();
092: final Expression expression = childActivation.getExpression();
093: final int depth = childActivation.getDepth() + 1;
094: final IHandlerActivation localActivation = new HandlerActivation(
095: commandId, handler, expression, depth, this );
096: handlerAuthority.activateHandler(localActivation);
097: return localActivation;
098: }
099:
100: public final IHandlerActivation activateHandler(
101: final String commandId, final IHandler handler) {
102: return activateHandler(commandId, handler, null);
103: }
104:
105: public final IHandlerActivation activateHandler(
106: final String commandId, final IHandler handler,
107: final Expression expression) {
108: return activateHandler(commandId, handler, expression, false);
109: }
110:
111: public final IHandlerActivation activateHandler(
112: final String commandId, final IHandler handler,
113: final Expression expression, final boolean global) {
114: final IHandlerActivation activation = new HandlerActivation(
115: commandId, handler, expression,
116: IHandlerActivation.ROOT_DEPTH, this );
117: handlerAuthority.activateHandler(activation);
118: return activation;
119: }
120:
121: public final IHandlerActivation activateHandler(
122: final String commandId, final IHandler handler,
123: final Expression expression, final int sourcePriority) {
124: return activateHandler(commandId, handler, expression);
125: }
126:
127: public final void addSourceProvider(final ISourceProvider provider) {
128: handlerAuthority.addSourceProvider(provider);
129: }
130:
131: public final ExecutionEvent createExecutionEvent(
132: final Command command, final Event event) {
133: return new ExecutionEvent(command, Collections.EMPTY_MAP,
134: event, getCurrentState());
135: }
136:
137: public ExecutionEvent createExecutionEvent(
138: final ParameterizedCommand command, final Event event) {
139: return new ExecutionEvent(command.getCommand(), command
140: .getParameterMap(), event, getCurrentState());
141: }
142:
143: public final void deactivateHandler(
144: final IHandlerActivation activation) {
145: if (activation.getHandlerService() == this ) {
146: handlerAuthority.deactivateHandler(activation);
147: }
148: }
149:
150: public final void deactivateHandlers(final Collection activations) {
151: final Iterator activationItr = activations.iterator();
152: while (activationItr.hasNext()) {
153: final IHandlerActivation activation = (IHandlerActivation) activationItr
154: .next();
155: deactivateHandler(activation);
156: }
157: }
158:
159: public final void dispose() {
160: handlerAuthority.dispose();
161: handlerPersistence.dispose();
162: }
163:
164: public final Object executeCommand(
165: final ParameterizedCommand command, final Event trigger)
166: throws ExecutionException, NotDefinedException,
167: NotEnabledException, NotHandledException {
168: return command.executeWithChecks(trigger, getCurrentState());
169: }
170:
171: public final Object executeCommand(final String commandId,
172: final Event trigger) throws ExecutionException,
173: NotDefinedException, NotEnabledException,
174: NotHandledException {
175: final Command command = commandService.getCommand(commandId);
176: final ExecutionEvent event = new ExecutionEvent(command,
177: Collections.EMPTY_MAP, trigger, getCurrentState());
178: return command.executeWithChecks(event);
179: }
180:
181: public final IEvaluationContext getCurrentState() {
182: return handlerAuthority.getCurrentState();
183: }
184:
185: public final void readRegistry() {
186: handlerPersistence.read();
187: }
188:
189: public final void removeSourceProvider(
190: final ISourceProvider provider) {
191: handlerAuthority.removeSourceProvider(provider);
192: }
193:
194: public final void setHelpContextId(final IHandler handler,
195: final String helpContextId) {
196: commandService.setHelpContextId(handler, helpContextId);
197: }
198:
199: /**
200: * <p>
201: * Bug 95792. A mechanism by which the key binding architecture can force an
202: * update of the handlers (based on the active shell) before trying to
203: * execute a command. This mechanism is required for GTK+ only.
204: * </p>
205: * <p>
206: * DO NOT CALL THIS METHOD.
207: * </p>
208: */
209: public final void updateShellKludge() {
210: handlerAuthority.updateShellKludge();
211: }
212:
213: /**
214: * <p>
215: * Bug 95792. A mechanism by which the key binding architecture can force an
216: * update of the handlers (based on the active shell) before trying to
217: * execute a command. This mechanism is required for GTK+ only.
218: * </p>
219: * <p>
220: * DO NOT CALL THIS METHOD.
221: * </p>
222: *
223: * @param shell
224: * The shell that should be considered active; must not be
225: * <code>null</code>.
226: */
227: public final void updateShellKludge(final Shell shell) {
228: final Shell currentActiveShell = handlerAuthority
229: .getActiveShell();
230: if (currentActiveShell != shell) {
231: handlerAuthority.sourceChanged(ISources.ACTIVE_SHELL,
232: ISources.ACTIVE_SHELL_NAME, shell);
233: }
234: }
235:
236: /**
237: * Currently this is a an internal method to help locate a handler.
238: * <p>
239: * DO NOT CALL THIS METHOD.
240: * </p>
241: *
242: * @param commandId
243: * the command id to check
244: * @param context
245: * the context to use for activations
246: * @since 3.3
247: */
248: public final IHandler findHandler(String commandId,
249: IEvaluationContext context) {
250: return handlerAuthority.findHandler(commandId, context);
251: }
252:
253: /**
254: * Normally the context returned from getCurrentState() still tracks the
255: * application state. This method creates a copy and fills it in with the
256: * variables that we know about. Currently it does not fill in the active
257: * selection.
258: * <p>
259: * DO NOT CALL THIS METHOD. It is experimental in 3.3.
260: * </p>
261: *
262: * @return an evaluation context with no parent.
263: * @since 3.3
264: */
265: public final IEvaluationContext getContextSnapshot() {
266: return handlerAuthority.getContextSnapshot();
267: }
268:
269: /**
270: * Normally the context returned from getCurrentState() still tracks the
271: * application state. This method creates a copy and fills it in with all the
272: * variables that we know about.
273: * <p>
274: * DO NOT CALL THIS METHOD. It is experimental in 3.3.
275: * </p>
276: *
277: * @return an evaluation context with no parent.
278: * @since 3.3
279: */
280: public final IEvaluationContext getFullContextSnapshot() {
281: return handlerAuthority.getFullContextSnapshot();
282: }
283:
284: /**
285: * Execute the command using the provided context. It takes care of finding
286: * the correct active handler given the context, and executes with that
287: * handler.
288: * <p>
289: * It currently cannot effect the enablement of the handler.
290: * </p>
291: * <p>
292: * DO NOT CALL THIS METHOD. It is experimental in 3.3.
293: * </p>
294: *
295: * @param command
296: * the parameterized command to execute
297: * @param trigger
298: * the SWT event trigger ... can be null
299: * @param context
300: * the evaluation context to run against.
301: * @return
302: * @throws ExecutionException
303: * @throws NotDefinedException
304: * @throws NotEnabledException
305: * @throws NotHandledException
306: * @since 3.3
307: * @see #getContextSnapshot()
308: */
309: public final Object executeCommandInContext(
310: final ParameterizedCommand command, final Event trigger,
311: IEvaluationContext context) throws ExecutionException,
312: NotDefinedException, NotEnabledException,
313: NotHandledException {
314: IHandler oldHandler = command.getCommand().getHandler();
315:
316: IHandler handler = findHandler(command.getId(), context);
317: boolean enabled = true;
318: if (handler instanceof HandlerProxy) {
319: enabled = ((HandlerProxy) handler).getProxyEnabled();
320: }
321:
322: try {
323: command.getCommand().setHandler(handler);
324: if (handler instanceof HandlerProxy) {
325: ((HandlerProxy) handler).setEnabledFor(context);
326: }
327:
328: return command.executeWithChecks(trigger, context);
329: } finally {
330: if (handler instanceof HandlerProxy) {
331: ((HandlerProxy) handler).setProxyEnabled(enabled);
332: }
333: command.getCommand().setHandler(oldHandler);
334: }
335: }
336: }
|