Saturday, May 31, 2008

LWUIT - guest post by Chen Fishbein

It's been a long couple of years, I still remember the day I came up to Yoav and asked him to give me 3 months to create a POC (proof of concept) of a UI framework that will ease the pain of creating compelling and consistent midp applications.
Back then the team created the first version of project Hydrazine client and it took us ages to meet the UE requirements, and when we finally did, the marketing guys asked us to create a 2nd version to a different device. That was the point when we realized we were doing something wrong.
When I came up with LWUIT 1st version after 3 months the development center realized this was something we must invest in for project hydrazine and potentially for other internal projects (releasing this to the community was something we didn't consider).
Then when we demoed the Hydrazine client to customers the responses were "so, how did you implement the client?". That basically gave me the "green light" to keep working on this and to bring in more engineers resources such as Shai who did and still does an amazing job in LWUIT.
I am very happy to say that since the b day of LWUIT at J1 we got lots of complimentary feedback.
It is very exciting and encouraging to know that LWUIT has been excepted within the Java ME community.
We look forward to see what will happen with LWUIT in the near future and in the open source.


project hydrazine 2 years ago

Guest bloggers

I asked Chen Fishbein who is the architect of LWUIT to start blogging here as well, his first post should appear soon. Hopefully additional guest posts from other authors will follow shortly as well as repeat posts from Chen.

Thursday, May 29, 2008

Very busy week running around with LWUIT

This has been a remarkably busy week for both Chen and myself promoting LWUIT both at Java Tech Day Israel and visiting on-site with companies using LWUIT to build commercial applications for mobile phones.

Comverse have been working with us on one of the first commercial applications outside of Sun that leverage LWUIT. They seem to share the excitement we have towards this project and Amit of Comverse went on stage with us at Java tech day. I hope to post some shots and a video of their really cool LWUIT application, its a visual voice mail application which they developer well before the iPhone was even planned (at least 3 years ago). They had a Java version for years but they couldn't get the UI to look "just right", it looks great in LWUIT and they are really helping us iron out the kinks in LWUIT.
Hopefully I will be able to get guys from Comverse to blog in the future about their LWUIT experiences.

I was also at another company which I won't name for now since it wasn't yet announced, they too will have a very widely deployed LWUIT application out within a ridiculously short amount of time. Hopefully once its made public I can blog more about their product which is also really cool.

This brings me to the point, people are using LWUIT for production already even before we released the code! There is real excitement and the amount of interest is just phenomenal!
I can't talk yet about most of the leads and directions because I'm working in a corporate environment, here you always assume everything is secrete (which it usually is). Expect allot of LWUIT related announcements in the coming months...

I have also spent allot of time on S60 performance with the help of some kind soles within Nokia who profiled the LWUIT Demo on devices and gave me some pointers. I tried to make simple and wide sweeping changes that might actually improve performance on all devices across the board.

Note: Updates by Shai to include image of Comverse Visual Voicemail application taken from here.

Sunday, May 25, 2008

New Video From Chen Of LWUIT On Devices

Chen sent me this video he filmed of LWUIT running on some cell phones in the office. He was not very happy with my old PSP video since the VM and runtime on the PSP are very slow and not very flattering to LWUIT performance.
I should really dedicate a few future blogs to LWUIT performance and what is really going on under the covers in LWUIT.

Saturday, May 24, 2008

Licensing Terms of LWUIT

Sylvain seems to have misunderstood the licensing terms of LWUIT which is understandable since these things are complex and we are not lawyers so let me reiterate this in no uncertain terms: LWUIT is 100% free for commercial use!

LWUIT is NOT GPL!
It is GPL+CPE (Classpath Exception) which allows you to make changes to the source without a problem. You will need to publish all changes you made to LWUIT, but since the CPE still applies you can still package your proprietary application with the binary and ship this without publishing the source code for your own application!

Disclaimer: I Am Not A Lawyer, however I know these issues reasonably well.

The main idea: change LWUIT as you want but give it back, feel free to make money off it using whatever business model you choose.

So why do we have another license on the page, the SLA?

Simplicity, it is often hard to talk in some corporations about open source. There is general GPL phobia in some cases and you might not be able to get past some of those lawyer types.
Sun wants to help you by offering another licensing option that might be easier to use in a corporate environment rather than dealing with OSS license complexities. Obviously this license can only be applied to the binary release to prevent potential harmful forking of the code.


How can Sun publish under the SLA and not only under the GPL+CPE?

Sun maintains full copyright to the code and as the copyright owner can license the binary & source as Sun pleases. This is a privilage of Sun as the owner of the rights to the code, you yourself can't just relicese and resell the code. However, you can sell derivative work as long as you comply with the appropriate license. e.g.:
When you haven't changed the code you can pick any license terms SLA or GPL+CPE.
When you changed the code you must comply with GPL+CPE and cannot use the SLA license.


Hopefully this makes sense, one thing I don't like about the GPL is that it makes programmers talk like lawyers... Hopefully we provided enough licensing leverage to render these issues mute.

Friday, May 23, 2008

LWUITDemo in only 123kb JAR!

The LWUIT demo which we have been showing around for some time is often quite hefty (500kb without obfuscation and 300kb with) we often say that most of the size is taken up by resources but due to complexity we didn't want to go into the trouble of removing them...
What I did today was just that, I refactored all usage of resources and made them downloadable on startup. If the demo can't find the resources locally then it goes to a download URL and fetches them to RMS. I have some odd deployment problems with my server but the jad/jar seem correct since I was able to beam the jar to my Nokia for testing.
This is the jad url and this is the jar url.
This is the exact same full blown LWUIT demo in 123kb, the size was so small it even surprised me!
BTW I also added a couple of features and fixed some bugs since this is based on a newer LWUIT snapshot. Notice that I added a feature suggested on the list for applying the list cell renderer (in the renderer demo) to the menu. The screenshot in this post shows the menu with a fisheye cell renderer installed, very cool effect!

Update by Shai: Fixed the JAR URL which was broken.

Thursday, May 22, 2008

When Will We See LWUIT Matisse Support

Those of you who were at J1 saw that we have a pretty complete build of Matisse working with LWUIT. The full blown Matisse GUI builder with group layout support, not some special limited tool... It supports things like custom components, theme switching, event handling etc.
Pretty much everything supported by the standard Matisse is supported (even baseline alignment is supported!).

So why isn't this out yet?

Matisse is HUGE, I could never have built this without the tremendous help from Tomas Pavek and Jan Stola. Their help made this stage possible, however to release something like this we need even further effort to verify that this tool doesn't break when you are actually trying to use it.

Problem is that there are dosens of priorities and tasks related to LWUIT and Matisse isn't at a high position in our team compared to this at the moment.

How can you help?

Write to lwuit_comments at sun.com or the users list, open RFE's both for LWUIT and for Netbeans (both Matisse and Mobility). Don't spam and be nice about it, the point being to show to both our management here and the NetBeans team how worthwhile it is to invest in this tool.
If its one person asking and writing I doubt that will help much, so if you really want it and think it warrants sacrificing other features/efforts to get this please let us know.

Wednesday, May 21, 2008

What Do You Want To Know About LWUIT?

How can I help? Let me know what sort of examples and instructions can be of help in LWUIT, I will try to write blog posts about various aspects of LWUIT and answer questions as much as possible.
Feel free to reply to this post and I will try to answer in future blog posts.

InvokeAndBlock, Foxtrot Inspired Threading In LWUIT

I previously mentioned that LWUIT has some nifty threading tools inspired by Foxtrot but didn't get into details, this is made worse by the fact that even people coming from Swing don't know enough about Foxtrot. So here I'll try to explain the basic concepts behind this threading approach which many consider superior to the simple approach in MIDP/Swing, but first we have to understand modal dialogs.

When people talk about dialog modality they often mean two separate things, the first indicates that the dialog intercepts all input and blocks the background form/window which is the true definition of modality. However, there is another aspect often associated with modality that is really important from a programmers perspective and simplified our code considerably:
public void actionPerformed(ActionEvent ev) {
// will return true if the user clicks "OK"
if(!Dialog.show("Question", "How Are You", "OK", "Not OK")) {
// ask what went wrong...
}
}
Notice that the dialog show method will block the calling thread until the user clicks OK or Not OK...
If you read a bit about LWUIT you would notice that we are blocking the EDT (Event Dispatch Thread) which is also responsible for painting, how does the dialog paint itself or handle events?

The secret is invokeAndBlock, it allows us to "block" the EDT and resume it while keeping a "nested" EDT functioning. The semantics of this logic are a bit hairy so I won't try to explain them further, this functionality is also available in Swing which has the exact same modality feature however Swing doesn't expose the "engine" to developers. Foxtrot, exposes this undocumented engine to Swing developers, in LWUIT we chose to expose the ability to block the EDT (without "really" blocking it) as a simple API: invokeAndBlock.

The best way to explain this is by example:
public void actionPerformed(ActionEvent ev) {
label.setText("Initiating IO, please wait...");
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
// perform IO operation...
}
});
label.setText("IO completed!");
// update UI...
}

