One area of improvement with the E4AP was to rethink how to approach themeing or styling an application — to change its look and feel. E4AP supports radical changes through the use of CSS, or cascading style sheets, the same technology used in HTML.
In brief, CSS supports separating how content is shown from how the content is presented (e.g., colors, fonts). CSS applies rules to affect the appearance of some subset of elements within a document. These elements are selected using selectors that identify elements based on element properties or their relationship to other elements within the document's container hierarchy. A general discussion of CSS is beyond the scope of this document, but as the CSS support is largely based on the same CSS standard as HTML and SVG CSS, many of the CSS tutorials and guides are mostly applicable to the E4AP .
Applying CSS to styling widgets, windows, and dialogs, may seem a bit strange at first. But a UI forms a hierarchy just like an HTML document. For example, an SWT window or dialog has a Shell as a root container, which contains a number of Composite or Group elements, each containing other widgets such as a CTabFolder, Text, Tree, or Table.
CSS selectors support identifying elements by their type, class, or id, in the form "type#id.class". In the CSS-SWT mapping:
- The type corresponds to the simple class name of the widget (e.g., Button, Composite).
- The CSS specification defines that the id must be unique within the document (i.e., within the window). A widget's id may be set by calling WidgetElement.setId(widget, "unique-id").
- An element may have a number of classes. The set of classes may be specified using WidgetElement.setCSSClass(widget, "space delimited set of classes"). CSS-SWT also exposes SWT's widget's data values through the class attribute.
The E4AP further annotates the widgets used for rendering the modelled elements. Specifically:
- A Modeled UI element's interface type (e.g., MPart, MTrimmedWindow) and its tags are exposed as CSS classes.
- The id corresponds to the modelled element's elementId, with periods replaced with dashes.
Some nifty ways that selectors can be used:
- Selecting on style bits: SWT widget style bits are exposed through the "style" attribute allowing queries like Button[style~='SWT.CHECK']
- Selecting by modelled element type. For example, to style partstacks shown within the editor area, to differentiate editors from views: #org-eclipse-ui-editorss .MPartStack
- Some JFace-created elements, such as instances of org.eclipse.jface.dialogs.Dialog and org.eclipse.jface.windows.Window install the JFace object as the top-level widget's data object. The class hierarchy of this object can be queried using the "swt-data-class" attribute. So the following selector will identify all Shells that are from a JFace dialog: Shell[swt-data-class ~= 'org.eclipse.jface.dialogs.Dialog']
- widget data: SWT widgets carry a data dictionary. These key-values can be queries through CSS selectors. For example, a widget configured with:
could be subsequently selected with *[level='basic'].
Installing / Configuring CSS Stylesheets
There are three ways to configure a CSS stylesheet for an application. The first three approaches are suited for RCP applications:
- [Eclipse 4.2 only] Launch Eclipse with -applicationCSS url:to/cssfile. Resources referenced by CSS files will be looked up in locations specified with -applicationCSSResources url:prefix/for/resources.
- Provide your own CSS-based theme using the org.eclipse.e4.ui.css.swt.theme extension point. This approach is discussed in the following section.
- Programmatically obtain the org.eclipse.e4.ui.css.core.engine.CSSEngine and provide a style sheet. See the CSSScratchPadWindow.applyCSS() for an example.
The other two ways are more intended for personal use or debugging/exploration:
- [Eclipse 4.2 only] Install the CSS Editor and customize the CSS in Preferences → General → Appearance.
- [Eclipse 4.2 only] Install the CSS Spy and use the CSS Scratchpad to define new CSS rules.
The CSS Editor and CSS Spy are add-on tools from the Platform/UI team that are available through the Eclipse Marketplace.
E4AP Themeing Support
A replacement Theme Manager is available in Eclipse 4 to manage multiple CSS-based themes. A theme is provided using the org.eclipse.e4.ui.css.swt.theme extension point; there is support for restricting a theme to a particular operating system or windowing system. The themes are managed by an org.eclipse.e4.ui.css.swt.theme.IThemeManager, available as an OSGi service. On a theme change, an event is sent using the OSGi EventAdmin service; the event is described in IThemeEngine.Events.THEME_CHANGED.
On 4.2, the preferences include a theme selector in Preferences → General → Appearance. On 3.7 or 3.8, you will need to trigger the theme change programmatically using the, exposed as an OSGi service.
Applying Rules Programmatically
- Obtaining the IStylingEngine as a service
- Fetching the CSSEngine for a Display
Extending CSS to handle new widgets
Adding CSS support to a custom widget takes three steps:
- Set the widget's class and (optional) id using the org.eclipse.e4.ui.services.IStylingEngine service.
- Define the widget's element adapter using the org.eclipse.e4.ui.css.core.elementProvider extension point.
- Define the new properties using the org.eclipse.e4.ui.css.core.propertyHandler extension point.
Setting the Widget Class and Id
The more generic approach to setting the id for a widget is through the methods on IStylingEngine.
For SWT widgets, the class and ids are stored in the widget data using specific keys:
- CSSSWTConstants.CSS_ID_KEY ("org.eclipse.e4.ui.css.id")
- The CSS identifier for this widget. Typically expected to be unique within the DOM (e.g., the Shell), though this is not enforced. Identifiers should not contain periods as they cannot otherwise be referenced in a CSS selector!
- CSSSWTConstants.CSS_CLASS_NAME_KEY ("org.eclipse.e4.ui.css.CssClassName")
- The space-separated list of CSS classes for this widget.
The org.eclipse.e4.ui.css.swt.dom.WidgetElement class provides some helper methods for setting these values.
Note that setting the CSS id or classes does not trigger a refresh of the element.
Defining the Widget Element
The element adapter is the CSS dual of the widget, responsible for translating a widget into a CSSStylableElement, essentially DOM Node as used in CSS. A Node provides a simplified interface to get the widget's parent and children. The element is also responsible for re-applying styles in response to changes on the widget. For example, ControlElement installs focus and mouse event handlers to trigger CSS :focus and :hover changes (currently disabled by default; see bug 362532). Typically most widgets can simply use ControlElement. These element classes must be registered using the org.eclipse.e4.ui.css.core.elementProvider extension point.
See CompositeElement for an example of an element.
Defining the CSS Property Handlers
There are a number of predefined interfaces and abstract CSS property handlers in org.eclipse.e4.ui.css.core.dom.properties.css2. Most implementations typically extend AbstractCSSPropertySWTHandler. A property handler must be registered with the org.eclipse.e4.ui.css.core.propertyHandler extension point.
For example, the AbstractCSSPropertyTextHandler provides base support for handling color and text-transform properties.
Differences from HTML and SVG CSS
- margin and padding (see bug 364070)
- E4AP's SWT CSS support does not support layout changes to enable techniques like Tableless Web Design.
- EclipseCon 2011 Tutorial: Style It! The Eclipse 4 Styling Tutorial (Kai Tödter, Boris Bokowski, Bogdan Gheorghe)