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.
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.com.packtpub.e4.ui.internal.css
to store the classes necessary for CSS cooperation.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.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.control
argument to a ClockWidget
and store it in a local variable clock
.switch
block that uses the propertyName
to determine if it is clock-hand-color
. 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());
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); } ...
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; } } } }
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; }
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.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.CSSPropertyClockHandler
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); } }
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; } }
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.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
.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>
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; }
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.
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.
18.188.38.142