The LWUIT Blog

Thursday, May 3, 2012

We have an important notice for you. As of May 3rd, we are removing the BlackBerry port and BlackBerry support code from LWUIT's main source trunk and binary file.

We tried hard to resolve third-party licensing issues related to the port, but after months without progress we decided to remove the BlackBerry port from the main trunk and relocate it in LWUIT's incubator source trunk.

Note: We will update you when the BlackBerry port is live.

Here are the details.

1. We are removing the directory Ports/RIM and its subfolders. The subfolder includes IO_RIM and UI_RIM, which contains the following files.

Monday, December 12, 2011

I was looking at the presentation from Eric Burke about the work square did with Android which resulted in a really nice UI. He tells about quite a few struggles they had with the Android API which seem to be pretty easy to get around in LWUIT.Anyway, one of the nicest things they did was the screenshot on the right which features a leather texture with stitches as the UI for the application which is a really nice touch for a wallet application (assuming you aren't a vegan).Anyway, that took me back a bit... How do you make a UI like that regardless of the platform that will look nice for all resolutions. I came up with the answer but because I suck at Photoshop I wasn't able to achieve anything remotely close to the image on the right... This just goes to show you how valuable professional design can be to a team.The way to produce an image like that is start with a clean tileable leather texture such as this one which I got from here and scaled down:

I set this as the style of the Form UIID and made it TILE on both axis's. Then I created a simple transparent gradient image, its so transparent you might not even see it but its very important to create the texturized depth to the image above:

I created a container and placed it above the form and gave it a style of Gradient, then I set this image as the scaled background (since this is an alpha mask scaling won't hurt the image quality much).Last I created a stitch image by using a stitch brush tool I found on the internet and this is the stitch image I was able to make (I set the background to red since the image is barely visible otherwise):

I set the stitches as a 9-piece border which allowed them to grow nicely. However, due to the bad source material the end result doesn't look nearly as polished as the work the guys from square were able to achieve. I'm guessing they have a depression overlay with the stitch layer to create an additional effect and their images are obviously more refined. This is what I ended up with in the resource editor:

Sunday, December 4, 2011

EmbeddedContainer is a class I added to LWUIT 1.5 without much fanfare out of a simple necessity, the problem is that this necessity existed only within the GUI builder and the class makes no sense outside of the context of the GUI builder. How do you document something like that???The necessity came about due to Triplay's application designs (our original GUI builder beta site), their design was iPhone inspired and so it relied on tabs (iPhone style tabs at the bottom of the screen) where different features of the application are within a different tab.

This didn't mesh well with the LWUIT GUI builder navigation logic and so we needed to rethink some of it. I wanted to reuse GUI as much as possible while still enjoying the advantage of navigation being completely managed for me.Android does this with Activities and the iPhone itself has a view controller, I don't like both approaches and think they both suck. The problem is that you have what is effectively two incompatible hierarchies to mix and match which is why Android needed to "invent" fragments and Apple can't mix view controllers within a single application.

The Component/Container hierarchy is powerful enough to represent such a UI but we needed a "marker" to indicate to the UIBuilder where a "root" component exists so navigation occurs only within the given "root". Here EmbeddedContainer comes into play, its a simple container that can only contain another GUI from the GUI builder. Nothing else. So we can place it in any form of UI and effectively have the UI change appropriately and navigation would default to "sensible values".

Navigation replaces the content of the embedded container, it finds the embedded container based on the component that broadcast the event. If you want to navigate manually just use the showContainer() method which accepts a component, you can give any component that is under the EmbeddedContainer you want to replace and LWUIT will be smart enough to replace only that component.

You can see an example of building a simple Tab based UI with the GUI builder and embedded container in the video above. The nice part about this is that this UI can be very easily refactored to provide a more traditional form based UI without duplicating effort and can be easily adapted to a more tablet oriented UI (with a side bar) again without much effort.

Wednesday, November 30, 2011

When we were at JavaOne this year Ofir and Peter sat down for a chat about the LWUIT accessibility, which you can read about there. Its a fascinating and complex subjects that we don't spend much time thinking about.Listen to their interview in the Java Spotlight mobility podcast.

Sunday, November 27, 2011

I've been meaning to write an introduction to LWUIT for Swing developers, for quite a while so this is it. We were highly inspired by Swing when writing LWUIT and that inspiration allows Swing developers instant familiarity into LWUIT thus providing them a very easy path into mobile development without the hassle.

The best way for a Swing developer to get into mobile is just to open a LWUIT based project and start working, its just that simple! At first the use of styles might seem slightly alien but you get used to it instantly and its ridiculously familiar.

There are quite a few differences between LWUIT and Swing which came thanks to the fact that we could learn and adapt from Swing. So LWUIT is in effect better than Swing mostly thanks to it being newer. Here is a list of highlight/bullet points for Swing developers wishing to take a look at LWUIT.

What's Similar:

Component/Container hierarchy with layout managers to arrange the elements. All the old friends are there with some additional added features (GridLayout, BorderLayout, BoxLayout, FlowLayout, GroupLayout) and some new (TableLayout, LayeredLayout). Naturally LWUIT doesn't feature the whole JComponent sub hierarchy and maintains a simpler hierarchy.

You can override paint and get a graphics object to do whatever you want. LWUIT is lightweight (just like Swing) and draws everything on its own to maximize portability and flexibility

You can add/remove action listener and similar observer based patterns for various events

Dialogs can be modal, so when you use Dialog.show() or similar method the next line won't execute until the dialog is disposed. Like in Swing, this is entirely optional.

LWUIT has a glasspane, its a bit different from the Swing glasspane but very similar in functionality

List model and list cell renderer, pretty much like Swing's API with added functionality for animations and horizontal lists.

ContentPane for the body of the Form (LWUIT's root component) which is technically hidden

The LWUIT EDT requires that you interact with it over a single thread, it has a callSerially method (invokeLater), callSeriallyAndWait (invokeAndWait) and even an invokeAndBlock (foxtrot for the advanced swing users)

What's Different :

Optimized for phones/tablets both touch & feature phones. This includes support for gestures and complex key layouts

Styles & Themeing - the PLAF is much narrower in LWUIT (due to size constraints) but LWUIT makes up for it by having a Style object associated with every component. Furthermore, LWUIT allows customizing said styles with a theme that can be created visually using an open source resource editor tool!

Animations are integrated in the core of LWUIT in several levels. You can animate layouts, transitions and just arbitrary objects.

The resource file format is an integral part of LWUIT (although technically completely optional) it offers a GUI builders (optional but quite helpful), theme creator, localization etc. Unlike matisse it doesn't generate any code thus providing a more VB like experience where the UI and code are cleanly separated. The tool can be given to a designer with no coding experience

Painters - Swing tried to integrate painters after the fact and failed since the framework needs to be designed with them to begin with. We did just that. We also separated background painting from foreground painting and made it easier to override just background painting.

Deep and elaborate porting layer allowing LWUIT to be ported to any platform easily

LWUIT is truly open source - while Swing was technically open sourced, debugging/modifying Swing was not trivial since it was integrated into the JDK. This also prevented developers from incorporating fixes (or a known working version) into their build. LWUIT is bundled with the application so you can easily fix it and very easily modify code/debug to locate/fix issues. The development is easy to follow with a public viewable SVN. You can actually get commits from us as we fix issues and add features.

Monday, November 21, 2011

Simple animations to provide a sense of place/navigation are what makes an application shine. They attract the attention of the user to the ongoing operation within the application while providing a sense of continuity, in that sense they are not "fluff" and should be taken very seriously.One of the nicest things in the places demo is the animation on the map bellow which you should be able to see in the video above. When selecting a city within the demo we can see an animation of the map highlight moving to a new location. To do that we need to start with the map location image here (I set the text background to red to make the white image visible):

We can add this image by using the add multi-image dialog as such:

And now we need to go back to the GUI builder to place the image on the map, don't worry about the location we will get to that soon enough. I select the Map Label entry and change its name to Map (to make it easier to work with it in code), I also change the name of the List at the bottom to cityList.Next drag a container into the same container where the Map is currently at and set its layout to layered layout. Make sure that the Map entry is before the Container entry which you just added (you can rearrange them in the tree). Drag the Map into that container and place another new container next to it. Drag a label into the new container and call it "MapHighlight", set its text to an empty string, set its UIID to container and select the mapPosition.png image as its icon. You should end up with something that looks like this:

Now its FINALLY time to start writing some code... Click the menu Application->Generate Netbeans Project. Type the name "LWUITPlaces" and select a directory into which the project should be generated.Important: you do this only ONCE after that saving the file will automatically update the generated code for you. Also important: If you saved the file in the past the old location is no longer relevant! The resource file will now be within the src directory of the generated project and can't be moved from that location.

In the GUI select the Form and select the events tab in the properties on the right, click the "Before Show" button. This should open the StateMachine.java file in Netbeans and create a method like this: protected void beforeMain(Form f) { // If the resource file changes the names of components this call will break notifying you that you should fix the code super.beforeMain(f);

Some of these things might seem obvious but others might not. When we animate to a particular list offset we need to know the pixel coordinate of the city within the Map. This worked great in Martin & Chen's demo since they used a regular image as the map. The problem is that a regular sized image would not work for lower/higher resolution devices which is why I used a multi-image.Once I used a multi-image the resolution of the image (hence the coordinates) would change depending on the device, so all the old city coordinates from Martin will no longr work (these are the MAP_POINTS coordinates).

The trick is simple, I ask the size of the map image in runtime and store it within the mapActualWidth/Height variables. Then I calculate the position in map offsets using a simple ratio equasion in the mapXCoordinate/mapYCoordinate methods.

Back to the beforeMain method (under the super call) we will write the code to position the selection based on coordinates. With the comments within the body I hope the content of this method is clear enough:

Monday, November 14, 2011

Last time we left off with the UI partially implemented yet we left one of the hardest features still ahead: the annoying circular button.To implement that button we will first select the top area container (the one with the MainList UIID) and set its layout to box layout Y. We will then drag a container (which will represent the first entry in the list) into that container, we will set the layout of that container to LayeredLayout!We will then place two containers within the layered layout container and set both to BorderLayout. We will add a button to the center of the first (label it Attractions) and a label to the west of the second (give it a " " space label, important do not leave it blank make sure a space is there!).

One last thing I forgot the last time, update the padding of the MainList UIID to 10 on all sides to keep the entries at a healthy distance from the border.

You should end up with something like the image bellow:

What we did is create a layered layout which places one component on top of the other and we used two containers with their layout to position a label on top of a button pretty much like we would do for the actual layout of the button.

Now lets style this to actually look like the end result, change the UIID of the attractions button to ListEntry and open its unselected style. Use this image to create an image border (notice I placed the same image in my first post in this series but it had a small artifact on it so use this one!):

And define the image border as such:

After generating the image border select the Margin and define 5 Millimeters on the left side and 1 millimeter on every other side. Notice that using millimeters allows us to scale the padding/margin more appropriately to higher/lower resolutions.Then select the padding tab and define 5 Millimeters on the left and 15 pixels on the other sides.After pressing OK you should have something like this:

Now select the parent container of the button and set its style to PaddedContainer, set the padding to 10 pixels on the left 0 on the right 4 on top and 4 on bottom. In the derive tab select deriving from Container. This will ensure that the button will always be smaller than the label which is important for the base design.

Now add the following images as multi-images:

Using the "Add Multi-Images" add these 4 icons as such:

Open ListEntry's selected/pressed style and in the derive tab type "ListEntry" unselected to derive the same style.

Select the label for the first entry and set its UIID to AttractionsIcon, edit its style and set the background to image scaled and attractions.png image from above:

Set the padding of the style to 5 millimeters on all sides and the margin to 0 on all sides.

You should end up with this result:

Which is already pretty much what we are looking for. Now just right click on the attractionsContainer and copy it. Paste it to the parent container 4 times and update every entries icon/text to this end result:

Now just so you will understand why we did all of this, this is how the UI will look on the iPhone scale resolution (3GS = 320x480):

Here is what it will look like on a Nexus One device (480x800, larger font):

Notice that after blogger scaled down the images they look almost identical, but if you will click to zoom you will see they are sized very differently.

Lets proceed with the easy parts! Select the main form and uncheck the scrollable Y property. Then select the Container with the MainList style and check its scrollable Y property. This will effectively make sure that horizontal scrolling doesn't hide the bottom section of the screen.

Now lets add the entries in the list, select "Add Multi-Images" and select the following images:

Use these values for the multi-image dialog:

Now select the UI section in the GUI builder and click the + button on the top left to add a new Blank Container. Call it CityRenderer.Set its UIID to "Renderer" and edit the style, set its derive tab to derive from Container and set its margin left/right to 15 millimeters.

Set the layout of the container to border layout and place two labels one in the north which you should name "Icon" (notice this should be the name not the label text!) and another in the south which you should name "Name" (yep).Set the UIID of the North label to Container and the UIID of the south label to WhiteLabel. Edit the style of white label, set its foreground color to white and make its transparency 0. Set its alignment to Center.

In the theme add a new Style in the selected tab called RendererFocus and set it to derive from Container.

You should end up with something like this:

Go back to the Main form in the UI builder and select the list of cities at the bottom, select the ListItems property and remove all the elements within it. Click add entry and add elements one by one starting with San Francisco (and the matching image from above) using the key Name for the city label and the key Icon for the image to this end result:

Follow this up and add all the cities from above to the list.After pressing OK select the list and set the fixed selection to Center and uncheck the scroll visible flag.

Last but not least select the Main form and type "LWUIT Places" in the title attribute, then create a title style and use this image to generate the border: