Theming custom components
So far our theme file has specified attributes for the standard components supported by the library. It is possible to use theming for custom components too. To try this out, we shall use the TimeTeller component. The two interfaces and the two classes that together make up that component have been put into a package named book.newcomp to make the code better organized. A timeteller is added to the form by uncommenting the relevant statements shown in the MIDlet code snippet listed earlier in this article. However, note that we have not set any style for the timeteller instance.
Without any entry for TimeTeller in the theme file, the screen looks similar to the following screenshot:
We can see that the two labels of the timeteller are properly styled, while the overall component background has the default color. This happens because the labels have been explicitly styled through code while creating the timeteller. If you experiment with the theme file, then you will see that it is not possible to affect the styles of the TimeViewer part of the component through the file. This can be explained when we consider how theming works. When the setThemeProps method is executed, the UIManager instance transfers values from the theme file into respective style objects by using the UIID of a component as the key. Obviously, if a component does not have its own UIID, its style cannot be set through the theme. The TimeViewer class has not been allocated a UIID and that is why it will not be affected by any entry in the theme file. TimeTeller, on the other hand, does have a UIID, and we can therefore set its attributes through the theme file. In order to do that, we click on the Add button to get the Add dialog. In the Component field, we type in TimeTeller and set bgColor following the usual procedure.
A click on the OK button enters the value in the theme. The following screenshot shows three entries for TimeTeller:
The result of setting these attributes can be seen in the following screenshot:
Manual styling versus theming
We know that an attribute can be set for a specific widget by using a settermethod of theStyleclass. Let's take a concrete example. In our demo MIDlet, we have manually set background colors for the two labels of the timeteller. We have also defined a different set of background colors for labels in general through the theme. We need to understand which setting takes precedence when conflicting attributes are set in this way.
The API documentation tells us that there are two types of methods for setting attributes. For setting background colors, the methods are setBgColor(int bgColor) and setBgColor(int bgColor, boolean override). If the first method is used to manually set the background color of a widget, then a theme file entry will not be effective for that particular component instance. However, all other instances of the same component will be styled as per the theme file, provided manual styling using the same method has not been done. In this case, we have used the setBgColor(int bgColor) method to set background colors for the two labels within the timeteller. Therefore, the theme file has no effect on these two labels, although it does determine the corresponding color for the other label on the form. On the other hand, when the setBgColor(int bgColor, boolean override) method is used and the Boolean parameter is true, theme settings will override any manual styling.
There is another way to allow a theme to override manually set style attributes. If we create a new style object and pass all the options in the constructor, then setting a theme file will change the attributes of such a style object.
Theming on the fly
One feature of theming that we have not talked about so far is that it is possible to change themes at runtime by using the setThemeProps method of UIManager. But when a theme is set on the fly there will be, in general, components that are not visible, and the effect of setting a theme on these components is not predictable. In order to make sure that even the components that are not visible have their styles properly updated, you should call the refreshTheme method using code like this:
When a theme is installed at runtime, there may be form instances that have been created earlier and are to be displayed later. In order that the newly installed theme may take effect on these forms too, it is necessary to call refreshTheme on all such forms before they are shown on screen. For forms that are created after the theme is set, no such action is required, as the respective style objects will be initialized to the theme settings. In the current example, demoForm was instantiated after the theme was installed, and accordingly, refreshTheme was not invoked.
New version of the LWUIT Designer
The example in this article has been developed on the SWTK and the LWUIT Designer (Resource Editor) that comes with it. This is very convenient, as the resource bundle can be opened for viewing and editing from the SWTK console. The LWUIT download bundle also includes an LWUIT Designer, which offers some additional capabilities. In this section, we shall examine this version and see what is different about it.
The first impression we get from the next screenshot is that of a totally different look. We then realize that it also has the new name on the title bar.
However, the really significant difference is that this version of the LWUIT Designer supports a much wider variety of components and also an additional attribute. Some of the additions to the list of supported components are as follows:
The additional attribute that has been included is border. We shall use this edition of LWUIT Designer to add a border to the button in our demo. We will click on the Add button on the panel that shows the theme listing. We then select Button from the list of components and border from the drop-down attribute list on the Add dialog.
The browse button next to the Border field opens a dialog for specifying the kind of border we want.
Here we have selected a line border and have checked the box that will use the color scheme from the theme for the border. The resulting border for the button (An ordinary Button) is shown in the following screenshot:
Word of caution: When you create or modify a theme file using the new versions of LWUIT Designer, you may not be able to open the file through the version that comes with the SWTK. However, you will still be able to run the application on the SWTK, and the new or modified theme will work properly.
The steps we followed during our exploration of this topic are:
- A custom component was themed
- We saw how to make theming and manual styling work together without contentions
- A second version of LWUIT Designer was also tried out
Theming is one of the radically new functionalities available on the LWUIT as compared to the javax.microedition.lcdui package and allows the use of application-specific look and feel that is also independent of the native platform. So, complete familiarity with theming is very important for effective application development using LWUIT.