Notice that the behavior here is similar to the modal dialog, invokeAndBlock "blocked" the current thread despite the fact that it is the EDT and performed the run() method in a separate thread. When run() completes the EDT is resumed. All the while repaints and events occur as usual, you can have invokeAndBlock calls occurring while another invokeAndBlock is still pending there are no limitations here.

As you can see this is a very simple approach for thread programming in UI, you don't need to block your flow and track the UI thread. You can just program in a way that seems sequential (top to bottom) but really uses multi-threading correctly without blocking the EDT.

Text Input In LWUIT Now And In The Future

Chen and myself got a question during our LWUIT session in J1 which in retrospect we probably didn't answer correctly. Text input in LWUIT today goes to the system native text box and returns when the user approves the change to the text.

One of our biggest users asked us in the past for a "lightweight" text widget, this would allow fast input for numbers or search fields but won't support predicitive text (T9). Such a future development won't replace the option to go to the native text box but would supplant it mostly for the simpler input types (e.g. numbers) and for input types where T9 is less important (e.g. search where mostly names are typed).

So when we got a question of how input is implemented in LWUIT we made the mistake of discussing the future support for lightweight input rather than the already existing support for standard text box input.

BTW for lightweight numeric input we already have a sample in the developer guide which implements a numeric text field with a blinking cursor so this should be a feasible component.

