Jump to: navigation, search

Difference between revisions of "Eclipse4/RCP/Event Model"

< Eclipse4‎ | RCP
Line 2: Line 2:
  
 
= Introduction  =
 
= Introduction  =
 
 
Eclipse 4 uses a single global event bus with a publish and subscribe event model. The rational for using this strategy is described in [[E4/Event Processing|Event Processing in E4]]. The global event bus is implemented on top of the OSGi eventing engine and is accessed using org.eclipse.e4.core.services.events.IEventBroker.  
 
Eclipse 4 uses a single global event bus with a publish and subscribe event model. The rational for using this strategy is described in [[E4/Event Processing|Event Processing in E4]]. The global event bus is implemented on top of the OSGi eventing engine and is accessed using org.eclipse.e4.core.services.events.IEventBroker.  
  
 +
= Getting an IEventBroker =
 
IEventBroker provides methods for subscribing and unsubscribing to events on the bus, as well as methods for posting events to the bus.  
 
IEventBroker provides methods for subscribing and unsubscribing to events on the bus, as well as methods for posting events to the bus.  
  
Line 42: Line 42:
  
 
= Responding to Events =
 
= Responding to Events =
 +
== Dependency Injection ==
  
There are two ways to be notified of events:
+
Whenever possible you should use dependency injection to register and respond to events. This method results in less code, is easier to read and maintain and has fewer anonymous inner classes.
 
+
* Dependency Injection using @UIEventTopic
+
* Subscribing to the event using IEventBroker.subscribe()
+
 
+
Whenever possible you should use dependency injection. This results in less code that is easier to read and maintain with fewer anonymous inner classes.  
+
 
+
In each example below we show how to receive the event published by the posting example above.
+
 
+
Dependency Injection
+
  
 
<source lang="java">
 
<source lang="java">
Line 61: Line 53:
 
</source>  
 
</source>  
  
Subscribing using IEventBroker  
+
== Subscribing using IEventBroker ==
 +
In some circumstances you will not be able to use dependency injection and must subscribe to events directly.  This is the case if the class you are editing does not use dependency injection.  You can usually tell this because the class does not already contain any @Inject annotations.
 +
 
 +
You also can not use dependency injection if the topic string you are registering for is constructed at run time.  The annotation strings need to be available and complete and compile time to be used by @UIEventTopic()
  
 
<source lang="java">
 
<source lang="java">
Line 69: Line 64:
  
 
eventBroker.subscribe(TOPIC_STRING, closeHandler);
 
