blob: 8fb2badcbc4c5755c4e72642dbf19c1171e61c15 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 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
*******************************************************************************/
package org.eclipse.ui.internal.contexts;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import javax.inject.Inject;
import org.eclipse.core.commands.contexts.Context;
import org.eclipse.core.commands.contexts.ContextManager;
import org.eclipse.core.commands.contexts.IContextManagerListener;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.e4.ui.services.EContextService;
import org.eclipse.e4.ui.workbench.modeling.ExpressionContext;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ISourceProvider;
import org.eclipse.ui.ISources;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.internal.WorkbenchPlugin;
/**
* <p>
* Provides services related to contexts in the Eclipse workbench. This provides
* access to contexts.
* </p>
*
* @since 3.1
*/
public final class ContextService implements IContextService {
private HashMap<IContextActivation, UpdateExpression> activationToRat = new HashMap<IContextActivation, ContextService.UpdateExpression>();
/**
* The central authority for determining which context we should use.
*/
private final ContextAuthority contextAuthority;
/**
* The context manager that supports this service. This value is never
* <code>null</code>.
*/
private ContextManager contextManager;
@Inject
private EContextService contextService;
@Inject
private IEclipseContext eclipseContext;
@Inject
private UISynchronize synchService;
/**
* The persistence class for this context service.
*/
private final ContextPersistence contextPersistence;
/**
* Constructs a new instance of <code>ContextService</code> using a
* context manager.
*
* @param contextManager
* The context manager to use; must not be <code>null</code>.
*/
@Inject
public ContextService(final ContextManager contextManager) {
if (contextManager == null) {
throw new NullPointerException(
"Cannot create a context service with a null manager"); //$NON-NLS-1$
}
this.contextManager = contextManager;
this.contextAuthority = new ContextAuthority(contextManager, this);
this.contextPersistence = new ContextPersistence(contextManager);
}
/* (non-Javadoc)
* @see org.eclipse.ui.contexts.IContextService#deferUpdates(boolean)
*/
public void deferUpdates(boolean defer) {
contextManager.deferUpdates(defer);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#activateContext(java.lang.String)
*/
public final IContextActivation activateContext(final String contextId) {
return activateContext(contextId, null);
}
private class UpdateExpression extends RunAndTrack {
boolean updating = true;
private String contextId;
private Expression expression;
public UpdateExpression(String contextId, Expression expression) {
this.contextId = contextId;
this.expression = expression;
}
@Override
public boolean changed(IEclipseContext context) {
if (!updating) {
return false;
}
ExpressionContext ctx = new ExpressionContext(eclipseContext.getActiveLeaf());
try {
if (updating) {
if (expression.evaluate(ctx) != EvaluationResult.FALSE) {
runExternalCode(new Runnable() {
public void run() {
contextService.activateContext(contextId);
}
});
} else {
runExternalCode(new Runnable() {
public void run() {
contextService.deactivateContext(contextId);
}
});
}
}
} catch (CoreException e) {
// contextService.deactivateContext(contextId);
WorkbenchPlugin.log("Failed to update " + contextId, e); //$NON-NLS-1$
}
return updating;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#activateContext(java.lang.String,
* org.eclipse.core.expressions.Expression)
*/
public final IContextActivation activateContext(final String contextId,
final Expression expression) {
final IContextActivation activation = new ContextActivation(contextId,
expression, this);
contextAuthority.activateContext(activation);
if (expression == null) {
contextService.activateContext(contextId);
} else {
final UpdateExpression runnable = new UpdateExpression(contextId, expression);
activationToRat.put(activation, runnable);
eclipseContext.runAndTrack(runnable);
}
return activation;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#activateContext(java.lang.String,
* org.eclipse.core.expressions.Expression, boolean)
*/
public IContextActivation activateContext(String contextId,
Expression expression, boolean global) {
return activateContext(contextId, expression);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#activateContext(java.lang.String,
* org.eclipse.core.expressions.Expression, int)
*/
public final IContextActivation activateContext(final String contextId,
final Expression expression, final int sourcePriority) {
return activateContext(contextId, expression);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#addContextManagerListener(org.eclipse.core.commands.contexts.IContextManagerListener)
*/
public final void addContextManagerListener(
final IContextManagerListener listener) {
contextManager.addContextManagerListener(listener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.services.IServiceWithSources#addSourceProvider(org.eclipse.ui.ISourceProvider)
*/
public final void addSourceProvider(final ISourceProvider provider) {
contextAuthority.addSourceProvider(provider);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#deactivateContext(org.eclipse.ui.contexts.IContextActivation)
*/
public final void deactivateContext(final IContextActivation activation) {
if (activation != null && activation.getContextService() == this) {
final UpdateExpression rat = activationToRat.remove(activation);
if (rat != null) {
rat.updating = false;
}
contextService.deactivateContext(activation.getContextId());
contextAuthority.deactivateContext(activation);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#deactivateContexts(java.util.Collection)
*/
public final void deactivateContexts(final Collection activations) {
final Iterator activationItr = activations.iterator();
while (activationItr.hasNext()) {
final IContextActivation activation = (IContextActivation) activationItr
.next();
deactivateContext(activation);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.services.IDisposable#dispose()
*/
public final void dispose() {
contextPersistence.dispose();
contextAuthority.dispose();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#getActiveContextIds()
*/
public final Collection getActiveContextIds() {
return contextService.getActiveContextIds();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#getContext(java.lang.String)
*/
public final Context getContext(final String contextId) {
return contextService.getContext(contextId);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#getDefinedContextIds()
*/
public final Collection getDefinedContextIds() {
return contextManager.getDefinedContextIds();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#getDefinedContexts()
*/
public final Context[] getDefinedContexts() {
return contextManager.getDefinedContexts();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#getShellType(org.eclipse.swt.widgets.Shell)
*/
public final int getShellType(final Shell shell) {
return contextAuthority.getShellType(shell);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#readRegistry()
*/
public final void readRegistry() {
// contextPersistence.read();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#registerShell(org.eclipse.swt.widgets.Shell,
* int)
*/
public final boolean registerShell(final Shell shell, final int type) {
return contextAuthority.registerShell(shell, type);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#removeContextManagerListener(org.eclipse.core.commands.contexts.IContextManagerListener)
*/
public final void removeContextManagerListener(
final IContextManagerListener listener) {
contextManager.removeContextManagerListener(listener);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.services.IServiceWithSources#removeSourceProvider(org.eclipse.ui.ISourceProvider)
*/
public final void removeSourceProvider(final ISourceProvider provider) {
contextAuthority.removeSourceProvider(provider);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.contexts.IContextService#unregisterShell(org.eclipse.swt.widgets.Shell)
*/
public final boolean unregisterShell(final Shell shell) {
return contextAuthority.unregisterShell(shell);
}
/**
* <p>
* Bug 95792. A mechanism by which the key binding architecture can force an
* update of the contexts (based on the active shell) before trying to
* execute a command. This mechanism is required for GTK+ only.
* </p>
* <p>
* DO NOT CALL THIS METHOD.
* </p>
*/
public final void updateShellKludge() {
contextAuthority.updateShellKludge();
}
/**
* <p>
* Bug 95792. A mechanism by which the key binding architecture can force an
* update of the contexts (based on the active shell) before trying to
* execute a command. This mechanism is required for GTK+ only.
* </p>
* <p>
* DO NOT CALL THIS METHOD.
* </p>
*
* @param shell
* The shell that should be considered active; must not be
* <code>null</code>.
*/
public final void updateShellKludge(final Shell shell) {
final Shell currentActiveShell = contextAuthority.getActiveShell();
if (currentActiveShell != shell) {
contextAuthority.sourceChanged(ISources.ACTIVE_SHELL,
ISources.ACTIVE_SHELL_NAME, shell);
}
}
}