There are some constants defined in <code>org.eclipse.e4.ui.services.IServiceConstants</code> that are available for consumption. The most commonly used ones will probably be <code>SELECTION</code>, <code>ACTIVE_PART</code> and <code>ACTIVE_SHELL</code>. Though <code>ACTIVE_SHELL</code> will likely be preceded by <code>IShellProvider</code>. To use a constant, you would need the <code>@Named</code> annotation.

+

There are some constants defined in <code>org.eclipse.e4.ui.services.IServiceConstants</code> that are available for consumption. The most commonly used ones will probably be <code>ACTIVE_SELECTION</code>, <code>ACTIVE_PART</code> and <code>ACTIVE_SHELL</code>. Though <code>ACTIVE_SHELL</code> will likely be preceded by <code>IShellProvider</code>. To use a constant, you would need the <code>@Named</code> annotation.

Summary

The IEclipseContext is used to provide common services to the application. It is not intended for the developer to use the IEclipseContext directly but to use @Inject annotations to receive the necessary services into the Java class. This page describes the usage of service injection.

Problems with the existing Eclipse 3.x architecture

The following are some problems present in Eclipse 3.x that should be address by the IEclipseContext and dependency injection.

This tightly couples consumers of "things" to their producer/provider, inhibits reuse, etc

Mechanisms are not very dynamic - react to context changes drastically rather than incrementally (just close the affected controls)

IEvaluationContext has global state that gets swapped according to context change (such as the focus control)

Current solutions are not multi-threadable - they assume evaluation occurs in the UI thread

Scaling granularity

Current solutions don't scale down to services with brief lifetimes

Current solutions may not scale up to very large numbers of services

There are too many parallel trees that mimic each other (widget tree, service locator tree, etc)

Currently don't track service consumers - to notify when services come/go

Client code needs to know the internas of the Eclipse code base

No support forservices lookup that are composed out of other services on the fly

Available Services in Eclipse 4

The Eclipse context stores the available services and provides OSGi service lookup. As it is not possible to ask the Eclipse context for available keys and because it is the hope that clients do not directly call methods on the context, it is important for clients to be able to know what they can actually inject.

Model

Model objects that are themselves MContext instances will be included in their own context.

For example, MWindows and MParts are MContexts, so you can query their context for the model object.

...which allows your code to be reused by other MDirtyable implementations that might not actually be MParts. This leads into an interesting point, which is that a model interface's superinterfaces are also added into the context. In the following code...

Services

Essentially, anything starting with E*Service should be retrievable from the context, some examples are:

org.eclipse.e4.core.commands.ECommandService

org.eclipse.e4.core.commands.EHandlerService

org.eclipse.e4.workbench.modeling.EPartService

org.eclipse.e4.workbench.modeling.EModelService

org.eclipse.e4.workbench.modeling.ESelectionService

org.eclipse.e4.ui.bindings.EBindingService

org.eclipse.e4.ui.services.EContextService

There are also some other things in there such as, but not limited to, the following:

org.eclipse.e4.core.services.Adapter

org.eclipse.e4.core.services.StatusReporter

org.eclipse.e4.core.services.Logger

org.eclipse.e4.core.services.events.IEventBroker

org.eclipse.e4.workbench.ui.IPresentationEngine

org.eclipse.jface.window.IShellProvider

As always, you can just prefix your object's fields with the @Inject annotation and then they will be injected when the object is constructed.

publicclass AccountsPart {
@Inject
private EPartService partService;}

OSGi Services

For a standard e4 application, if an injection requirement cannot be satisfied in the context chain, the context lookup will ultimately query OSGi. Hence, you can also ask for OSGi services like LogService or PackageAdmin.

Constants

There are some constants defined in org.eclipse.e4.ui.services.IServiceConstants that are available for consumption. The most commonly used ones will probably be ACTIVE_SELECTION, ACTIVE_PART and ACTIVE_SHELL. Though ACTIVE_SHELL will likely be preceded by IShellProvider. To use a constant, you would need the @Named annotation.

The following information seems outdated and requires an update

Overview of current and suggested context mechanisms

IEquinoxContext (e4)

org.eclipse.core.runtime.RegistryContextFactory - Creates objects based on the registry's configuration element. Creates a user-specified class and injects into it contents of the configuration element and, optionally, the supplied context

org.eclipse.equinox.context.IEquinoxContext - This interface represents a hierarchical context with dependency injection capabilities. The context might have number of objects associated with it. For instance, a context might include log, status, and preferences. We'll call such associated objects "services" (through they don't have to be OSGi services).

parentLocator: A locator that can return a parent service instance if desired

locator: the service locator which can be used to retrieve dependent services

When we create our service locators using org.eclipse.ui.internal.services.IServiceLocatorCreator we pass in an owner (an IDisposable). If we are using services that go away (for example, the plugin is unloaded) we will call dispose() on the owner. For example, creating a service locator for a workbench window looks like:

IEvaluationContext (3.x)

Provided by org.eclipse.core.expressions this is the application context used in 3.x by the IEvaluationService (and hence all declarative expressions like enabledWhen/activeWhen/visibleWhen)

EvaluationContext is hierarchical and has a lookup strategy that checks the local cache and then asks the parent. In 3.x we create the root org.eclipse.core.expressions.EvaluationContext in our EvaluationAuthority(ExpressionAuthority) and populate it from the ISourceProviders, mostly contributed through org.eclipse.ui.services. In 3.x, the context hierarchy does not match the part hierarchy, it is basically flat. This supports the global application context used by expressions and the command framework, but prevents the notion of local context.

In e4

In E4 we're investigating a different part of the IEvaluationContext API, resolveVariable(*).

Object resolveVariable(String name, Object[] args);

