Wednesday, November 30, 2011

Interview With Peter & Ofir From JavaOne

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

How LWUIT Is Different (better) From Swing

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

Places Demo Part V: Location Animation

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);
       
    }

Before we continue go to the top of the class and add the following variables and constants:
    private static final int MAP_ORIGINAL_WIDTH = 178;
    private static final int MAP_ORIGINAL_HEIGHT = 114;
    private int mapActualWidth;
    private int mapActualHeight;
    private static final int [][] MAP_POINTS =  {
        {10, 65},
        {0, 42},
        {77, 75},
        {146, 37},
        {107, 33}
    };
   
    private int mapSelection = 0;

We will also need these methods to exist:
    private int mapXCoordinate(int c) {
        return (int)(((float)c) / ((float)MAP_ORIGINAL_WIDTH) * ((float)mapActualWidth));
    }

    private int mapYCoordinate(int c) {
        return (int)(((float)c) / ((float)MAP_ORIGINAL_HEIGHT) * ((float)mapActualHeight));
    }

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

Places Demo Part IV

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:




Now use the border wizard as such:



And we are done! This is the final result:

Monday, November 7, 2011

Places Demo Part III

OK, its time to get started with actual resource editor work. First we need to launch the resource editor and create a new blank theme.

BTW If you follow along don't forget to save frequently, unfortunately the resource editor doesn't yet offer proper "crash recovery" it is in my todo list but is a rather hairy problem.

Then I define the form background to a vertical gradient starting from d8fe:





The next stage is going to the GUI builder and creating a new form (I called it Main, but call it whatever you want). I set its layout to border layout and placed two containers within it (in the center and in the south), these containers will hold the UI for the two portions of the screen.

It should look something like this:

Then we need to allow for the design of the top area texture, for that we will add a new multi-image using the Images->Add Multi-Images option and select the skyline image here:
Notice that I am selecting the full size image and not the one included in the blog!

Then I am prompted to select the resolutions to the multi images. Notice that I filled out the percentages (to 100 and 61) and only then updated the values to 0 where appropriate.

This dialog effectively tells the resource editor which size images it should manufacture for every resolution. I selected 100% for width which means I want the typical width of a device class as listed above (since the image needs to occupy the full width) and selected 60 percent height to match the image dimensions.
I zeroed out the values of the fields for which I didn't want an image created, very high resolution images would make my resource file too large and very low res images will be pointless for this sort of application.

After pressing OK I select the first container and set its UIID property to "MainTexture", I then right click it and select Style->Unselected to edit its style. I select "Image Tile Horizontal Align Top" and within the derive tab I type in Container (to inherit the behavior of the Container style).

Notice that the image might not tile properly sometimes due to its size, in which case we can increase its width slightly. Ideally an image that tiles "properly" will provide the best background texture.

You should have something that looks like this:

And the GUI should look like this:

Now we would like to add the carousel to the bottom of the screen and the map.
We add the map image using the same multi-image approach from before:


We then select the second container and select BoxLayout_Y as its layout. We drag two containers into it. We select the containers and select for both the FlowLayout layout type, and configure it to align to center. This allows us to center the elements within the containers.
We drag a label into the top first of these two containers, set its UIID to Container and set its icon to the map image.
We drag a List to the second container and configure its orientation to be Horizontal. You should end up with something that looks like this:


We will implement the list bellow in the next part but lets at least finish the main sections of the top part... Go to the top container (the one I called Container1 which we placed in the Center) and set its layout to border layout, drag a container into its center area.
Set the UIID of that new container to MainList and its layout to box layout Y.
Edit its style by right clicking it and selecting Style->Unselected, in the derive tab type in "Container". Select the border tab and click the image border wizard.
Use pick image to pick the list image here:




And fill out the cutting setting as such with 30 px for every direction and Low/Medium multi-image generation:

After pressing the generate button close the wizard and select the margin tab, define 10 pixels for every direction and click OK. 
This should produce something like this:




Next time I will continue from this point to complete the UI of the first form.


Wednesday, November 2, 2011

Places Demo Part II

In the first part of this series I went over the image Martin and Chen produced, in this part I'll review the path that needs to be taken in order to take this image and make it into an actual application fit for all devices.

The first part is divide & conquer, we need to divide the image into its basic elements:
Backgrounds
Component looks
Content

Photoshop makes this division relatively easy since it already divides elements to layers, although often these layers make sense in photoshop and not within our application. So reviewing this image:


We have the following elements in the background:
  • Gradient from 00d8fe to black:




  • Translucent texture image, notice that this image is translucent and it appears here on the background of the blog. When layered on the gradient it will look quite different:

Effectively these two come together to form a background like this:




Notice the color at the top its actually the area where the title bar background should reside, that is a part of the title component design.

The components within the design are far more complex, there are easy elements such as the title:



And the list background:



Which are both pretty easy. It gets complicated when looking at an element like this:




Obviously the word Bars is part of the foreground its just here for visualization. As you can see the round portion of the cup fits snugly into the button, because it contains and icon and is aligned perfectly to that icon it can't be separated from that icon.
Yet because it aligns to the button and the button needs to grow with the text within it we might end up with something that looks like that:
Which is obviously very far from the original design! There is no way to actually solve this problem that would be truly satisfying so we will make some compromises.
We will treat this element as the component:
And we will always scale the icon on the left to fit that element so it will be covered perfectly. Its not an ideal solution since it requires scaling the background image which can cause degradation.

The rest of the images and the text within the application are really just the content, this separation is critical since elements that are background elements should be incorporated in the theme and elements that represent content should be incorporated into the UI.

In the next post I will start explaining how to move this logic into the resource editor and create the UI for this demo.