eventBroker.subscribe(TOPIC_STRING, closeHandler);
 
 
 
 
}
 
}
Line 77: Line 71:
 
     …
 
     …
 
}
 
}
 
 
 
 
+
private org.osgi.service.event.EventHandler closeHandler = new EventHandler() {
private EventHandler closeHandler = new EventHandler() {
+
 
     public void handleEvent(Event event) {
 
     public void handleEvent(Event event) {
  
Line 88: Line 80:
 
</source>  
 
</source>  
  
UI Model Events  
+
= UI Model Events =
  
The Eclipse 4 UI is a model based UI built on an underlying EMF Model. Part of the UI framework listens to EMF events and publishes UIEvents on the global event bus.  
+
The Eclipse 4 UI is a model based UI with an underlying EMF Model. Part of the UI framework, UIEventPublisher, listens to EMF events and publishes corresponding OSGi Events on the global event bus.  
  
The chief class of interest is org.eclipse.e4.ui.workbench.UIEvents. This class defines all the topic and attribute strings used to subscribe and respond to the various UI events through either of the two mechanisms described above.  
+
The constants used to subscribe to and work with the UI model events are defined in org.eclipse.e4.ui.workbench.UIEvents. The bulk of the constants in this class are generated directly from the EMF model at development time using the utility org.eclipse.e4.ui.internal.workbench.swt.GenTopic. There are a few hand crafted constants for non UI events such as the life cycle events.  
  
The bulk of the constants in this class are generated directly from the EMF model at development time using the utility org.eclipse.e4.ui.internal.workbench.swt.GenTopic. There are a few hand crafted constants for non UI events such as the Lifecycle events.  
+
Late in the M4 milestone the hierarchy and usage pattern of UIEvents was significantly changed. This page discusses the new mechanism. For a discussion of the old mechanism and the changes you need to make to migrate from the old style to the new style look [[here|here]].  
  
Late in the M4 milestone the hierarchy and usage pattern of UIEvents underwent a significant change. This page will discuss the new mechanism. For a discussion of the old mechanism and the changes you need to make to migrate from the old style to the new style see this [page]
+
== UIEvent Structure ==
  
UIEvent Structure
+
Each EMF model element has a corresponding interface defined in UIEvents. Each interface has two constants defined for each attribute of the model element.  
 
+
Each EMF model element will have a corresponding inner interface defined in UIEvents. Each interface has two constants defined for each attribute of the corresponding model element.  
+
  
 
Here is the example for the UILabel model element  
 
Here is the example for the UILabel model element  
  
 
<source lang="java">
 
<source lang="java">
    @SuppressWarnings("javadoc")
 
 
   public static interface UILabel {
 
   public static interface UILabel {
  
 
       // Topics that can be subscribed to
 
       // Topics that can be subscribed to
 
      @Deprecated
 
      public static final String ALL = "org/eclipse/e4/ui/model/ui/UILabel"; //$NON-NLS-1$
 
 
 
       public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/UILabel/*"; //$NON-NLS-1$
 
       public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/UILabel/*"; //$NON-NLS-1$
 
       public static final String TOPIC_ICONURI = "org/eclipse/e4/ui/model/ui/UILabel/iconURI/*"; //$NON-NLS-1$
 
       public static final String TOPIC_ICONURI = "org/eclipse/e4/ui/model/ui/UILabel/iconURI/*"; //$NON-NLS-1$
Line 125: Line 110:
 
</source>  
 
</source>  
  
The TOPIC_* constants are used to subscribe to events generated when the corresponding attribute changes. The constant can be used for either the dependancy injection technique or the IEventBroker.subscribe() technique described above. The TOPIC_ALL constant is used to register for changes on all the attributes of a model element.  
+
The TOPIC_* constants are used to subscribe to events generated when the corresponding attribute changes. The constant can be used for either the dependency injection technique or the IEventBroker.subscribe() technique described above. The TOPIC_ALL constant is used to register for changes on all the attributes of a model element.
 +
 
 +
The constants named directly for the element attribute (LABEL, TOOLTIP and ICONURI from the example above) are used in event handlers if you need to inspect the event and determine which attributes have actually changed.  
  
The constants named directly for the element attribute (LABEL, TOOLTIP and ICONURI from the example above) are used in the event handlers themselves if you need to inspect the event and determine which attributes have actually changed.  
+
This works because UIEventPublisher adds the attribute name from the source EMF event to the OSGi event with the property key UIEvents.EventTags.ATTNAME. The other UIEvents.EventTags.* constants list other values that may be published in an event depending on the event type. Different event types will store different tags in the event.
  
This works because UIEventPublisher adds the attribute name from the source EMF event to the OSGi event with the property key UIEvents.EventTags.ATTNAME. The other UIEvents.EventTags.* constants list other values that may be published in an event depending on the event type. Different event types will store differnt tags in the event.
+
== UI Event Types ==

Revision as of 13:58, 2 December 2011

Stop.png
This page is a stub
This page is currently undergoing substantial and active editing. Please refrain from editing this page or raising issues against this page until this banner is gone. Hopefully later today. :-)


Introduction

Eclipse 4 uses a single global event bus with a publish and subscribe event model. The rational for using this strategy is described in Event Processing in E4. The global event bus is implemented on top of the OSGi eventing engine and is accessed using org.eclipse.e4.core.services.events.IEventBroker.

Getting an IEventBroker

IEventBroker provides methods for subscribing and unsubscribing to events on the bus, as well as methods for posting events to the bus.

An instance of the IEventBroker is typically available in the EclipseContext or directly through dependency injection:
private IEclipseContext ecliseContext;
…
IEventBroker eventBroker = eclipseContext.get(IEventBroker.class);

or is provided via dependency injection.

@Inject
IEventBroker eventBroker;

Posting an Event

Putting an event on the global event bus is as simple as calling one of two methods

IEventBroker.post(String topic, Object data) // synchronous delivery

or

IEventBroker.send(String topic, Object data) // asynchronous delivery
 
Example:
...

foo.Bar payload = getPayload();

boolean wasDispatchedSuccessfully = eventBroker.send(TOPIC_STRING, payload);

If the payload of the send or post command is a regular Java object, then the payload is attached to the OSGi event as a property with the key IEventBroker.DATA. If payload is a Dictionary or a Map, all the values from the Dictionary or Map are added as properties with their associated keys.

Responding to Events

Dependency Injection

Whenever possible you should use dependency injection to register and respond to events. This method results in less code, is easier to read and maintain and has fewer anonymous inner classes.

@Inject @Optional
public void closeHandler(@UIEventTopic(TOPIC_STRING) foo.Bar payload) {
    // Useful work that has access to payload.  The instance of foo.Bar that the event poster placed on the global event bus with the topic TOPIC_STRING
}

Subscribing using IEventBroker

In some circumstances you will not be able to use dependency injection and must subscribe to events directly. This is the case if the class you are editing does not use dependency injection. You can usually tell this because the class does not already contain any @Inject annotations.

You also can not use dependency injection if the topic string you are registering for is constructed at run time. The annotation strings need to be available and complete and compile time to be used by @UIEventTopic()

IEventBroker eventBroker;void addSubscribers() {
 
eventBroker.subscribe(TOPIC_STRING, closeHandler);}
 
void removeSubscribers() {
    eventBroker.unsubscribe(closeHandler);}private org.osgi.service.event.EventHandler closeHandler = new EventHandler() {
    public void handleEvent(Event event) {
 
    // Useful work that has access
    foo.Bar payload = (foo.Bar) event.getProperty(IEventBroker.DATA);
}

UI Model Events

The Eclipse 4 UI is a model based UI with an underlying EMF Model. Part of the UI framework, UIEventPublisher, listens to EMF events and publishes corresponding OSGi Events on the global event bus.

The constants used to subscribe to and work with the UI model events are defined in org.eclipse.e4.ui.workbench.UIEvents. The bulk of the constants in this class are generated directly from the EMF model at development time using the utility org.eclipse.e4.ui.internal.workbench.swt.GenTopic. There are a few hand crafted constants for non UI events such as the life cycle events.

Late in the M4 milestone the hierarchy and usage pattern of UIEvents was significantly changed. This page discusses the new mechanism. For a discussion of the old mechanism and the changes you need to make to migrate from the old style to the new style look here.

UIEvent Structure

Each EMF model element has a corresponding interface defined in UIEvents. Each interface has two constants defined for each attribute of the model element.

Here is the example for the UILabel model element

   public static interface UILabel {
 
       // Topics that can be subscribed to
       public static final String TOPIC_ALL = "org/eclipse/e4/ui/model/ui/UILabel/*"; //$NON-NLS-1$
       public static final String TOPIC_ICONURI = "org/eclipse/e4/ui/model/ui/UILabel/iconURI/*"; //$NON-NLS-1$
       public static final String TOPIC_LABEL = "org/eclipse/e4/ui/model/ui/UILabel/label/*"; //$NON-NLS-1$
       public static final String TOPIC_TOOLTIP = "org/eclipse/e4/ui/model/ui/UILabel/tooltip/*"; //$NON-NLS-1$
 
       // Attributes that can be tested in event handlers
       public static final String ICONURI = "iconURI"; //$NON-NLS-1$
       public static final String LABEL = "label"; //$NON-NLS-1$
       public static final String TOOLTIP = "tooltip"; //$NON-NLS-1$
   }

The TOPIC_* constants are used to subscribe to events generated when the corresponding attribute changes. The constant can be used for either the dependency injection technique or the IEventBroker.subscribe() technique described above. The TOPIC_ALL constant is used to register for changes on all the attributes of a model element.

The constants named directly for the element attribute (LABEL, TOOLTIP and ICONURI from the example above) are used in event handlers if you need to inspect the event and determine which attributes have actually changed.

This works because UIEventPublisher adds the attribute name from the source EMF event to the OSGi event with the property key UIEvents.EventTags.ATTNAME. The other UIEvents.EventTags.* constants list other values that may be published in an event depending on the event type. Different event types will store different tags in the event.

UI Event Types