Each EvaluationContext in the hierarchy can be provided one or more org.eclipse.core.expressions.IVariableResolvers. That allows the EvaluationContext to delegate the lookup. The algorithm is to iterate through the resolvers and return the first non-null answer, and if nothing is found delegate the resolve query to the parent.

In the e4 command investigation, Bug 257429 Command investigation phase 1, each workbench model Part<?> has an associated context. The IServiceLocator behaviour could be implemented by resolving a service variable "org.eclipse.e4.service" with the service as an argument.

Walk up the SWT parent hierarchy until we find a control that is owned by a Part<?> like a view or workbench window

Go to the application and look up the IEvaluationContext that was created with that Part<?>

With this mapping, the IEvaluationContext and IServiceLocator hierarchy are identical, and extending this to support different kinds of lookups for different variables means adding more IVariableResolvers.

ILocator Prototype

This prototype was a generalization of the org.eclipse.ui.services.IServiceLocator and the org.eclipse.core.expressions.IEvaluationContext. As with the standard IServiceLocator, using org.eclipse.e4.locator.ILocator avoids having to deal with any global singletons from the client's point of view. But in the framework, getting a service or variable is separated into the tree datastructure that supports local data at each node, and pluggable strategies that determine how each piece of data is set or retrieved.

Usecase 2 - IHandlerService uses the locator

The HandlerService uses the local storage to store active handlers for that context. This is currently implemented with a handler service chain, although would not need to be if the context to be used was passed in as part of the request:

Since the handlers are stored in the locator hierarchy they will be looked up using the default lookup strategy, which is org.eclipse.e4.locator.ActiveChainLookupStrategy. The algorithm is to go to the bottom of the active child chain, then walk up the parent chain until the first value can be returned.

The algorithm returns the correct answer no matter where the question is asked.

When executing in the active editor, it will return the active editor handler for that command

When executing in the global context (like a keybinding), it will go down to the active editor and return the active editor handler

When executing in a view that is not currently active (either because of cheatsheets or macros, or because an event need to trigger the command in that view), it will correctly return the view handler for that command.

Usecase 3 - active contexts

I have a sample IContextService the follows the same pattern used by IHandlerService. But in our hierarchy of parts, it makes sense that each part sets the context IDs it cares about without worrying about what other parts or levels have done. Setting an active context ID involves adding it to the local datastore and firing correct property change notifications. To get the active context IDs, find the active context chain and sum all of the IDs store in the local datastore.

Contexts with ComputedValue

Similar to the other designs, this is a "tree of local maps". A prototype is available in org.eclipse.e4.core.services. At any given Context, you can set a variable to a value or to a ComputedValue (function).

ComputedValue can also be used to implement the active context chain lookup strategy. It would follow any activeChild variable (in theory, maintained by the workbench) to the bottom of the chain, and then follow the standard lookup procedure (up the parent chain).

It seems we would use one variable to store the local IDs at each Context level.

A ComputedValue for activeContextIds could then sum them up.

Would we still use an IContextService to manage and/or simplify the interaction between activating a context and retrieving the activeContextIds?

Discussed in 20090115 meeting

Services are still useful. They can manage the co-ordination of setting or looking up data above and beyond what context.set(name, value) does. They can also arbitrate in more complex scenarios (i.e. how do we deal with 2 active handlers at the Part level? How do we let the user activate 2 handlers at the part level).

For the example usecase like the IContextService, should the context IDs used be String values in a variable that is a Set, or should they each be their own variable, categorized in some way?

As their own variable, it becomes easier to listen for that specific context (as opposed to being told the context changed, so look it up).

What does categorization of variables mean? Is that added value provided by the IContextService, or is that inherent in the Context?

Q: If we have a workbench model, should contexts contain the active lookup elements (ComputedValue) and use the EMF model for local storage instead of an internal map?

(not of interest for M1 or possibly even M2)

Should we restrict the workbench model to workbench/layout/rendering information?

Should we allow contributors to "graft" their model onto the workbench model?

Should we provide an IModelService (from a Context) that contributors could publish their model to (and then supply information through ComputedValue)

General Requirements

The following are some very general requirements of a context system:

Support notion of service availability lifecycle. The service publisher can add or withdraw services at any time

Support notion of service usage lifecycle. Some services may want to perform cleanup when clients are no longer using the service

Eliminate global singletons

Separation of usage from knowledge of environment to increase reuse (inversion of control)

Lookup of both simple variable values and "live" service objects

Flexible algorithm for service lookup - how a service is retrieved is completely in the hands of the local context, or perhaps some pluggable strategy inserted into the local context

Interesting Use Cases

The following are some interesting concrete use cases that came up during discussion

Font lookup. Some composite needs to know what font to use. How the font is chosen depends on the context for that particular instance of the composite. Embedding the composite in a dialog would result in one font, and embedding the identical control into a view would result in another.

Printing. The workbench window has a 'print' button. the print button lives in some higher context (the window), but needs to access a more specific context (the active part). When the button is clicked it should:

If the active part has a selection, print the selection

If the active part is an editor with no selection, print the document

If the active part is of another kind, print the contents of the part

If there is no active part do nothing

Colors and fonts preference page. This preference page shows a 'preview' which is an embedded view or editor. That view or editor should be the 'real' view or editor rather than a fake one. When that part is embedded in the preference page, it should retrieve preference values from its local context (the preferences that the user has set but not yet applied). When the same editor control appears outside the preference page, it should obtain preference values directly from the preference service.

Cheat sheet / macro recorder playback. Commands execute in a local context (selection, focus control, etc). When the user clicks in a cheat sheet or macro playback, the 'real' focus control and selection are in the cheat sheet or macro view. The command should execute as if the current selection or focus control is the object on which the command is running. (Even apparently global things like 'focus control' are in fact also relative to a context - there should be no single global notion of active context)