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.io.BufferedWriter;
013: import java.io.IOException;
014: import java.io.StringWriter;
015: import java.util.Collection;
016: import java.util.Collections;
017: import java.util.HashMap;
018: import java.util.HashSet;
019: import java.util.Iterator;
020: import java.util.Map;
021: import java.util.Set;
022: import java.util.SortedSet;
023: import java.util.TreeSet;
024:
025: import org.eclipse.core.commands.Command;
026: import org.eclipse.core.commands.IHandler;
027: import org.eclipse.core.commands.util.Tracing;
028: import org.eclipse.core.expressions.EvaluationContext;
029: import org.eclipse.core.expressions.EvaluationResult;
030: import org.eclipse.core.expressions.Expression;
031: import org.eclipse.core.expressions.IEvaluationContext;
032: import org.eclipse.core.runtime.CoreException;
033: import org.eclipse.core.runtime.IStatus;
034: import org.eclipse.core.runtime.MultiStatus;
035: import org.eclipse.core.runtime.Status;
036: import org.eclipse.swt.widgets.Shell;
037: import org.eclipse.ui.ISources;
038: import org.eclipse.ui.commands.ICommandService;
039: import org.eclipse.ui.handlers.IHandlerActivation;
040: import org.eclipse.ui.internal.WorkbenchPlugin;
041: import org.eclipse.ui.internal.misc.Policy;
042: import org.eclipse.ui.internal.services.EvaluationResultCacheComparator;
043: import org.eclipse.ui.internal.services.ExpressionAuthority;
044:
045: /**
046: * <p>
047: * A central authority for resolving conflicts between handlers. This authority
048: * listens to a variety of incoming sources, and updates the underlying commands
049: * if changes in the active handlers occur.
050: * </p>
051: * <p>
052: * This authority encapsulates all of the handler conflict resolution mechanisms
053: * for the workbench. A conflict occurs if two or more handlers are assigned to
054: * the same command identifier. To resolve this conflict, the authority
055: * considers which source the handler came from.
056: * </p>
057: *
058: * @since 3.1
059: */
060: final class HandlerAuthority extends ExpressionAuthority {
061:
062: /**
063: * The default size of the set containing the activations to recompute. This
064: * is more than enough to cover the average case.
065: */
066: private static final int ACTIVATIONS_BY_SOURCE_SIZE = 256;
067:
068: /**
069: * The default size of the set containing the activations to recompute. This
070: * is more than enough to cover the average case.
071: */
072: private static final int ACTIVATIONS_TO_RECOMPUTE_SIZE = 1024;
073:
074: /**
075: * Whether the workbench command support should kick into debugging mode.
076: * This causes the unresolvable handler conflicts to be printed to the
077: * console.
078: */
079: private static final boolean DEBUG = Policy.DEBUG_HANDLERS;
080:
081: /**
082: * Whether the performance information should be printed about the
083: * performance of the handler authority.
084: */
085: private static final boolean DEBUG_PERFORMANCE = Policy.DEBUG_HANDLERS_PERFORMANCE;
086:
087: /**
088: * Whether the workbench command support should kick into verbose debugging
089: * mode. This causes the resolvable handler conflicts to be printed to the
090: * console.
091: */
092: private static final boolean DEBUG_VERBOSE = Policy.DEBUG_HANDLERS
093: && Policy.DEBUG_HANDLERS_VERBOSE;
094:
095: /**
096: * The command identifier to which the verbose output should be restricted.
097: */
098: private static final String DEBUG_VERBOSE_COMMAND_ID = Policy.DEBUG_HANDLERS_VERBOSE_COMMAND_ID;
099:
100: /**
101: * The component name to print when displaying tracing information.
102: */
103: private static final String TRACING_COMPONENT = "HANDLERS"; //$NON-NLS-1$
104:
105: /**
106: * A bucket sort of the handler activations based on source priority of its
107: * expression. Each expression will appear only once per set, but may appear
108: * in multiple sets. If no activations are defined for a particular priority
109: * level, then the array at that index will only contain <code>null</code>.
110: * This is an array of {@link Map}, where the maps contain instances of
111: * {@link Collection} containing instances of {@link IHandlerActivation}
112: * indexed by instances of {@link Expression}.
113: */
114: private final Map[] activationsByExpressionBySourcePriority = new Map[33];
115:
116: /**
117: * The command service that should be updated when the handlers are
118: * changing. This value is never <code>null</code>.
119: */
120: private final ICommandService commandService;
121:
122: /**
123: * This is a map of handler activations (<code>SortedSet</code> of
124: * <code>IHandlerActivation</code>) sorted by command identifier (<code>String</code>).
125: * If there is only one handler activation for a command, then the
126: * <code>SortedSet</code> is replaced by a <code>IHandlerActivation</code>.
127: * If there is no activation, the entry should be removed entirely.
128: */
129: private final Map handlerActivationsByCommandId = new HashMap();
130:
131: private Set previousLogs = new HashSet();
132:
133: /**
134: * Constructs a new instance of <code>HandlerAuthority</code>.
135: *
136: * @param commandService
137: * The command service from which commands can be retrieved (to
138: * update their handlers); must not be <code>null</code>.
139: */
140: HandlerAuthority(final ICommandService commandService) {
141: if (commandService == null) {
142: throw new NullPointerException(
143: "The handler authority needs a command service"); //$NON-NLS-1$
144: }
145:
146: this .commandService = commandService;
147: }
148:
149: /**
150: * Activates a handler on the workbench. This will add it to a master list.
151: * If conflicts exist, they will be resolved based on the source priority.
152: * If conflicts still exist, then no handler becomes active.
153: *
154: * @param activation
155: * The activation; must not be <code>null</code>.
156: */
157: final void activateHandler(final IHandlerActivation activation) {
158: // First we update the handlerActivationsByCommandId map.
159: final String commandId = activation.getCommandId();
160: MultiStatus conflicts = new MultiStatus(
161: "org.eclipse.ui.workbench", 0, //$NON-NLS-1$
162: "A handler conflict occurred. This may disable some commands.", //$NON-NLS-1$
163: null);
164: final Object value = handlerActivationsByCommandId
165: .get(commandId);
166: if (value instanceof SortedSet) {
167: final SortedSet handlerActivations = (SortedSet) value;
168: if (!handlerActivations.contains(activation)) {
169: handlerActivations.add(activation);
170: updateCommand(commandId, resolveConflicts(commandId,
171: handlerActivations, conflicts));
172: }
173: } else if (value instanceof IHandlerActivation) {
174: if (value != activation) {
175: final SortedSet handlerActivations = new TreeSet(
176: new EvaluationResultCacheComparator());
177: handlerActivations.add(value);
178: handlerActivations.add(activation);
179: handlerActivationsByCommandId.put(commandId,
180: handlerActivations);
181: updateCommand(commandId, resolveConflicts(commandId,
182: handlerActivations, conflicts));
183: }
184: } else {
185: handlerActivationsByCommandId.put(commandId, activation);
186: updateCommand(commandId, (evaluate(activation) ? activation
187: : null));
188: }
189:
190: if (conflicts.getSeverity() != IStatus.OK) {
191: WorkbenchPlugin.log(conflicts);
192: }
193:
194: // Next we update the source priority bucket sort of activations.
195: final int sourcePriority = activation.getSourcePriority();
196: for (int i = 1; i <= 32; i++) {
197: if ((sourcePriority & (1 << i)) != 0) {
198: Map activationsByExpression = activationsByExpressionBySourcePriority[i];
199: if (activationsByExpression == null) {
200: activationsByExpression = new HashMap(
201: ACTIVATIONS_BY_SOURCE_SIZE);
202: activationsByExpressionBySourcePriority[i] = activationsByExpression;
203: }
204:
205: final Expression expression = activation
206: .getExpression();
207: Collection activations = (Collection) activationsByExpression
208: .get(expression);
209: if (activations == null) {
210: activations = new HashSet();
211: activationsByExpression
212: .put(expression, activations);
213: }
214: activations.add(activation);
215: }
216: }
217: }
218:
219: /**
220: * Removes an activation for a handler on the workbench. This will remove it
221: * from the master list, and update the appropriate command, if necessary.
222: *
223: * @param activation
224: * The activation; must not be <code>null</code>.
225: */
226: final void deactivateHandler(final IHandlerActivation activation) {
227: // First we update the handlerActivationsByCommandId map.
228: final String commandId = activation.getCommandId();
229: MultiStatus conflicts = new MultiStatus(
230: "org.eclipse.ui.workbench", 0, //$NON-NLS-1$
231: "A handler conflict occurred. This may disable some commands.", //$NON-NLS-1$
232: null);
233: final Object value = handlerActivationsByCommandId
234: .get(commandId);
235: if (value instanceof SortedSet) {
236: final SortedSet handlerActivations = (SortedSet) value;
237: if (handlerActivations.contains(activation)) {
238: handlerActivations.remove(activation);
239: if (handlerActivations.isEmpty()) {
240: handlerActivationsByCommandId.remove(commandId);
241: updateCommand(commandId, null);
242:
243: } else if (handlerActivations.size() == 1) {
244: final IHandlerActivation remainingActivation = (IHandlerActivation) handlerActivations
245: .iterator().next();
246: handlerActivationsByCommandId.put(commandId,
247: remainingActivation);
248: updateCommand(
249: commandId,
250: (evaluate(remainingActivation) ? remainingActivation
251: : null));
252:
253: } else {
254: updateCommand(commandId, resolveConflicts(
255: commandId, handlerActivations, conflicts));
256: }
257: }
258: } else if (value instanceof IHandlerActivation) {
259: if (value == activation) {
260: handlerActivationsByCommandId.remove(commandId);
261: updateCommand(commandId, null);
262: }
263: }
264: if (conflicts.getSeverity() != IStatus.OK) {
265: WorkbenchPlugin.log(conflicts);
266: }
267:
268: // Next we update the source priority bucket sort of activations.
269: final int sourcePriority = activation.getSourcePriority();
270: for (int i = 1; i <= 32; i++) {
271: if ((sourcePriority & (1 << i)) != 0) {
272: final Map activationsByExpression = activationsByExpressionBySourcePriority[i];
273: if (activationsByExpression == null) {
274: continue;
275: }
276:
277: final Expression expression = activation
278: .getExpression();
279: final Collection activations = (Collection) activationsByExpression
280: .get(expression);
281: activations.remove(activation);
282: if (activations.isEmpty()) {
283: activationsByExpression.remove(expression);
284: }
285:
286: if (activationsByExpression.isEmpty()) {
287: activationsByExpressionBySourcePriority[i] = null;
288: }
289: }
290: }
291: }
292:
293: /**
294: * Returns the currently active shell.
295: *
296: * @return The currently active shell; may be <code>null</code>.
297: */
298: final Shell getActiveShell() {
299: return (Shell) getVariable(ISources.ACTIVE_SHELL_NAME);
300: }
301:
302: /**
303: * Resolves conflicts between multiple handlers for the same command
304: * identifier. This tries to select the best activation based on the source
305: * priority. For the sake of comparison, activations with the same handler
306: * are considered equivalent (i.e., non-conflicting).
307: *
308: * @param commandId
309: * The identifier of the command for which the conflicts should
310: * be detected; must not be <code>null</code>. This is only
311: * used for debugging purposes.
312: * @param activations
313: * All of the possible handler activations for the given command
314: * identifier; must not be <code>null</code>.
315: * @return The best matching handler activation. If none can be found (e.g.,
316: * because of unresolvable conflicts), then this returns
317: * <code>null</code>.
318: */
319: private final IHandlerActivation resolveConflicts(
320: final String commandId, final SortedSet activations,
321: MultiStatus conflicts) {
322: // If we don't have any, then there is no match.
323: if (activations.isEmpty()) {
324: return null;
325: }
326:
327: // Cycle over the activations, remembered the current best.
328: final Iterator activationItr = activations.iterator();
329: IHandlerActivation bestActivation = null;
330: IHandlerActivation currentActivation = null;
331: boolean conflict = false;
332: while (activationItr.hasNext()) {
333: currentActivation = (IHandlerActivation) activationItr
334: .next();
335: if (!evaluate(currentActivation)) {
336: continue; // only consider potentially active handlers
337: }
338:
339: // Check to see if we haven't found a potentially active handler yet
340: if ((DEBUG_VERBOSE)
341: && ((DEBUG_VERBOSE_COMMAND_ID == null) || (DEBUG_VERBOSE_COMMAND_ID
342: .equals(commandId)))) {
343: Tracing
344: .printTrace(
345: TRACING_COMPONENT,
346: " resolveConflicts: eval: " + currentActivation); //$NON-NLS-1$
347: }
348: if (bestActivation == null) {
349: bestActivation = currentActivation;
350: conflict = false;
351: continue;
352: }
353:
354: // Compare the two handlers.
355: final int comparison = bestActivation
356: .compareTo(currentActivation);
357: if (comparison < 0) {
358: bestActivation = currentActivation;
359: conflict = false;
360:
361: } else if (comparison == 0) {
362: if (currentActivation.getHandler() != bestActivation
363: .getHandler()) {
364: conflict = true;
365: break;
366: }
367:
368: } else {
369: break;
370: }
371: }
372:
373: // If we are logging information, now is the time to do it.
374: if (DEBUG) {
375: if (conflict) {
376: Tracing.printTrace(TRACING_COMPONENT,
377: "Unresolved conflict detected for '" //$NON-NLS-1$
378: + commandId + '\'');
379: } else if ((bestActivation != null)
380: && (DEBUG_VERBOSE)
381: && ((DEBUG_VERBOSE_COMMAND_ID == null) || (DEBUG_VERBOSE_COMMAND_ID
382: .equals(commandId)))) {
383: Tracing
384: .printTrace(TRACING_COMPONENT,
385: "Resolved conflict detected. The following activation won: "); //$NON-NLS-1$
386: Tracing.printTrace(TRACING_COMPONENT,
387: " " + bestActivation); //$NON-NLS-1$
388: }
389: }
390:
391: // Return the current best.
392: if (conflict) {
393: if (previousLogs.add(commandId)) {
394: final StringWriter sw = new StringWriter();
395: final BufferedWriter buffer = new BufferedWriter(sw);
396: try {
397: buffer.write("Conflict for \'"); //$NON-NLS-1$
398: buffer.write(commandId);
399: buffer.write("\':"); //$NON-NLS-1$
400: buffer.newLine();
401: buffer.write(bestActivation.toString());
402: buffer.newLine();
403: buffer.write(currentActivation.toString());
404: buffer.flush();
405: } catch (IOException e) {
406: //should never get this.
407: }
408:
409: IStatus s = new Status(IStatus.WARNING,
410: "org.eclipse.ui.workbench", //$NON-NLS-1$
411: sw.toString());
412: conflicts.add(s);
413: }
414: return null;
415: }
416: return bestActivation;
417: }
418:
419: /**
420: * Carries out the actual source change notification. It assumed that by the
421: * time this method is called, <code>context</code> is up-to-date with the
422: * current state of the application.
423: *
424: * @param sourcePriority
425: * A bit mask of all the source priorities that have changed.
426: */
427: protected final void sourceChanged(final int sourcePriority) {
428: // If tracing, then track how long it takes to process the activations.
429: long startTime = 0L;
430: if (DEBUG_PERFORMANCE) {
431: startTime = System.currentTimeMillis();
432: }
433:
434: /*
435: * In this first phase, we cycle through all of the activations that
436: * could have potentially changed. Each such activation is added to a
437: * set for future processing. We add it to a set so that we avoid
438: * handling any individual activation more than once.
439: */
440: final Collection changedCommandIds = new HashSet(
441: ACTIVATIONS_TO_RECOMPUTE_SIZE);
442: for (int i = 1; i <= 32; i++) {
443: if ((sourcePriority & (1 << i)) != 0) {
444: final Map activationsByExpression = activationsByExpressionBySourcePriority[i];
445: if (activationsByExpression != null) {
446: final Iterator activationByExpressionItr = activationsByExpression
447: .values().iterator();
448: while (activationByExpressionItr.hasNext()) {
449: final Collection activations = (Collection) activationByExpressionItr
450: .next();
451: final Iterator activationItr = activations
452: .iterator();
453:
454: // Check the first activation to see if it has changed.
455: if (activationItr.hasNext()) {
456: IHandlerActivation activation = (IHandlerActivation) activationItr
457: .next();
458: final boolean currentActive = evaluate(activation);
459: activation.clearResult();
460: final boolean newActive = evaluate(activation);
461: if (newActive != currentActive) {
462: changedCommandIds.add(activation
463: .getCommandId());
464:
465: // Then add every other activation as well.
466: while (activationItr.hasNext()) {
467: activation = (IHandlerActivation) activationItr
468: .next();
469: activation.setResult(newActive);
470:
471: changedCommandIds.add(activation
472: .getCommandId());
473: }
474: } else {
475: while (activationItr.hasNext()) {
476: activation = (IHandlerActivation) activationItr
477: .next();
478: // if for some reason another activation
479: // doesn't match the new result, update and
480: // mark as changed. It's not as expensive
481: // as it looks :-)
482: if (newActive != evaluate(activation)) {
483: activation.setResult(newActive);
484: changedCommandIds
485: .add(activation
486: .getCommandId());
487: }
488: }
489: }
490: }
491: }
492: }
493: }
494: }
495:
496: MultiStatus conflicts = new MultiStatus(
497: "org.eclipse.ui.workbench", 0, //$NON-NLS-1$
498: "A handler conflict occurred. This may disable some commands.", //$NON-NLS-1$
499: null);
500:
501: /*
502: * For every command identifier with a changed activation, we resolve
503: * conflicts and trigger an update.
504: */
505: final Iterator changedCommandIdItr = changedCommandIds
506: .iterator();
507: while (changedCommandIdItr.hasNext()) {
508: final String commandId = (String) changedCommandIdItr
509: .next();
510: final Object value = handlerActivationsByCommandId
511: .get(commandId);
512: if (value instanceof IHandlerActivation) {
513: final IHandlerActivation activation = (IHandlerActivation) value;
514: updateCommand(commandId,
515: (evaluate(activation) ? activation : null));
516: } else if (value instanceof SortedSet) {
517: final IHandlerActivation activation = resolveConflicts(
518: commandId, (SortedSet) value, conflicts);
519: updateCommand(commandId, activation);
520: } else {
521: updateCommand(commandId, null);
522: }
523: }
524: if (conflicts.getSeverity() != IStatus.OK) {
525: WorkbenchPlugin.log(conflicts);
526: }
527:
528: // If tracing performance, then print the results.
529: if (DEBUG_PERFORMANCE) {
530: final long elapsedTime = System.currentTimeMillis()
531: - startTime;
532: final int size = changedCommandIds.size();
533: if (size > 0) {
534: Tracing
535: .printTrace(
536: TRACING_COMPONENT,
537: size
538: + " command ids changed in " + elapsedTime + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
539: }
540: }
541: }
542:
543: /**
544: * Updates the command with the given handler activation.
545: *
546: * @param commandId
547: * The identifier of the command which should be updated; must
548: * not be <code>null</code>.
549: * @param activation
550: * The activation to use; may be <code>null</code> if the
551: * command should have a <code>null</code> handler.
552: */
553: private final void updateCommand(final String commandId,
554: final IHandlerActivation activation) {
555: final Command command = commandService.getCommand(commandId);
556: if (activation == null) {
557: command.setHandler(null);
558: } else {
559: command.setHandler(activation.getHandler());
560: commandService.refreshElements(commandId, null);
561: }
562: }
563:
564: /**
565: * <p>
566: * Bug 95792. A mechanism by which the key binding architecture can force an
567: * update of the handlers (based on the active shell) before trying to
568: * execute a command. This mechanism is required for GTK+ only.
569: * </p>
570: * <p>
571: * DO NOT CALL THIS METHOD.
572: * </p>
573: */
574: final void updateShellKludge() {
575: updateCurrentState();
576: sourceChanged(ISources.ACTIVE_SHELL);
577: }
578:
579: /**
580: * Currently this is a an internal method to help locate a handler.
581: * <p>
582: * DO NOT CALL THIS METHOD.
583: * </p>
584: *
585: * @param commandId
586: * the command id to check
587: * @param context
588: * the context to use for activations
589: * @since 3.3
590: */
591: public final IHandler findHandler(String commandId,
592: IEvaluationContext context) {
593: Object o = handlerActivationsByCommandId.get(commandId);
594: if (o instanceof IHandlerActivation) {
595: IHandlerActivation activation = (IHandlerActivation) o;
596: try {
597: if (eval(context, activation)) {
598: return activation.getHandler();
599: }
600: } catch (CoreException e) {
601: // the evalution failed
602: }
603: } else if (o instanceof SortedSet) {
604: SortedSet activations = (SortedSet) o;
605: IHandlerActivation lastActivation = null;
606: IHandlerActivation currentActivation = null;
607: Iterator i = activations.iterator();
608: while (i.hasNext() && lastActivation == null) {
609: IHandlerActivation activation = (IHandlerActivation) i
610: .next();
611: try {
612: if (eval(context, activation)) {
613: lastActivation = currentActivation;
614: currentActivation = activation;
615: }
616: } catch (CoreException e) {
617: // OK, this one is out of the running
618: }
619: }
620: if (currentActivation != null) {
621: if (lastActivation == null) {
622: return currentActivation.getHandler();
623: }
624: if (lastActivation.getSourcePriority() != currentActivation
625: .getSourcePriority()) {
626: return lastActivation.getHandler();
627: }
628: }
629: }
630: return null;
631: }
632:
633: /**
634: * Evaluate the expression for the handler and bypass the result cache.
635: * <p>
636: * DO NOT CALL THIS METHOD.
637: * </p>
638: *
639: * @param context
640: * @param activation
641: * @return <code>true</code> if the handler expression can evaluate to
642: * true.
643: * @throws CoreException
644: * @since 3.3
645: */
646: private boolean eval(IEvaluationContext context,
647: IHandlerActivation activation) throws CoreException {
648: Expression expression = activation.getExpression();
649: if (expression == null) {
650: return true;
651: }
652: return expression.evaluate(context) == EvaluationResult.TRUE;
653: }
654:
655: /**
656: * Normally the context returned from getCurrentState() still tracks the
657: * application state. This method creates a copy and fills it in with the
658: * variables that we know about. Currently it does not fill in the active
659: * selection.
660: * <p>
661: * DO NOT CALL THIS METHOD. It is experimental in 3.3.
662: * </p>
663: *
664: * @return an evaluation context with no parent.
665: * @since 3.3
666: */
667: public IEvaluationContext getContextSnapshot() {
668: return fillInContext(false);
669: }
670:
671: /**
672: * Normally the context returned from getCurrentState() still tracks the
673: * application state. This method creates a copy and fills it in with all the
674: * variables that we know about.
675: * <p>
676: * DO NOT CALL THIS METHOD. It is experimental in 3.3.
677: * </p>
678: *
679: * @return an evaluation context with no parent.
680: * @since 3.3
681: */
682: public IEvaluationContext getFullContextSnapshot() {
683: return fillInContext(true);
684: }
685:
686: private IEvaluationContext fillInContext(boolean fullContext) {
687: IEvaluationContext tmpContext = getCurrentState();
688:
689: EvaluationContext context = null;
690: if (fullContext) {
691: context = new EvaluationContext(null, tmpContext
692: .getDefaultVariable());
693: copyVariable(context, tmpContext,
694: ISources.ACTIVE_CURRENT_SELECTION_NAME);
695: copyVariable(context, tmpContext,
696: ISources.ACTIVE_FOCUS_CONTROL_ID_NAME);
697: copyVariable(context, tmpContext,
698: ISources.ACTIVE_FOCUS_CONTROL_NAME);
699: copyVariable(context, tmpContext,
700: ISources.ACTIVE_MENU_EDITOR_INPUT_NAME);
701: copyVariable(context, tmpContext, ISources.ACTIVE_MENU_NAME);
702: copyVariable(context, tmpContext,
703: ISources.ACTIVE_MENU_SELECTION_NAME);
704: } else {
705: context = new EvaluationContext(null,
706: Collections.EMPTY_LIST);
707: }
708:
709: copyVariable(context, tmpContext,
710: ISources.ACTIVE_ACTION_SETS_NAME);
711: copyVariable(context, tmpContext, ISources.ACTIVE_CONTEXT_NAME);
712: copyVariable(context, tmpContext,
713: ISources.ACTIVE_EDITOR_ID_NAME);
714: copyVariable(context, tmpContext, ISources.ACTIVE_EDITOR_NAME);
715: copyVariable(context, tmpContext, ISources.ACTIVE_PART_ID_NAME);
716: copyVariable(context, tmpContext, ISources.ACTIVE_PART_NAME);
717: copyVariable(context, tmpContext, ISources.ACTIVE_SITE_NAME);
718: copyVariable(
719: context,
720: tmpContext,
721: ISources.ACTIVE_WORKBENCH_WINDOW_IS_COOLBAR_VISIBLE_NAME);
722: copyVariable(
723: context,
724: tmpContext,
725: ISources.ACTIVE_WORKBENCH_WINDOW_IS_PERSPECTIVEBAR_VISIBLE_NAME);
726: copyVariable(context, tmpContext,
727: ISources.ACTIVE_WORKBENCH_WINDOW_NAME);
728: copyVariable(context, tmpContext,
729: ISources.ACTIVE_WORKBENCH_WINDOW_SHELL_NAME);
730: copyVariable(context, tmpContext, ISources.ACTIVE_SHELL_NAME);
731:
732: return context;
733: }
734:
735: private void copyVariable(IEvaluationContext context,
736: IEvaluationContext tmpContext, String var) {
737: Object o = tmpContext.getVariable(var);
738: if (o != null) {
739: context.addVariable(var, o);
740: }
741: }
742: }
|