How Portable Is LWUIT Part 2 - The PSP


A cool thing about J1 is meeting people who are working on great ideas which I wasn't expecting, I met Max Mu before but we hadn't talked too much... Then in J1 he flashed his PSP running a port of Phone ME which was also the subject of his BoF, getting LWUIT running on it was just a matter of beaming the jar over into his device using BT. It just worked, very little needed doing. The attached video shows our reaction to the feat including sideline commentary about people stealing our food (goes to show you what people like Max and myself are up to while drinking in a bar party).


Max did an amazing job with this port just the fact that LWUIT worked without a hitch using the exact same jar as any other device on the first try is a testament of that. The VM is purely interpreted which is why LWUIT is so slow (the screen is very large making LWUIT even slower without a JIT).
This was not the only surprise I had at J1 regarding devices, all over the show people approached me and showed me the UI demo on their pet device and in many cases it was devices we haven't seen before. Had LWUIT been a public product this would have been commendable, but these people all came to us from the very limited set of people who had access to our pre-releases...

Tuesday, May 20, 2008

Progress Indicator & Threads In LWUIT

LWUIT doesn't ship with a pre-existing progress indicator, mostly because making something generic enough for all the common cases is not as simple as it might seem in the beginning. Especially when considering how easy it is to write your own progress indicator...
This is a simple example of how to create a custom component in LWUIT in this specific case a progress indicator that supports both drawing itself (as a filled round rectangle and as a couple of images overlayed one on top of the other. The progress indicator component is fully themeable and customizable and will accept all L&F settings seamlessly.
The screenshots show both an image based indicator (its ugliness is just a testament to my bad drawing skills) and an indicator drawn in graphics primitives (fill/drawRoundRect). These are the images used to draw the image progress:

As part of this I also wanted to create something else familiar to Swing developers, the SwingWorker. Generally I prefer the foxtrot approach implemented in LWUIT as invokeAndBlock in Display, however lots of people like the SwingWorker approach so I used it here as part of the explanations.

First lets create the Progress indicator component:
/**
* Simple progress indicator component that fills out the progress made.
* Progress is assumed to always be horizontal in this widget
*
* @author Shai Almog
*/

public class Progress extends Component {
private byte percent;
private Image unfilled;
private Image filled;

/**
* The default constructor uses internal rendering to draw the progress
*/

public Progress() {
setFocusable(false);
}

/**
* Allows indicating the progress using a filled/unfilled images.
* The unfilled image is always drawn and the filled image is drawn on top with
* clipping to indicate the amount of progress made.
*
* @param unfilled an image containing the progress bar without any of its
* content being filled (with the progress color)
* @param filled an image identicall to unfilled in every way except that progress
* is completed in this bar.
*/

public Progress(Image unfilled, Image filled) {
this();
this.unfilled = unfilled;
this.filled = filled;
}

/**
* Indicate to LWUIT the component name for theming in this case "Progress"
*/

public String getUIID() {
return "Progress";
}

/**
* Indicates the percent of progress made
*/

public byte getProgress() {
return percent;
}

/**
* Indicates the percent of progress made, this method is thread safe and
* can be invoked from any thread although discression should still be kept
* so one thread doesn't regress progress made by another thread...
*/

public void setProgress(byte percent) {
this.percent = percent;
repaint();
}

/**
* Return the size we would generally like for the component
*/

protected Dimension calcPreferredSize() {
if(filled != null) {
return new Dimension(filled.getWidth(), filled.getHeight());
} else {
// we don't really need to be in the font height but this provides
// a generally good indication for size expectations
return new Dimension(Display.getInstance().getDisplayWidth(),
Font.getDefaultFont().getHeight());
}
}

/**
* Paint the progress indicator
*/

public void paint(Graphics g) {
int width = (int)((((float)percent) / 100.0f) * getWidth());
if(filled != null) {
if(filled.getWidth() != getWidth()) {
filled = filled.scaled(getWidth(), getHeight());
unfilled = unfilled.scaled(getWidth(), getHeight());
}

// draw based on two user supplied images
g.drawImage(unfilled, getX(), getY());
g.clipRect(getX(), getY(), width, getHeight());
g.drawImage(filled, getX(), getY());
} else {
// draw based on simple graphics primitives
Style s = getStyle();
g.setColor(s.getBgColor());
int curve = getHeight() / 2 - 1;
g.fillRoundRect(getX(), getY(), getWidth() - 1, getHeight() - 1, curve, curve);
g.setColor(s.getFgColor());
g.drawRoundRect(getX(), getY(), getWidth() - 1, getHeight() - 1, curve, curve);
g.clipRect(getX(), getY(), width - 1, getHeight() - 1);
g.setColor(s.getBgSelectionColor());
g.fillRoundRect(getX(), getY(), getWidth() - 1, getHeight() - 1, curve, curve);
}
}
}
This code seems to me to be simple but obviously I'm not objective, if something is not clear or you think it might not be clear to others please let me know in the comments.

BackgroundTask is my equivalent to SwingWorker, its much simpler than SwingWorker:

/**
* A tool allowing to respond to an event in the background possibly with
* progress indication inspired by Swings "SwingWorker" tool. This class
* should be used from event dispatching code to prevent the UI from blocking.
* State can be stored in this class the separate thread and it can be used by
* the finish method which will be invoked after running.
*
* @author Shai Almog
*/

public abstract class BackgroundTask {
/**
* Start this task
*/

public final void start() {
if(Display.getInstance().isEdt()) {
taskStarted();
} else {
Display.getInstance().callSeriallyAndWait(new Runnable() {
public void run() {
taskStarted();
}
});
}
new Thread(new Runnable() {
public void run() {
if(Display.getInstance().isEdt()) {
taskFinished();
} else {
performTask();
Display.getInstance().callSerially(this);
}
}
}).start();
}

/**
* Invoked on the LWUIT EDT before spawning the background thread, this allows
* the developer to perform initialization easily.
*/

public void taskStarted() {
}

/**
* Invoked on a separate thread in the background, this task should not alter
* UI except to indicate progress.
*/

public abstract void performTask();

/**
* Invoked on the LWUIT EDT after the background thread completed its
* execution.
*/

public void taskFinished() {
}
}

And this is the code to display these two progress bars:

Form progressForm = new Form("Progress");
progressForm.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
Progress p1 = new Progress();
progressForm.addComponent(new Label("Drawn"));
progressForm.addComponent(p1);
Progress p2 = new Progress(Image.createImage("/unfilled.png"), Image.createImage("/filled.png"));
p2.getStyle().setBgTransparency(0);
progressForm.addComponent(new Label("Image Based"));
progressForm.addComponent(p2);
progressForm.show();

class ProgressCommand extends Command {
private Progress p;
public ProgressCommand(String name, Progress p) {
super(name);
this.p = p;
}
public void actionPerformed(ActionEvent ev) {
new BackgroundTask() {
public void performTask() {
for(byte b = 0 ; b <= 100 ; b++) {
try {
p.setProgress(b);
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}.start();
}
}

progressForm.addCommand(new ProgressCommand("Drawn", p1));
progressForm.addCommand(new ProgressCommand("Images", p2));