Skip to content

UI Handler GUI Swing (LAF Packages)

Carsten Stocklöw edited this page May 1, 2018 · 4 revisions

Table of Contents

Building new LAFs

In this page you will find information on how to implement your own Look and Feel (LAF for short) packages for the gui swing handler.

Handler Model

The handler design is based on this paper an we will use terminology explained there to focus on how to implement LAFs. It is also recommended to have the javadoc opened along with this page.

The Mapping of this design to the actual implementation is as follows:

  • Main Hub(MH) -> Renderer
  • View Mapper (VM) -> ModelMapper
  • Meta Model Component -> the instance of FormControl, Form or Label received through the bus
  • Container Management Unit -> any instance of FormManager
  • Container View -> FormModel (and FormLAF); as well as GroupModel (and GroupLAF)
  • Element View -> all included inside Package org.universAAL.ui.handler.gui.swing.model.FormControl and org.universAAL.ui.handler.gui.swing.defaultLookAndFeel packages.
As you may have noticed view components are divided in two, the fist part the "Model" defines the behavioural part of the view, and the second part is the LAF; hence the Model and LAF postfixes in the classes.

Note that the Model part will define for example the text to be displayed in a text field, and the translation back to uAAL UI bus; but will not play with any visual parameter. Tweaking the visual parameters (such as colour or layout) is responsibility of the LAF component which will under no circumstances change the content (or behaviour) imposed by the Model.

Therefore you will find a Model and a LAF class per each FormControl, Form and Label. LAF class is always a subclass of the Model class, inheriting this way the behaviour from the model as well as useful methods.

The VM (ModelMapper) will locate the LAF class corresponding for each FormControl, Form or Label using Java Reflection. It will look inside the configured (or default) java package for the class that is called LAF, where is the name of the UIModel class (for example Form will be mapped to FormLAF, and Range to RangeLAF. If a LAF class is not found then the defaultLAF will be used; if then defaultLAF does not exist either, then the VM will search for the LAF class corresponding to the parent UIModel class. This mechanism allows to manage UIModel extensions both managed extensions (by finding the extended LAF class) and not managed extensions (by using the next best "compatible" thing, i.e: the LAF class for the nearest existent antecessor of the UIModel class requested).

FormControls, Forms and Labels are treated very similar, but they do have differences.

FormControl's models implement the Model abstract class but usually don't completes it, leaving open the update() to be overridden. The workflow for these models is getComponent() is called, if there isn't a JComponent already created then it creates it calling getNewComponent() then the component is updated calling the update() method. getNewComponent() may be overridden by the LAF class but it has to "register it" by calling first the parent method. Note not all FormControlls map to just one JComponent, this is why update() method should check for the type of the JComponent (or type of FormControl) to act accordingly.

Form's LAFs just have to implement the methods getFrame() and terminateDialog(), the suggested way to implement the construction of this JFrame is to deal with JPanels (one per each main area, and available through the FormModel getXPanel() methods) tweaking them and arranging them in the desired way.

Label's LAFs will just give the font and colours to the JLabel component.

This design helps focusing on one component at a time, the trick is to develop each LAF class as subclass of their respective Model class, a clean LAF package will render (just a standard Metal Swing look and feel).

A LAF package Has to contain LAF classes (it is recommended to have at least for the standard UIModel), an Init class is mandatory. Init implements InitInterface which have a install() [and,] method. This method is used to initialize the LAF, and it is the first thing called, and only once the LAF is loaded. The LAF package may contain helper classes, it is recommended to locate these in an inner Java package to avoid the Mapper confusing them with actual LAF classes.

Always from either a Model or LAF class you can call the getRenderer() method, this object gives access to the Handler's context and user's preferences/impariments, as well as configuration parameters, and constants. This way you can implement a true context aware LAF! In the future this method will also give access to the uiPreferencesProfile or even the LAFProfile enabling true fine tuning by the user. Please look at the javadoc to find the useful methods provided by Renderer, Model, FormModel, and LabelModel.

Using a LAF different than defaultLAF

To use your LAF package, remember to include the jar library (in maven reference) in the run configuration after installing or deploying it with maven.

Also edit the LookandFeel.package property to point to the desired package.

LAF creation Methods

To create your new LAF we strongly recommend to read the UI Guidelines published in D4.1C, Part III and available in User Interaction Guidelines for AAL Services

LAF packages consist in a java library, in a JAR file (they aren't bundles).

If there are any resources needed, such as images or sounds, they should be embedded in the generated Jar file. To do this just inclide the files in the src/main/resources folder, maven will encapsulate them for you. To access such resources use the following snippet:

 getClass().getResource("<file>");
where <file> is the route to the file with root in src/main/resources.

Extending the defaultLAF method

To create your own Look and feel (LAF) package, you may at first whant to tweak a bit the default LAF, whether it's just the colours or the layout. To do so it is best recommended to create your own package extending the defaultLAF, for each class in the defaultLAF create a new class that extends the original LAF class instead of the Model class. Then implement/override the original methods (still recomendend to call parent methods before doing anything) with your idea of LAF.

From scratch method

Shall your LAF package require radical changes of the defaultLAF, then it is recommended to create your own package.

Start by creating a project based on the following archetype: org.universAAL.ui.gui.swing/defaultBasedLAF-archetype/1.2.0 .

This new project will contain all needed classes for the LAF package, and these classes will produce a LAF exactly the same as the default package.

Edit at will, to create your LAF.

Building new UI Model extensions

Note: content here will be added in next version