This article describes how you can react to changes in the application model.
1. Listening to Eclipse framework events
If the application model changes, the Eclipse framework sends out notifications. The Eclipse 4 framework allows event listeners to be notified if this happens.
For example, the UIEvents.UILifeCycle.APP_STARTUP_COMPLETE
event is triggered once the application has started.
Application components can register for this event and are called by the framework once it occurs.
If your application model changes—for example, if windows, perspectives, parts, or their containers (such as the application, perspective stacks, part sash containers, or part stacks) are modified—the framework detects these changes.
In this case, the IEventBroker
propagates an event.
The central class that defines the Eclipse framework events is the UIEvents
class from the org.eclipse.e4.ui.workbench
package.
It contains the events or topics and helper methods for working with the events.
This class contains information in its Javadoc about the purpose of events.
The Eclipse framework sends out objects of the type org.osgi.service.event.Event
.
1.1. Example: Part activation event
A topic that is fired by Eclipse is UIEvents.UILifeCycle.ACTIVATE
, which is fired every time a part is activated.
@Inject
@Optional
public void subscribeTopicPartActivation(@UIEventTopic(UIEvents.UILifeCycle.ACTIVATE) Event event) {
Object element = event.getProperty(EventTags.ELEMENT);
if (!(element instanceof MPart)) {
return;
}
MPart part = (MPart) element;
System.out.println("Part activated: " + part.getLabel());
}
The Event
class contains properties, such as EventTags.ELEMENT
, from which you can receive the element associated with this event.
Review the UIEvents
class and its internal interfaces, such as UIEvents.EventTags
, to see the other events fired by the Eclipse framework.
1.2. Extracting event information
The UIEvents.EventTags
interface defines the possible event tags.

These event tags are explained in the following sections.
1.2.1. ATTNAME event tag
The ATTNAME
property of the event is the attribute of the model that has been changed.
For instance, if you listen for changes to a model element’s label, the ATTNAME
of the event will be label
.
@Inject
@Optional
public void subscribeTopicLabelChange(@EventTopic(UIEvents.UILabel.TOPIC_LABEL) Event event) {
Object element = event.getProperty(EventTags.ATTNAME);
// will print "label" to the system output
System.out.println(element);
}

