Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "GEF/GEF4/Common"

< GEF‎ | GEF4
(IAdaptable, AdapterKey)
Line 50: Line 50:
 
</source>
 
</source>
  
The last point is realized by formalizing that each adaptable has to fire property change events, when adapters get registered or unregistered.
+
 
 +
To formalize support for notifying listeners about registration and unregistration of adapters, IAdaptable extends IPropertyChangeNotifier, which provides capabilities for registering and unregistering respective listeners.
  
 
=== IAdaptable.Bound ===
 
=== IAdaptable.Bound ===

Revision as of 04:20, 9 May 2015

Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in the original wiki page.


Introduction

The GEF4 Common component provides key concepts and infrastructure to be potentially used by all other GEF4 components.

Activate

  • package: org.eclipse.gef4.common.activate

GEF4-Common-activate.png

Adapt

  • package: org.eclipse.gef4.common.adapt

GEF4-Common-adapt.png

The adapt package provides a modernized interpretation of the Eclipse Core Runtime's IAdaptable, providing the following enhancements:

  1. Adapters may be registered and retrieved by means of a TypeToken key as an alternative to a Class key, which ensures that adapters with parameterized types may also be registered and retrieved in a type-safe manner, not only via their raw type. For instance, an adapter instance a1 of parameterized type A<T1> and an instance a2 of type A<T2> can both be registered at an IAdaptable. The GEF/GEF4/MVC GEF4 MVC component makes use of this intensively, when registering providers, i.e. a Provider<IGeometry> and a Provider<IFXAnchor> can now both be registered at an IAdaptable simultaneously.
  2. Adapters may (optionally) be registered and retrieved by providing an additional role key, which allows to register multiple adapters of the same type (using different roles) at an IAdaptable. For instance, adapter instances a1 and a2 of type A can both be registered at an IAdaptable using different roles. The GEF/GEF4/MVC GEF4 MVC component again makes use of this, when registering providers. Different geometry providers (Provider<IGeometry>) are e.g. registered for selection and hover feedback, by registering respective providers with respective roles.
  3. Adapters may request a back-reference to the respective IAdaptable they get registered at, by implementing a respective back-interface (IAdaptable.Bound). Again, this is intensively used within GEF/GEF4/MVC GEF4 MVC, where an IBehavior or IPolicy for instance needs to be aware of the host IVisualPart it is registered at.
  4. IAdaptable provides support for registering property change listeners, to be notified whenever adapters are registered or unregistered.

Besides the IAdaptable, IAdaptable.Bound, and AdapterKey abstractions that formalize the modernized adaptable pattern, the package also provides a supporting class (AdaptableSupport) to implement IAdaptable in compliance with its contract, as well as a standalone implementation (AdapterStore) of an IAdaptable.

IAdaptable, AdapterKey

The first two parts are realized by registering and retrieving adapters via an AdapterKey, which combines a type key (Class or TypeToken) with an (optional) role, instead of a Class key. The transferred getAdapter(Class<? super T>) method now is just a convenience operation that will retrieve the adapter registered under the default role (or the only adapter registered under the given Class key, if there is only one adapter for that type key). Support for type-safe registration and access of adapters with generic types is realized by supporting a TypeToken key instead of Class key. An adapter can thus be registered and retrieved in various ways:

  // register and retrieve adapter 'a' of raw type 'A' under 'default' role (traditional adaptable objects pattern).
  adaptable.setAdapter(A.class, a); 
  A a = adaptable.getAdapter(A.class);
 
  // register and retrieve adapter 'a' of generic type 'A<T>' under 'default' role
  adaptable.setAdapter(new TypeToken<A<T>>(){}, a);
  A<T> a = adaptable.getAdapter(new TypeToken<A<T>>(){});
 
  // register and retrieve adapter 'a' of raw type 'A' under role 'a1'
  adaptable.setAdapter(AdapterKey.get(A.class, "a1"));
  A a = adaptable.getAdapter(AdapterKey.get(A.class));
 
  // register and retrieve adapter 'a' of generic type 'A<T>' under role 'a1'
  adaptable.setAdapter(AdapterKey.get(new TypeToken<A<T>>(){}, "a1"));
  A a = adaptable.getAdapter(AdapterKey.get(new TypeToken<A<T>>(){}, "a1"));


To formalize support for notifying listeners about registration and unregistration of adapters, IAdaptable extends IPropertyChangeNotifier, which provides capabilities for registering and unregistering respective listeners.

IAdaptable.Bound

The third part is realized by formalizing the back reference from the adapter to the adapter through a respective interface. That is, if an adapter that is set/unset at an adaptable implements IAdaptable.Bound, the adaptable is responsible of setting/unsetting a back reference to itself on the adapter:

public class MyAdaptable implements IAdaptable {
 
  public <T> void setAdapter(AdapterKey<? super T> key, T adapter) {
    ...
    if (adapter instanceof IAdaptable.Bound) {
      ((IAdaptable.Bound<A>) adapter).setAdaptable(this);
    ...
  }
 
  public <T> T unsetAdapter(AdapterKey<? super T> key) {
    ...
    if (adapter instanceof IAdaptable.Bound) {
      ((IAdaptable.Bound<A>) adapter).setAdaptable(null);
    }
    ...
  }
}

AdaptableSupport

To enforce that implementers of IAdaptable properly follow this contract, the package furthermore provides an AdaptableSupport class, which does not formally implement the IAdaptable interface but provides implementations for all its methods and can thus be used as a delegate, as follows:

public class MyAdaptable implements IAdaptable {
 
  // create delegates
  private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  private AdaptableSupport<MyAdaptable> ads = new AdaptableSupport<MyAdaptable>(this, pcs);
 
  public <T> T getAdapter(AdapterKey<? super T> key){
    return ads.getAdapter(key);
  }
 
  ...
}


It needs to be provided with a PropertyChangeSupport, via which notifies listeners about registration and unregistration of adapters.

AdapterStore

The package furthermore provides an AdaptableStore, which can be used as a standalone IAdaptable.

Dispose

  • package: org.eclipse.gef4.common.dispose

GEF4-Common-dispose.png

Inject

  • package: org.eclipse.gef4.common.inject

This package contains Google Guice-based support for injection of adapters to adaptables.

GEF4-Common-inject-adaptermap.png

In addition to basic injection support for adapters, the package also provides support for scoping adapter instances during injection. GEF4-Common-inject-adaptablescopes.png

Notify

  • package: org.eclipse.gef4.common.notify

GEF4-Common-notify.png

Properties

  • package: org.eclipse.gef4.common.properties

GEF4-Common-properties.png

Reflect

  • package: org.eclipse.gef4.common.reflect

GEF4-Common-reflect.png

Back to the top