-
Notifications
You must be signed in to change notification settings - Fork 0
Development Guidelines
This guide provides instructions for building a new Tempo UI. Refer to the
example
folder in the main repo to follow along.
This guide assumes basic knowledge of DukeScript and the Remote Control feature described in Section 15.2 of the Overture User Guide.
The first step of TempoUI development is building an API for the UI to interact with the VDM model. The role of the Model API is to expose model functionality to the UI. We can provide an API for an existing model or define the API upfront and develop the model later. The latter option works well when developing the UI and model in parallel, provided everyone agrees on the API.
The ModelAPI
(or whatever else we want to call it) is a handwritten Java class of mostly static methods that exposes the VDM model operations that we want to trigger from the UI. This class is handwritten for two reasons:
- we only want to expose a subset of operation
- we may need to do encoding values from the UI into VDM values
In the future, we would like to generate this class from a configuration and automate the encoding. But for now, it's manual. To expose a VDM operation named foo
, use something like:
public static void foo(RemoteInterpreter ri) throws Exception {
interpreter.execute(ROOT_NAME + ".bar()");
}
As you can see, the ModelAPI
and VDM names don't have to match. Also, the ModelAPI
methods are all static and the class itself has a static reference to the interpreter
that is being controlled with the UI. The methods must be static in order to be accessed from the UI. The interpreter reference is needed to execute the VDM operations.
The VDM model itself has no static class restrictions but we will need to store the names of any VDM objects we want to call operations on. The easiest thing to do is to only cal operations on the top-level VDM object -- what roughly corresponds to the entry point. The name of this object can then be easily stored in a constant. Also, remember that there is no checking on the VDM strings that we submit to the interpreter so be careful.
Once we have the ModelAPI
in place, we can build the View Model for the UI. This is a Java class that DukeScript binds to the UI using the Knockout library. This class is typically called some variation of Data Model (ex: CustomerModel
) but should never be confused with the VDM model. In this guide we always refer to it as ViewModel
The ViewModel
is defined through annotations and code generation provided by DukeScript. When defining the ViewModel
, we need to use operations from the ModelAPI
and also declare properties to hold any VDM variables that we want to bind to the UI. Properties may be strings, enums, primitives or other classes generated as View Models. If we want to bind a property in the ViewModel
to a VDM variable, then their names must match.
For example, the following snippet defines a basic ViewModel
with a single property (ok
). Later on, this property will be bound to a VDM variable of the same name.
@Model(className = "VdmData", targetId="",properties = {
@Property(name = "ok", type = boolean.class),
})
final class UiModelData {
}
In order to expose methods to the UI, we use the @Function annotation
. The annotated method must be static. The generated data class (VdmData
in this case) is always passed as a parameter.
@Function
static void foo(VdmData vdm) throws Exception {
ModelAPI.foo();
}
Tempo UIs are built with HTML5 and JavaScript. We will not discuss how to build the UI except to say that we can use any standard HTML5 technology when building the UI. In addition, the UI can be designed and developed independently from the model.
For connecting the UI to model, the Maven archetype will have created a file src/main/webapp/pages/index.html
. This is the page that is loaded in the browser when the model is launched. The UI must start from this page.
The HTML5 UI elements are bound to the ViewModel
properties using Knockout. Refer to the Knockout documentation (http://knockoutjs.com/documentation/introduction.html) for information on what kinds of bindings are available.
As an example, here is a trivial HTML snippet that binds a status message to the ok
property:
<p>
Status is: <em data-bind="if: ok"style="color:green">Ok</em> <em data-bind="if: !ok"style="color:red">Not Ok</em>
</p>
When launched, this UI would look something like:
Once the underlying VDM variable changes the false, the UI will automatically update to reflect this.
In regular DukeScript applications, the application logic is a "plain" Java application. In the TempoUI, the application logic is a VDM Model wrapped in a Remote Control class, as described in section 15.2 of the Overture user guide. Each TempoUI project must provide its own Remote Control class that subclasses
TempoRemoteControl
.
The remote control class is also responsible for connecting the
VDM Model and the ViewModel
. This is done in a public static void method named
onPageLoad()
. This method handles the final stages of connecting the UI to
the VDM model.
Broadly speaking, onPageLoad
must do the following:
- connect to the interpreter
- initialise the
ViewModel
- construct a list of VDM model variables to be bound to
ViewModel
variables - attach UI binding listeners to those variables (TempoUI provides classes to do this).
The snippet below shows a sample page loader method.
public static void onPageLoad() throws Exception {
// Connect UI to Model Interpreter
ModelAPI.setInterpreter(interpreter);
// Create ViewModel and bind it to the UI
VdmData uiData = new VdmData();
uiData.applyBindings();
// Acquire top-level value
String root = "foo";
String rootConstructor = "new Foo()";
interpreter.create(root, rootConstructor);
Value v = interpreter.valueExecute(root);
// Create list of VDM variables to bind
List<ListenerAttacher.VarBindInfo> vars = new ArrayList<>(1);
vars.add(ListenerAttacher.VarBindInfo.create("ok", new ABooleanBasicType()));
// Attach listeners to notify ViewModel of variable changes
ModelBinder mb = new ModelBinder(v, vars, uiData);
mb.bind();
}
And that's it!