This section introduces an example of how to define and reuse Spec user interfaces. The example UI that is built will serve to browse the public API of all the basic widgets offered by Spec. This API is further documented in the page Where to find what I want. In this section we do not detail the different parts of Spec yet, for a more in-depth discussion on the heart of Spec we refer to Instantiating sub widgets and Defining the layout.
The example is structured in four parts. First, a list UI named ModelList that is dedicated to render the subclasses of the AbstractWidgetModel class is created. Second, a UI composed of a list and a label is defined and named ProtocolList. Third, a protocol viewer is defined by combining a ModelList with two ProtocolList to browse the protocol and protocol-events methods. Finally a protocol browser is made by reusing a protocol viewer and adding a text zone.
Creating a specific UI always starts with the subclassing of ComposableModel. Each sub widget is stored into an instance variable of the newly created class. The following snippet shows the definition of this ModelList class.
The first required step then is to instantiate and define the sub widgets.
This step is done in the method
initializeWidgets as shown in the following code. It creates the list and populates it with the required classes, in alphabetical order.
More details on the use of the
initializeWidgets method are given here.
The second required step is to define a layout, which is done on the class side. Since there is here only one sub widget, the layout is quite simple, as shown in the following code. It simply returns a layout that contains only the list. More details on the use of this method are given here.
The three last methods to define on ModelList are a getter, a method to display the UI title and a method to register to list selection changes. This code shows the implementation of these three methods and their protocols:
The first UI is now done.
The result can be seen by executing the following snippet of code:
ModelList new openWithSpec.
The next user interface is the protocol list. This UI combines two sub widgets: a list and a label. The class definition is similar to the code above:
initializeWidgets method for this UI is quite similar to the method in ModelList:
The layout method is quite different though. Now the sub widgets need to be placed more specifically than in the previous example. The following code shows how to build a column with the label on top and the list taking all the space that is left.
The remaining methods are getters, sub widget delegation methods, a method to display the title, and a method to register to list selection changes. The following code shows the implementations of these methods as well as their protocol.
ProtocolList UI can be seen by evaluating
ProtocolList new openWithSpec.
The third user interface is a composition of the two previous user interfaces. It is composed of a ModelList and two ProtocolList. When a model class is selected, the methods in the protocol protocol and in the protocol protocol-events are listed.
The class has now three instance variables:
models to store the
protocols to store the
ProtocolList for the protocol
events to store the
ProtocolList for protocol
The following code in shows the definition of the class
initializeWidgets method now uses a different way to initialize the sub-widgets of the UI.
This is because it does not use basic widgets but instead reuses the user interfaces we defines previously.
The remainder of the method is quite similar to the previous implementation:
The layout puts the sub widgets in one column, with all sub widgets taking the same amount of space. The implementation of this layout is:
To describe the interactions between the sub widgets, the method
initializePresenter needs to be defined.
Here, it specifies that when a class is selected, the selections in the protocol list are reset and both protocol lists are populated.
Additionally, when a method is selected in one protocol list, the selection in the other list is reset.
The implementation of this method is exposed in the following code.
More details on the
initializePresenter method are given in
Sub widgets interaction.
The remaining methods are getters, methods to delegate to sub widgets, one method to compute the methods in a specific class for a specific protocol, and methods to register to sub widget events. Those methods are given in this code:
As previously, the result can be seen by executing the following snippet of code:
ProtocolViewer new openWithSpec.
The last user interface reuses a ProtocolViewer with a different layout and adds a text zone to edit the source code of the selected method. The class definition is:
initializeWidgets implementation is shown in the code:
The layout is more complex than the previous layouts.
Now the user interface mainly lays out widgets that are contained in its
viewer sub widget (the list of models and the two protocol browsers).
The layout is based on a column whose first row is divided in columns.
The implementation of this method is shown in the following code:
initalizePresenter method is used to make the text zone react to a selection in the lists.
When a method is seleted, the text zone updates its contents to show the source code of the selected method.
The implementation of this method is detailled in the following code.
The other methods are two getters, a method to set the default size, and a method to set the UI title. Their implemenations are detailled in:
This finishes the protocol browser.
The final user interface can be opened with the following snippet:
ProtocolBrowser new openWithSpec.
The result can be seen in figure