Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Eclipse4/RCP/Modeled UI/Rendering the Model
With the Eclipse 4 Application Platform, the UI model has been separated from how the model is presented, meaning rendered as widgets. The rendering of the presentation is handled by a presentation engine. The presentation is configurable by a number of properties that can be specified either as product properties or on the command-line.
Contents
Defining a New Presentation Engine
The renderer is configured using a product property (described below), and is expected to implement org.eclipse.e4.ui.workbench.IPresentationEngine. Implementations of this class are responsible for creating or destroying widgets corresponding to model elements, as well as running an event loop required for handling user events on those widgets. These special tags are defined in the org.eclipse.e4.ui.workbench.IPresentationEngine interface.
Presentation engines are expected to respect tags presented by model elements. For example, parts bearing the NoClose tag should not have any affordances to allow closing or disposing of the part.
Although it is primarily defined for testing, the HeadlessContextPresentationEngine provides a starting point for defining a new presentation engine.
Configuring a New Presentation Engine
Presentation engines are specified through using the "presentationURI" product property. For example:
<extension point="org.eclipse.core.runtime.products" name="Example" id="org.example.product"> <product application="org.eclipse.e4.ui.workbench.swt.E4Application" name="Example"> <property name="applicationXMI" value="org.example.app/Application.e4xmi" /> <!-- configure the new renderer: the renderer may choose to use or ignore the 'applicationCSS' --> <property name="presentationURI" value="platform:/plugin/org.example.app/org.application.app.MyWidgetEngine" /> <property name="applicationCSS" value="org.example.app/style.css" /> </product> </extension>
When defining a presentation engine, it is worth considering how or whether the engine should be extensible with regards to new model element definitions.
What is the difference between #visible and #toBeRendered?
#visible captures whether the rendered UI elements are in presentation or hidden from view. With the SWT renderer, when #visible = false, then the element's widgets are reparented to an invisible shell; the widget is still alive, but won't be seen.
#toBeRendered captures whether this UI element should be rendered; it serves as an instruction to the renderer as to whether the element should or should not be rendered. When set to true, the renderer should explicitly When set to false, all resources are removed and nulled.
Enhancing the Standard SWT Presentation Engine
Eclipse 4 ships with a standard SWT presentation engine, defined in org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine. This engine delegates to a renderer factory to build renderers that correspond to the different model elements. The renderer factory is provided as a factory property.
Defining and Rendering A New Element Type
<extension point="org.eclipse.core.runtime.products" name="Example" id="org.example.product"> <product application="org.eclipse.e4.ui.workbench.swt.E4Application" name="Example"> <property name="applicationXMI" value="org.example.app/Application.e4xmi" /> <!-- by not specifying a presentation engine, we use the standard SWT engine which delegates to a renderer factory --> <property name="rendererFactoryUri" value="platform:/plugin/org.example.app/org.application.app.MyRendererFactory" /> <property name="applicationCSS" value="org.example.app/style.css" /> </product> </extension>
We define a new renderer factory to add support for our new model element:
package org.application.app; import org.eclipse.e4.ui.workbench.renderers.swt.WorkbenchRendererFactory; import org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer; public class MyRendererFactory extends WorkbenchRendererFactory { protected NewElementRenderer newElementRenderer; public AbstractPartRenderer getRenderer(MUIElement uiElement, Object parent) { if(uiElement instanceof MNewElement) { if(newElementRenderer == null) { newElementRenderer = new NewElementRenderer(); initRenderer(newElementRenderer); } return newElementRenderer; } return super.getRenderer(uiElement, parent); } public class NewElementRenderer extends SWTPartRenderer { public Object createWidget(final MUIElement element, Object parent) { Label label = new Label((Composite)parent, SWT.NONE); label.setText("Coolness"); return label; } } }
Adding CSS Support for a New Widget Type
Add an extension for org.eclipse.e4.u.css.core.elementProvider:
<extension point="org.eclipse.e4.u.css.core.elementProvider"> <provider class="my.SWTElementProvider"> <widget class="org.eclipse.ui.forms.Section"/> <widget class="org.eclipse.ui.forms.widgets.FormText"/> </provider> </extension>
The provider class must implement org.eclipse.e4.ui.css.core.dom.IElementProvider and is intended to adapt a widget to a DOM element. The base SWT provider implementation is org.eclipse.e4.ui.css.swt.dom.SWTElementProvider.
Next, you must define a property handler through the org.eclipse.e4.ui.css.swt.property.handler extension point. The extension specifies a handler class and a list of CSS properties that it is able to fetch or set on a particular type of element.
<extension point="org.eclipse.e4.ui.css.swt.property.handler"> <handler adapter="my.FormTextElement" composite="true" handler="my.FormElementPropertyHandler"> <property-name name="background" /> <property-name name="background-color" /> <property-name name="background-image" /> </handler> </extension>
A single element may require individual handlers for each of its supported properties.
See the org.eclipse.e4.ui.css.swt/plugin.xml and its referenced classes for an example of how CSS support has been implemented for the base SWT classes.