Time for action – using a CSS property

At present the color of the hand is set in the constructor of the ClockWidget, and cannot be changed after creation. It would be better if the style of the widget could be controlled externally using the CSS that is used to style the application. This is handled with an ICSSPropertyHandler subclass from the org.eclipse.e4.ui.css.swt plug-in.

  1. Open the plugin.xml file from the com.packtpub.e4.clock.ui plug-in and switch to the Dependencies tab. Add the org.eclipse.e4.ui.css.swt and org.eclipse.e4.ui.css.core plug-ins to the list. To ensure that the bundle will work if these are missing, mark them both as Optional dependencies.
  2. Create a new package com.packtpub.e4.ui.internal.css to store the classes necessary for CSS cooperation.
  3. Create a new class CSSPropertyClockHandler, which extends AsbtractCSSPropertySWTHandler. The IDE will offer to auto-create the missing methods applyCSSProperty and retrieveCSSProperty, so create these as they will be used next.
  4. In the applyCSSProperty method, set up an if block to verify that the control is an instance of ClockWidget, and exit the method if not. This will ensure that the only kinds of classes that are customized by this method are ClockWidget instances.
  5. Cast the control argument to a ClockWidget and store it in a local variable clock.
  6. Add a switch block that uses the propertyName to determine if it is clock-hand-color.

    Note

    Although an if statement would work in this case, if subsequent property names are added later, a switch will allow others to be seamlessly integrated in.

  7. If the propertyName is clock-hand-color, use the engine to get hold of a color from the value argument with:
    Color handColor = (Color)engine.convert(
     value, Color.class, control.getDisplay());
  8. To set the hand color on the ClockWidget, the ClockWidget class needs to be updated. Open the ClockWidget class and add a new field, private Color handColor, along with setHandColor and getHandColor getter methods. Modify the drawClock method to use the handColor if available, and fall back to the color created in the constructor if not. The changes will look like:
    public class ClockWidget extends Canvas {
      private final Color color;
      private Color handColor;
      public Color getHandColor() {
        if (handColor == null) {
          return color;
        } else {
          return handColor;
        }
      }
      public void setHandColor(Color color) {
        handColor = color;
      }
      private void drawClock(PaintEvent e) {
        ...
        if (handColor == null) {
          e.gc.setBackground(color);
        } else {
          e.gc.setBackground(handColor);
        }
    ...
  9. Now the ClockWidget supports setting the handColor; the CSSPropertyClockHandler can be updated to set the color appropriately in the applyCSSProperty method:
    protected void applyCSSProperty(Control control, String property, CSSValue value, String pseudo, CSSEngine engine) throws Exception {
      if (control instanceof ClockWidget) {
        ClockWidget clock = (ClockWidget) control;
        switch (property) {
          case "clock-hand-color":
            Color handColor = (Color)engine.convert(value, Color.class, control.getDisplay());
            clock.setHandColor(handColor);
            break;
          }
        }
      }
    }
  10. The retrieveCSSProperty method can be implemented similarly:
    protected String retrieveCSSProperty(Control control, String property, String pseudo, CSSEngine engine) throws Exception {
      if (control instanceof ClockWidget) {
        ClockWidget clock = (ClockWidget) control;
        switch (property) {
          case "clock-hand-color":
            return engine.convert(clock.getHandColor(), Color.class, null);
        }
      }
      return null;
    }
  11. To allow the CSSPropertyHandler to style a ClockWidget, an org.eclipse.e4.ui.css.core.propertyHandler extension needs to be added to the plugin.xml. Open this file, switch to the Extensions tab, and click on the Add button. In the New Extension dialog, add the org.eclipse.e4.ui.css.core.propertyHandler extension and click on Finish.

    Tip

    If the extension doesn't show up in the list, unselect the Show only extension points from the required plug-ins checkbox and it should show up. Adding it will prompt the IDE to add the plug-in to the requirements when this happens.

  12. Right-click on the org.eclipse.e4.ui.css.core.propertyHandler extension and select New | handler, if one is not automatically created by the IDE. Right-click on the handler and select New | property-name if one is not automatically created by the IDE. Enter clock-hand-color as the name.
  13. Select the handler again, click on the Browse button by the handler field, and then select the CSSPropertyClockHandler class.

    Note

    To provide a bridge between the SWT widgets and the Eclipse 4 application, a shadow-dom like facade provides a representation of UI elements without a particular windowing library. This is achieved with a subclass of a ControlElement and an IElementProvider subclass.

  14. Create a new class ClockElement in the com.packtpub.e4.ui.internal.css package, which subclasses ControlElement, which passes the arguments to the super constructor:
    public class ClockElement extends ControlElement {
      public ClockElement(ClockWidget widget, CSSEngine engine) {
        super(widget, engine);
      }
    }
  15. To connect the ClockElement to the ClockWidget, an IElementProvider needs to be created. Create a class called ClockElementProvider that implements the IElementProvider interface, and implement the getElement method that returns a binding between the ClockWidget and the ClockElement:
    public class ClockElementProvider implements IElementProvider {
      public Element getElement(Object element, CSSEngine engine) {
        if (element instanceof ClockWidget) {
          return new ClockElement((ClockWidget) element, engine);
        }
        return null;
      }
    }

    Tip

    The Element comes from the org.w3c.dom package; there are several classes called Element in the Java libraries, so verify that the right one is used.

  16. Now that the ClockElementProvider class has been created, open the plugin.xml file and in the Extensions tab click on the handler underneath the propertyHandler node. Click on Browse next to the adapter field, and choose the ClockElementProvider to join them together.
  17. To define the provider properly, an elementProvider needs to be created. Click on the Add button in the Extensions tab, choose the org.eclipse.e4.ui.css.core.elementProvider extension, and click on Finish. Right-click on the elementProvider node and choose New | provider. In the provider, click on the Browse button next to the class and choose the ClockElementProvider. Expand the provider node and the widget child should be present. Click on the Browse button next to the class field and choose ClockWidget.
  18. The resulting plugin.xml should look like:
    <extension point="org.eclipse.e4.ui.css.core.propertyHandler">
      <handler composite="false"
       adapter="com.packtpub.e4.clock.ui.internal.css.ClockElement"
       handler="com.packtpub.e4.clock.ui.internal.css.CSSPropertyClockHandler">
        <property-name name="clock-hand-color"/>
      </handler>
    </extension>
    <extension point="org.eclipse.e4.ui.css.core.elementProvider">
      <provider class="com.packtpub.e4.clock.ui.internal.css.ClockElementProvider">
        <widget class="com.packtpub.e4.clock.ui.ClockWidget"/>
      </provider>
    </extension>
  19. Now modify the css/default.css stylesheet in the com.packtpub.e4.application, and add a rule to style the ClockWidget:
    ClockWidget {
      background-color: white;
      clock-hand-color: blue;
    }
  20. Run the application and verify that the color is set appropriately. Modify the CSS and re-run the application. Does the color of the hand change?

What just happened?

Eclipse 4 uses a shadow-dom like model for representing the user interface. The Widget hierarchy used by SWT has a parallel Element hierarchy that is used to represent the key aspects of the widget in use. This allows other rendering engines, such as JavaFX to display an Eclipse 4 user interface by simply modifying the presentation layer.

To bind this Element hierarchy to the Widget, the elementProvider extension is used. This defines a relationship between the SWT Widget (in this case, ClockWidget) and a corresponding Element object (in this case, ClockElement). The elementProvider typically wraps the underlying (Clock)Widget with a (Clock)Element, in the getElement method. The ClockElement needs to subclass ControlElement in order to inherit the standard SWT properties; if it does not, then properties such as background-color will not be applied.

Once this relationship has been defined, it is possible to associate an ICSSPropertyHandler with one or more property names to elements. A single property handler may provide support for multiple property-name definitions, or even support multiple classes. Each name must be added in the property-name element of the propertyHandler extension. For SWT widgets, the AbstractCSSPropertySWTHandler class is typically used as the parent class.

In order to convert CSS color names into SWT Color objects, the CSSEngine that is passed in as an argument can be used to dynamically cast objects into a target type with the convert method. For conversion from a String into an SWT Widget, the third parameter must be the SWT Display (typically from the control that was passed in); but for conversion the other way (from a Color to a String), the third parameter is not required.

Themes

Although a standalone product may have a default custom stylesheet, it is sometimes an advantage to allow the end user to customize the look and feel of the product, or to allow different styles of user interface to suit the user. This is the purpose of themes, which are available both in the Eclipse IDE and also in generated Eclipse 4 applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.38.142