The label is an XML attribute and can be found in the source of your Application.e4xmi file.
|
<children xsi:type="basic:Part" xmi:id="_9CJOwNgYEeKX2Jv3m0M6IA"
elementId="com.sample.application.part.attname"
contributionURI="bundleclass://com.sample.application/yourpackage.attname"
label="ATTNAME sample label"/>
1.2.2. ELEMENT event tag
The ELEMENT
event tag generally refers to the model element that is associated with the event.
1.2.3. NEW_VALUE and OLD_VALUE event tags
The NEW_VALUE
and OLD_VALUE
properties contain the new and old values of the element’s attribute.
These tags represent the values before and after the attribute change.
For example, use them to detect which value was updated when listening for selection changes in perspectives.
In Eclipse 3.x, you would have registered an IPerspectiveListener for the WorkbenchWindow and implemented the perspectiveChanged(…) method.
In Eclipse 4, you think in a DOM (Document Object Model) manner, where <ELEMENT ATTNAME="NEW_VALUE"> is manipulated and fired within events.
|
An example of using the values of an attribute in the model is a listener for a perspective change.
@Inject
@Optional
public void subscribeTopicSelectedElement(@EventTopic
(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
Object element = event.getProperty(EventTags.ELEMENT);
Object newValue = event.getProperty(EventTags.NEW_VALUE);
// ensure that the selected element of a perspective stack is changed and that this is a perspective
if (!(element instanceof MPerspectiveStack) || !(newValue instanceof MPerspective)) {
return;
}
MPerspectiveStack perspectiveStack = (MPerspectiveStack) element;
MPerspective perspective = (MPerspective) newValue;
System.out.println("Selected perspective of " + perspectiveStack + " is " + perspective.getLabel());
}
If you want to listen for an event when the perspective changes, you need to listen for the change of the selectedElement
attribute of the MPerspectiveStack
. You can then get the new and old MPerspective
from the EventTags.NEW_VALUE
and EventTags.OLD_VALUE
properties.
You listen for the changed selectedElement
attribute value of the MPerspectiveStack
, rather than looking for a "perspective change" event.
It is good to keep the DOM structure of the application model in mind and think about the changes that can occur within the application model.
1.2.4. TYPE event tag
With the TYPE
event tag, you can determine what action has been performed on the application model.
You can find the various types in the UIEvents.EventTypes
interface.
With these event types, you can determine whether a model element was added, created, moved, removed, or an attribute was set.
The UIEvents
class offers convenience methods to check for some types.

The isADD(Event)
and isREMOVE(Event)
methods apply to both single and multiple items (e.g., ADD and ADD_MANY).
1.2.5. POSITION event tag
The POSITION
event tag contains the new position of model elements.
This property is only set if a collection of elements is concerned.
If you move parts in an MPartStack
or between different MPartStack
containers, you can listen for changes to the children of an element container like this:
@Inject
@Optional
public void subscribeTopicElementContainerChildren(@EventTopic
(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
Object element = event.getProperty(EventTags.ELEMENT);
if (!(element instanceof MPartStack)) {
return;
}
if (UIEvents.isADD(event)) {
// check new value, because we check for addition and old value will be null
Object newValue = event.getProperty(EventTags.NEW_VALUE);
if (newValue instanceof MPart) {
MPart part = (MPart) newValue;
System.out.println("Added " + part.getLabel() + " at position: "
+ event.getProperty(EventTags.POSITION));
}
} else if (UIEvents.isREMOVE(event)) {
// check old value, because we check for remove and new value will be null
Object oldValue = event.getProperty(EventTags.OLD_VALUE);
if (oldValue instanceof MPart) {
MPart part = (MPart) oldValue;
System.out.println("Removed " + part.getLabel() + " from position: "
+ event.getProperty(EventTags.POSITION));
}
}
}
If you drag and drop an MPart
within an MPartStack
, the MPart
is removed and then added back to the MPartStack
.
The details can be seen in the UIEventPublisher.formatData()
method from the org.eclipse.e4.ui.internal.workbench
package.
The position attribute is only used for the move
, add
, or remove
events.
1.2.6. WIDGET event tag
The WIDGET
event tag can be used to get the underlying widget, e.g., a Composite
of the model element that is associated with the event.
You can directly interact with the underlying widget.
In most cases, this is not necessary, because the model elements themselves provide most of the methods to interact with the widget, such as setLabel()
or setVisible()
.
1.3. Convenience methods for working with events
Besides the convenience methods for the event types, the UIEvents
class offers two more convenience methods:

1.3.1. The contains
method
The contains
method can be used to check whether a certain object is part of an event’s property.
Imagine you are listening for changed tags on a certain model element and want to determine if a certain tag is part of the tags of the given model element.
In this case, the contains
method helps you with that task.
An example of this can be found in the subscribeTopicTagsChanged(Event)
method of the ToolBarManagerRenderer
class from the Eclipse framework.
@Inject
@Optional
private void subscribeTopicTagsChanged(@UIEventTopic
(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
Object changedObj = event.getProperty(EventTags.ELEMENT);
// this should only be applied to MToolbar elements
if (!(changedObj instanceof MToolBar)) {
return;
}
final MUIElement changedElement = (MUIElement) changedObj;
// In case tags have been added and the new tag list contains the
// IPresentationEngine.HIDDEN_EXPLICITLY String, the element should be hidden
if (UIEvents.isADD(event)) {
if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE,
IPresentationEngine.HIDDEN_EXPLICITLY)) {
changedElement.setVisible(false);
changedElement.setToBeRendered(false);
}
// If IPresentationEngine.HIDDEN_EXPLICITLY tag was removed, the element should be visible again
} else if (UIEvents.isREMOVE(event)) {
if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE,
IPresentationEngine.HIDDEN_EXPLICITLY)) {
changedElement.setVisible(true);
changedElement.setToBeRendered(true);
}
}
}
This code demonstrates how the existence of a certain tag (IPresentationEngine.HIDDEN_EXPLICITLY
) is checked with the contains
method.
1.3.2. The asIterable
method
The asIterable
method can be used to get an Iterable
of an event’s property.
Let’s take the example where we listened for the UIEvents.ElementContainer.TOPIC_CHILDREN
event and checked the new position.
This example fails when we add more than one child to the MPartStack
, which results in the UIEvents.EventTypes.ADD_MANY
event type.
In this case, nothing would be printed to System.out
, because we have a list in the EventTags.NEW_VALUE
property rather than an MPart
.
We need to enhance our subscribeTopicElementContainerChildren
method like this:
@Inject
@Optional
public void subscribeTopicElementContainerChildren(@EventTopic
(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
Object element = event.getProperty(EventTags.ELEMENT);
if (!(element instanceof MPartStack)) {
return;
}
if (UIEvents.isADD(event)) {
// check new value, because we check for addition and old value will
// be null
Iterable<?> asIterable = UIEvents.asIterable(event, EventTags.NEW_VALUE);
for (Object object : asIterable) {
if (object instanceof MPart) {
MPart part = (MPart) object;
System.out.println("Added " + part.getLabel() + " at position: "
+ event.getProperty(EventTags.POSITION));
}
}
} else if (UIEvents.isREMOVE(event)) {
// check old value, because we check for remove and new value will
// be null
Iterable<?> asIterable = UIEvents.asIterable(event, EventTags.OLD_VALUE);
for (Object object : asIterable) {
if (object instanceof MPart) {
MPart part = (MPart) object;
System.out.println("Removed " + part.getLabel() + " from position: "
+ event.getProperty(EventTags.POSITION));
}
}
}
}
2. Optional exercise: Changing the window title on a perspective change
In this exercise, we will change the window title according to the active perspective.
2.1. Add a new model add-on that listens to perspective switches
Create the following PerspectiveSwitchAddon
class.
This add-on listens for the perspective change event.
package com.vogella.tasks.ui.addon;
import jakarta.inject.Inject;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.extensions.EventTopic;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.UIEvents.EventTags;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.osgi.service.event.Event;
public class PerspectiveSwitchAddon {
@Inject
private EModelService modelService;
@Inject
@Optional
public void subscribeTopicSelectedElement(
@EventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
Object newValue = event.getProperty(EventTags.NEW_VALUE);
// only run this, if the NEW_VALUE is a MPerspective
if (!(newValue instanceof MPerspective)) {
return;
}
MPerspective perspective = (MPerspective) newValue;
// Get the MWindow, where we want to change the label
MWindow topLevelWindowOfPerspective = modelService.getTopLevelWindowFor(perspective);
topLevelWindowOfPerspective.setLabel(perspective.getLabel() + " Window");
}
}
Now we add a new model add-on via a model fragment.

2.2. Validate
Start your application again. Switch perspectives and observe the window title. It should change to the name of the perspective.
If the add-on is not visible, try to start your runtime with the -clearPersistedState flag to remove persisted model information.
|
3. Application Model Events online resources
3.1. vogella Java example code
If you need more assistance we offer Online Training and Onsite training as well as consulting