Tuesday, March 29, 2011

A New Way To LWUIT



LWUIT had a MIDP bias. It started as a MIDP project so it is perfectly understandable, however moving forward to support RIM and other platforms (e.g. Thorsten's great work) we wanted to completely disconnect LWUIT from its platform specific roots and offer some great new features in the process.
It started off when we generated projects for the GUI builder, but we decided to take this further into the LWUIT Demo and make that approach into our project structure recommendation. You can checkout the source code for the new LWUIT Demo from SVN to see the actual structure.

Basically what we are doing is placing all the LWUIT portable code into a MIDP shared library, this is effectively the common code for the project. Here we also place the common resources used within all the different ports.
Underneath this project (mostly for convenience not due to necessity) we place subprojects that depend on that parent project and are platform specific. That way we don't need a pre-processor or any similar tool to gain both portability and the ability to utilize platform specific features when we want to do so.

The really cool feature hidden beneath this is the ability to utilize the JavaSE port to run the application. Besides running practically instantly (no simulator!), the biggest hit is the ability to use Java SE level development tools!
Edit & continue, profilers, threadalizers, memory monitors etc. Its a whole different scale of debugging for business logic (assuming the issue reproduces on the SE port). Besides debugging this feature allows you to embed your application as an Applet right into a web page to provide users with a live preview of your application! How cool is that!

To your right you can (hopefully) see a running Applet containing the current version of the LWUIT demo. You can use escape as a back button, F1 as the menu button and the arrow keys/mouse to navigate within this Applet.

Tuesday, March 22, 2011

FYI About the videos I've been uploading

I'm currently in the midst of making major usability UI improvements to the resource editor which already changed quite allot since I started making the screencasting videos of it. I also discovered http://www.screencast-o-matic.com/ which seems to be exactly what I needed and is written in Java!

As a result of all of these I decided to complete the changes for the upcoming resource editor version and "reboot" the video tutorial with better planning for my goals. I'll keep the existing videos online for reference but will start making a far improved tutorial in a short while. One of the biggest blockers for me is actually finding some quite time to record, not a moment of quiet for the wary...

Monday, March 21, 2011

List Rendering: The Easy Way. Generic List Cell Renderer

LWUIT is really powerful and flexible, we took the power and flexibility of Swing and went even further (styles, painters) and one such power is the cell renderer. This is a concept we derived from Swing which is both remarkably powerful and pretty hard for newbies to figure out, frankly its pretty hard for everyone...
As part of the GUI builder work we needed a way to customize rendering for a List but the renderer/model approach seemed impossible to adapt to a GUI builder (it seems the Swing GUI builders had a similar issue). Our solution was to introduce the GenericListCellRenderer which while introducing limitations and implementation requirements still manages to make life easier both in the GUI builder and outside of it.

A small refresher of the LWUIT List MVC approach for those who haven't read the links above:
A LWUIT list doesn't contain components but rather arbitrary data, this seems odd at first but makes perfect sense... If you want a list to contain components just use a Container.
The advantage of using a List in this way is that we can display it in many ways (e.g. fixed focus positions, horizontally etc.) and that we can have more than a million entries without performance overhead. We can also do some pretty nifty things like filter the list on the fly or fetch it dynamically from the internet as the user scrolls down the list.
To achieve these things the list uses two interfaces: ListModel and ListCellRenderer.
List model represents the data, its responsibility is to return the arbitrary object within the list at a given offset. Its second responsibility is to notify the list when the data changes so the list can refresh, think of it as an array of objects that can notify you when you get changes.
The list renderer is like a rubber stamp that knows how to draw an object from the model, its called many times per entry in an animated list and must be very fast. Unlike standard LWUIT components it is only used to draw the entry in the model and immediately discarded hence it has no memory overhead but if it takes too long to process a model value it can be a big bottleneck!
This is all very generic but a bit too much for most, doing a list "properly" requires some understanding. The main source of confusion for developers is the stateless nature of the list and transferal of state to the model (e.g. a checkbox list needs to listen to action events on the list and update the model in order for the renderer to display that state... Once you understand that its easy).

GenericListCellRenderer is a renderer designed to be as simple to use as a Component-Container hierarchy, we effectively crammed most of the common renderer use cases into one class. To enable that we need to know the content of the objects within the model, so the GenericListCellRenderer assumes the model contains only Hashtable objects. Since Hashtable's can contain arbitrary data the list model is still quite generic and allows storing application specific data, furthermore a Hashtable can still be derived and extended to provide domain specific business logic.
The GenericListCellRenderer accepts two container instances (more later on why at least two and not one) which it maps to individual Hashtable entries within the model by finding the appropriate components within the given container hierarchy. Components are mapped to the Hashtable entries based on the name property of the component (get/setName) and the key value within the Hashtable e.g.:
For a model that contains a Hashtable entry like this:
"Foo": "Bar"
"X": "Y"
"Not": "Applicable"
"Number": Integer(1)

A renderer will loop over the component hierarchy in the container searching for component's whose name matches Foo, X, Not and Number and assign to them the appropriate value. Notice that you can also use image objects as values and they will be assigned to labels as expected. However, you can't assign both an image and a text to a single label since the key will be taken. That isn't a big problem since two labels can be used quite easily in such a renderer.
To make matters even more attractive the renderer seamlessly supports list tickering when appropriate and if a CheckBox appears within the renderer it will toggle a boolean flag within the Hashtable seamlessly.
One  issue that crops up with this approach is that if a value is missing from the hashtable it is treated as empty and the component is reset, this can pose an issue if we hardcode an image or text within the renderer and we don't want them replace (e.g. an arrow graphic). The solution for this is to name the component with Fixed in the end of the name e.g.: HardcodedIconFixed.
Naming a component within the renderer with $number will automatically set it as a counter component for the offset of the component within the list.

Styling the GenericListCellRenderer is slightly different, the renderer uses the UIID of the container passed to the generic list cell renderer and the background focus uses that same UIID with the word "Focus" appended.
It is important to notice that the generic list cell renderer will grant focus to the child components of the selected entry if they are focusable thus changing the style of said entries. E.g. a Container might have a child label that has one style when the parent container is unselected and another when its selected (focused), this can be easily achieved by defining the label as focusable. Notice that the component will never receive direct focus since it is still a par of a renderer.

Last but not least, the generic list cell renderer accepts two or four instances of a Container rather than the obvious choice of accepting only one instance. This allows the renderer to treat the selected entry differently which is especially important to tickering although its also useful for fisheye. Since it might not be practical to seamlessly clone the Container for the renderer's needs LWUIT expects the developer to provide two separate instances, they can be identical in all respects but they must be separate instances for tickering to work. The renderer also allows for a fisheye effect where the selected entry is actually different from the unselected entry in its structure, it also allows for a pinstripe effect where odd/even rows have different styles (this is accomplished by providing 4 instances of the containers selected/unselected for odd/even).

The best way to learn about the generic list cell renderer and the hashtable model is by playing with them in the GUI builder, however they can be used in code without any dependency on the GUI builder and can be quite useful at that.

Here is a simple sample for a list with checkboxes that get updated automatically:

List list = new List(createGenericListCellRendererModelData());
list.setRenderer(new GenericListCellRenderer(createGenericRendererContainer(), createGenericRendererContainer()));


private Container createGenericRendererContainer() {
Container c = new Container(new BorderLayout());
c.setUIID("ListRenderer");
Label name = new Label();
name.setFocusable(true);
name.setName("Name");
c.addComponent(BorderLayout.CENTER, name);
Label surname = new Label();
surname.setFocusable(true);
surname.setName("Surname");
c.addComponent(BorderLayout.SOUTH, surname);
CheckBox selected = new CheckBox();
selected.setName("Selected");
selected.setFocusable(true);
c.addComponent(BorderLayout.WEST, selected);
return c;
}

private Hashtable[] createGenericListCellRendererModelData() {
Hashtable[] data = new Hashtable[5];
data[0] = new Hashtable();
data[0].put("Name", "Shai");
data[0].put("Surname", "Almog");
data[0].put("Selected", Boolean.TRUE);
data[1] = new Hashtable();
data[1].put("Name", "Chen");
data[1].put("Surname", "Fishbein");
data[1].put("Selected", Boolean.TRUE);
data[2] = new Hashtable();
data[2].put("Name", "Ofir");
data[2].put("Surname", "Leitner");
data[3] = new Hashtable();
data[3].put("Name", "Yaniv");
data[3].put("Surname", "Vakarat");
data[4] = new Hashtable();
data[4].put("Name", "Meirav");
data[4].put("Surname", "Nachmanovitch");
return data;
}

Thursday, March 17, 2011

Constantly Theme'd

One of the often requested features in LWUIT's themes has been the addition of constants for themes. Constants allow the theme designer to "hint" of desired functionality to the application code, e.g. a particular theme might have a constant indicating that it wants the scrollbar to fadeout when unused.
The LWUIT resource editor now includes an additional tab for creating such constants which can be used to add constant values. These can be added in the ant task by prepending the @ sign before the constant key in the theme and setting the value to the appropriate string.
Constants are always strings, they have some conventions where a constant ending with Bool is treated as a boolean true/false value and a constant ending with Int or Image (for image the string name of the image is stored but the image instance will be returned).

To use a constant one can use the UIManager's methods to get the appropriate constant type specifically:
getThemeConstant
isThemeConstant
getThemeImageConstant

Internally LWUIT has several builtin constants and the list is constantly growing as we add features to LWUIT, we will try to keep this list up to date when possible.



.
LWUIT ConstantDescription
.
centeredPopupBoolPopup of the combo box will appear in the center of the screen
.
checkBoxCheckDisImageCheckBox image to use instead of LWUIT drawing it on its own
.
checkBoxCheckedImageCheckBox image to use instead of LWUIT drawing it on its own
.
checkBoxUncheckDisImageCheckBox image to use instead of LWUIT drawing it on its own
.
checkBoxUncheckedImageCheckBox image to use instead of LWUIT drawing it on its own
.
comboImageCombo image to use instead of LWUIT drawing it on its own
.
commandBehaviorIndicates how commands should act, as a touch menu, native menu etc. Possible values: SoftKey, Touch, Bar, Title, Right, Native
.
defaultCommandImageImage to give a command with no icon
.
dialogButtonCommandsBoolPlace commands in the dialogs as buttons
.
dialogPositionPlace the dialog in an arbitrary border layout position (e.g. North, South, Center etc.)
.
dialogTransitionInDefault transition for dialog
.
dialogTransitionInImageDefault transition Image for dialog, causes a Timeline transition effect
.
dialogTransitionOutDefault transition for dialog
.
dialogTransitionOutImageDefault transition Image for dialog, causes a Timeline transition effect
.
disabledColorColor to use when disabling entries by default
.
dlgCommandButtonSizeIntMinimum size to give to command buttons in the dialog
.
dlgSlideDirectionSlide hints
.
dlgSlideInDirBoolSlide hints
.
dlgSlideOutDirBoolSlide hints



.
fadeScrollBarBoolFade transition hints
.
fadeScrollEdgeBoolFade transition hints
.
fadeScrollEdgeIntFade transition hints
.
firstCharRTLBoolIndicates the GenericListCellRenderer should determine RTL status based on the first character in the sentence
.
fixedSelectionIntNumber corresponding to the fixed selection constants in List
.
formTransitionInDefault transition for form
.
formTransitionInImageDefault transition Image for form, causes a Timeline transition effect
.
formTransitionOutDefault transition for form
.
formTransitionOutImageDefault transition Image for form, causes a Timeline transition effect
.
hideEmptyTitleBoolIndicates that a title with no content should be hidden even if the border for the title occupies space
.
ignorListFocusBoolHide the focus component of the list when the list doesn't have focus
.
listItemGapIntBuiltin item gap in the list, this defaults to 2 which predated padding/margin in LWUIT
.
menuHeightPercentAllows positioning and sizing the menu
.
menuPrefSizeBoolAllows positioning and sizing the menu
.
menuSlideDirectionDefines menu entrance effect
.
menuSlideInDirBoolDefines menu entrance effect
.
menuSlideOutDirBoolDefines menu entrance effect
.
menuTransitionInDefines menu entrance effect
.
menuTransitionInImageDefines menu entrance effect
.
menuTransitionOutDefines menu entrance effect



.
menuTransitionOutImageDefines menu entrance effect
.
menuWidthPercentAllows positioning and sizing the menu
.
otherPopupRendererBoolIndicates that a separate renderer UIID/instance should be used to the list within the combo box popup
.
popupCancelBodyBoolIndicates that a cancel button should appear within the combo box popup
.
popupTitleBoolIndicates that a title should appear within the combo box popup
.
pureTouchBoolIndicates the pure touch mode
.
radioSelectedDisImageRadio button image
.
radioSelectedImageRadio button image
.
radioUnselectedDisImageRadio button image
.
radioUnselectedImageRadio button image
.
rendererShowsNumbersBoolIndicates whether renderers should render the entry number
.
reverseSoftButtonsBoolSwaps the softbutton positions
.
slideDirectionDefault slide transition settings
.
slideInDirBoolDefault slide transition settings
.
slideOutDirBoolDefault slide transition settings
.
snapGridBoolSnap to grid toggle
.
tabsFillRowsBoolIndicates if the tabs should fill the row using flow layout
.
tabsGridBoolIndicates whether tabs should use a grid layout thus forcing all tabs to have identical sizes
.
tickerSpeedIntThe speed of label/button etc. tickering in ms.
.
tintColorThe aarrggbb hex color to tint the screen when a dialog is shown



.
touchCommandFillBoolIndicates how the touch menu should layout the commands within
.
touchCommandFlowBoolIndicates how the touch menu should layout the commands within
.
touchMenuBoolForce the touch menu
.
transitionSpeedIntIndicates the default speed for transitions

One "odd" behavior of constants is that once they are set by a theme they don't get "lost" when replacing the theme. E.g. if one would set the comboImage constant to a specific value in theme A and then switch to theme B that doesn't define the comboImage, the original theme A comboImage might remain. The reason for this is simple, when extracting the constant values components keep the values in cache locally and just don't track the change in value. Furthermore, since the components allow manually setting values its impractical for them to track whether a value was set by a constant or explicitly by the user.
The solution for this is to either manually reset undesired values before replacing a theme (e.g. for the case above by calling the default look and feel method for setting the combo image with a null value) or defining a constant value to replace the existing value.

BTW I haven't been blogging or posting videos as often as I should both because I have been a bit under the weather and because I have been quite swamped with work (checkout the SVN changes). Hopefully I'll feel a bit better next week and increase my blogging a bit.

Monday, March 7, 2011

New Project Hierarchy For LWUIT

I haven't posted in a short while because we have some big things coming for LWUIT, I just committed a major restructuring of the LWUIT workspace which essentially moved everything around to more sensible locations. We made a tag just before the move so if you have hard dependencies on the old LWUIT workspace structure you can use that tag.
The new structure makes more sense for LWUIT ports since it removes all the none cross platform (MIDP specific code) from LWUIT and moves it entirely to the ports directory. This allows LWUIT to treat all ports to all platforms on even grounds and simplify the build process for such ports. In the past allot of things such as applications and LWUIT4IO were located under MIDP which made no sense at all (other than historic sense), so now we have two portable projects: UI & IO. Which are actually useless on their own.
You need to pick the specific project for your platform to link against from the ports folder where we have both an IO and a UI project for every supported platform.