Riena application can provide and use its own ridgets (see issue #259937). This feature is meant for situations where a specific ridget (and corresponding widget) is not already present in Riena. To support a new custom ridget the following has to be done:
- For the widget, create a ridget class implementing as minimum interface IRidget (many examples for ridgets can be found in Riena, i.e. all subclasses of IRidget).
- — Comments by Elias: The default starting point would be extending AbstractRidget. However it will be easier to extend AbstractSWTRidget or AbstractValueRidget - even though they are internal. I believe in the long run, we may have to make them API to make implementing new Ridgets easier. Please provide feedback on the mailing list or newsgroup.
- Furthermore, a mapping from the widget class to the ridget class must be provided to create the corresponding ridget of a widget from the view for the controller at runtime. This is done by adding the desired mapping to the existing mappings of singleton SwtControlRidgetMapper using the following API methods:
- .addMapping(CustomWidget.class, CustomRidget.class)
- .addMapping(CustomWidget.class, CustomRidget.class, swtStyle)
- .addMapping(CustomWidget.class, CustomRidget.class, new CustomMappingCondition())
- For more details look at the JavaDoc of class SwtControlRidgetMapper. The mapping may be added in the custom application's activator for use in that application afterwards. Custom ridgets can be provided for all SWT widgets. For example, ridgets may be built for widgets from Nebula. Their usage is demonstrated in the Snippets.
Ridget Design Principles
To better understand the existing code and some challenges involved when writing a ridget, here are some design principles we follow. This applies to all IValueRidget/AbstractValueRidget implementations.
Values and Bindings
- There are three values: value of the model, value in the ridget, value in the widget.
- When invoking bindToModel(...), the value of the model is bound to the value of the ridget. The value in the ridget is not changed when binding until ridget#updateFromModel is invoked (see below).
- Update from ridget to model is automatic. Update from model to ridget happens on request (ridget#updateFromModel())
- When a control is bound to the ridget (ridget#setUIControl(...) invoked by the framework), the value of the ridget is copied into the control. From that point the value of the control is bound to the value in the ridget. Update in both directions (ridget to control, control to ridget) is automatic.
Ridgets and Controls
- Ridgets do not require a control (=widget) to work correctly.
- Ridgets initially have no control (i.e. getUIControl() returns null).
- When invoking ridget setters that may affect the control (example setVisibile(...)), the state must be stored in the ridget. The state is applied to the control immediately (if a control is available) or later (when a control is introduced via setUIControl(...))
- A ridget can be unbound from a control (i.e. ridget#setUIControl(null)) or bound to a different control (i.e. ridget#setUIControl(otherControl)). In both cases listeners / bindings to the original control must be cleaned up. After this method returns, the ridget should not modify the original control anymore.
A ridget should be provided as an interface. Then it is possible to access it through that interface in the controller.