Chen and myself created a new video featuring some of the touch screen visual effects we demoed in the simulator here on the Instinct device.
No 3D transition effects are demoed since the device doesn't support JSR 184 (notice that LWUIT still runs unmodified on such a device!). We hope to upload additional such videos but most of our devices got confiscated by people around the office (our N95 is completely gone).
Monday, August 25, 2008
Sunday, August 24, 2008
The Model (MVC): Million Contacts March
Swing's approach to MVC is one of the hardest concepts for people to fully grasp, which is a real shame as it is probably the most important and powerful feature in Swing. LWUIT copied Swing's approach to MVC almost entirely but at a smaller scale. Chen already blogged about renderers in the past but that is only one piece of the puzzle, to fully understand it we need to understand models... But first lets recap, what is MVC:
Model - Represents the data for the component (list), the model can tell us exactly how many items are in it and which item resides at a given offset within the model. This differs from a simple Vector (or array) since all access to the model is controlled (the interface is simpler) and unlike a Vector/Array the model can notify us of changes that occur within it.
View - The view draws the content of the model. It is a "dumb" layer that has no notion of what is displayed and only knows how to draw. It tracks changes in the model (the model sends events) and redraws itself when it changes.
Controller - The controller accepts user input and performs changes to model which in turn cause the view to refresh.
LWUIT's List component uses the MVC paradigm to separate its implementation. List itself is the Controller (with a bit of View mixed in). The ListCellRenderer interface is a View and the ListModel is (you guessed it by now) the model.
When the list is painted it iterates over the visible elements in the model and asks for them, it then draws them using the renderer.
Why is this useful?
Since the model is a lightweight interface it can be implemented by you and replaced in runtime if so desired, this allows several very cool use cases:
1. A list can contain thousands of entries but only load the portion visible to the user. Since the model will only be queried for the elements that are visible to the user it won't need to load into memory a very large data set until the user starts scrolling down (at which point other elements may be offloaded from memory).
2. A list can cache efficiently. E.g. a list can mirror data from the server into local RAM without actually downloading all the data. Data can also be mirrored from RMS for better performance and discarded for better memory utilization.
3. No need for state copying. Since renderers allow us to display any object type, the list model interface can be implemented by the applications data structures (e.g. persistence/network engine) which would return internal application data structures saving you the need of copying application state into a list specific data structure.
4. Using the proxy pattern (as explained in a previous post) we can layer logic such as filtering, sorting, caching etc. on top of existing models without changing the model source code.
5. We can reuse generic models for several views e.g. a model that fetches data from the server can be initialized with different arguments to fetch different data for different views. View objects in different Form's can display the same model instance in different view instances thus they would update automatically when we change one global model.
Most of these use cases work best for lists that grow to a larger size or represent complex data which is what the list object is designed to do.
To show this off lets create a list with one million entries... What I am trying to prove here is that a list and a model have a very low overhead when used properly. Most of the overhead for rendering a list is in the renderer and the model implementation, both of which you can optimize to your hearts content. This is a very small price to pay for something as flexible, powerful and customizable as the LWUIT list!
Model - Represents the data for the component (list), the model can tell us exactly how many items are in it and which item resides at a given offset within the model. This differs from a simple Vector (or array) since all access to the model is controlled (the interface is simpler) and unlike a Vector/Array the model can notify us of changes that occur within it.
View - The view draws the content of the model. It is a "dumb" layer that has no notion of what is displayed and only knows how to draw. It tracks changes in the model (the model sends events) and redraws itself when it changes.
Controller - The controller accepts user input and performs changes to model which in turn cause the view to refresh.
LWUIT's List component uses the MVC paradigm to separate its implementation. List itself is the Controller (with a bit of View mixed in). The ListCellRenderer interface is a View and the ListModel is (you guessed it by now) the model.
When the list is painted it iterates over the visible elements in the model and asks for them, it then draws them using the renderer.
Why is this useful?
Since the model is a lightweight interface it can be implemented by you and replaced in runtime if so desired, this allows several very cool use cases:
1. A list can contain thousands of entries but only load the portion visible to the user. Since the model will only be queried for the elements that are visible to the user it won't need to load into memory a very large data set until the user starts scrolling down (at which point other elements may be offloaded from memory).
2. A list can cache efficiently. E.g. a list can mirror data from the server into local RAM without actually downloading all the data. Data can also be mirrored from RMS for better performance and discarded for better memory utilization.
3. No need for state copying. Since renderers allow us to display any object type, the list model interface can be implemented by the applications data structures (e.g. persistence/network engine) which would return internal application data structures saving you the need of copying application state into a list specific data structure.
4. Using the proxy pattern (as explained in a previous post) we can layer logic such as filtering, sorting, caching etc. on top of existing models without changing the model source code.
5. We can reuse generic models for several views e.g. a model that fetches data from the server can be initialized with different arguments to fetch different data for different views. View objects in different Form's can display the same model instance in different view instances thus they would update automatically when we change one global model.
Most of these use cases work best for lists that grow to a larger size or represent complex data which is what the list object is designed to do.
To show this off lets create a list with one million entries... What I am trying to prove here is that a list and a model have a very low overhead when used properly. Most of the overhead for rendering a list is in the renderer and the model implementation, both of which you can optimize to your hearts content. This is a very small price to pay for something as flexible, powerful and customizable as the LWUIT list!
class Contact {
private String name;
private String email;
private Image pic;
public Contact(String name, String email, Image pic) {
this.name = name;
this.email = email;
this.pic = pic;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Image getPic() {
return pic;
}
}
class ContactsRenderer extends Container implements ListCellRenderer {
private Label name = new Label("");
private Label email = new Label("");
private Label pic = new Label("");
private Label focus = new Label("");
public ContactsRenderer() {
setLayout(new BorderLayout());
addComponent(BorderLayout.WEST, pic);
Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS));
name.getStyle().setBgTransparency(0);
email.getStyle().setBgTransparency(0);
cnt.addComponent(name);
cnt.addComponent(email);
addComponent(BorderLayout.CENTER, cnt);
}
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
Contact person = (Contact) value;
name.setText(index + ": " + person.getName());
email.setText(person.getEmail());
pic.setIcon(person.getPic());
return this;
}
public Component getListFocusComponent(List list) {
return focus;
}
}
String[][] CONTACTS_INFO = {
{"Nir V.","Nir.Vazana@Sun.COM"},
{"Tidhar G.","Tidhar.Gilor@Sun.COM"},
{"Iddo A.","Iddo.Arie@Sun.COM"},
{"Ari S.","Ari.Shapiro@Sun.COM"},
{"Chen F.","Chen.Fishbein@Sun.COM"},
{"Yoav B.","Yoav.Barel@Sun.COM"},
{"Moshe S.","Moshe.Sambol@Sun.COM"},
{"Keren S.","Keren.Strul@Sun.COM"},
{"Amit H.","Amit.Harel@Sun.COM"},
{"Arkady N.","Arcadi.Novosiolok@Sun.COM"},
{"Shai A.","Shai.Almog@Sun.COM"},
{"Elina K.","Elina.Kleyman@Sun.COM"},
{"Yaniv V.","Yaniv.Vakrat@Sun.COM"},
{"Nadav B.","Nadav.Benedek@Sun.COM"},
{"Martin L.","Martin.Lichtbrun@Sun.COM"},
{"Tamir S.","Tamir.Shabat@Sun.COM"},
{"Nir S.","Nir.Shabi@Sun.COM"},
{"Eran K.","Eran.Katz@Sun.COM"}
};
int contactWidth= 36;
int contactHeight= 48;
int cols = 4;
Resources images = Resources.open("/images.res");
Image contacts = images.getImage("people.jpg");
Image[] persons = new Image[CONTACTS_INFO.length];
for(int i = 0; i < persons.length ; i++){
persons[i] = contacts.subImage((i%cols)*contactWidth, (i/cols)*contactHeight, contactWidth, contactHeight, true);
}
final Contact[] contactArray = new Contact[persons.length];
for (int i = 0; i < contactArray.length; i++) {
int pos = i % CONTACTS_INFO.length;
contactArray[i] = new Contact(CONTACTS_INFO[pos][0], CONTACTS_INFO[pos][1], persons[pos]);
}
Form millionList = new Form("Million");
millionList.setScrollable(false);
List l = new List(new ListModel() {
private int selection;
public Object getItemAt(int index) {
return contactArray[index % contactArray.length];
}
public int getSize() {
return 1000000;
}
public int getSelectedIndex() {
return selection;
}
public void setSelectedIndex(int index) {
selection = index;
}
public void addDataChangedListener(DataChangedListener l) {
}
public void removeDataChangedListener(DataChangedListener l) {
}
public void addSelectionListener(SelectionListener l) {
}
public void removeSelectionListener(SelectionListener l) {
}
public void addItem(Object item) {
}
public void removeItem(int index) {
}
});
l.setListCellRenderer(new ContactsRenderer());
l.setFixedSelection(List.FIXED_NONE_CYCLIC);
millionList.setLayout(new BorderLayout());
millionList.addComponent(BorderLayout.CENTER, l);
millionList.show();
Thursday, August 21, 2008
Matisse Support - The Movie
We started working on the LWUIT Matisse port quite a while back and we demoed it on quite a few occasions.
Its actually a much cooler demo than the video lets out since the demo involves creating a theme from scratch, then the UI using Matisse and running it all directly on a device...
(In J1 it also involved NetBeans crashing and me gracefully avoiding tough curse words).
Those of you who haven't attended or heard about our presentation might not quite know or understand what this means. Let me be clear: This is the "true" fully functional Matisse with GroupLayout support. This Matisse allows custom made components (no special work required) and various other cool features right out of the box. But its sadly incomplete and releasing it as source would be impossible for us since we don't hold the rights (the NetBeans team does since its based on Matisse).
Its actually a much cooler demo than the video lets out since the demo involves creating a theme from scratch, then the UI using Matisse and running it all directly on a device...
(In J1 it also involved NetBeans crashing and me gracefully avoiding tough curse words).
Those of you who haven't attended or heard about our presentation might not quite know or understand what this means. Let me be clear: This is the "true" fully functional Matisse with GroupLayout support. This Matisse allows custom made components (no special work required) and various other cool features right out of the box. But its sadly incomplete and releasing it as source would be impossible for us since we don't hold the rights (the NetBeans team does since its based on Matisse).
Tuesday, August 19, 2008
LWUIT For Swing Developers
Chen and myself keep referring to LWUIT as a tool inspired by Swing and its architecture. To that extent I developed a while back this presentation for Swing developers, it uses terms that should be familiar to advanced Swing developers to help them get a leg up on LWUIT.
I think Swing developers will find LWUIT very interesting since it goes places Swing can't go and picked up lots of ideas from Swings experience. I also assume many Swing developers are peeking towards the mobile space and its rapid growth thinking about making the leap, LWUIT is ideal for those guys and hopefully this presentation will get you going.
These go both ways, the other day a colleague grabbed me in the office and told me that due to recent tasks he had to do some Swing programming. Jokingly he mentioned: "They really stole allot from LWUIT".
I think Swing developers will find LWUIT very interesting since it goes places Swing can't go and picked up lots of ideas from Swings experience. I also assume many Swing developers are peeking towards the mobile space and its rapid growth thinking about making the leap, LWUIT is ideal for those guys and hopefully this presentation will get you going.
These go both ways, the other day a colleague grabbed me in the office and told me that due to recent tasks he had to do some Swing programming. Jokingly he mentioned: "They really stole allot from LWUIT".
Monday, August 18, 2008
Resource Editor Tutorial
I just uploaded to youtube a new resource editor tutorial showing off a simple usage of the resource editor to create a quick theme in a few minutes while explaining what I'm doing.
This video tutorial barely scratches the surface of what can be done with the resource editor. I will try to show off some more elaborate features and abilities in future posts. The main goal here is to get people starting and playing around with the resource editor.
This video tutorial barely scratches the surface of what can be done with the resource editor. I will try to show off some more elaborate features and abilities in future posts. The main goal here is to get people starting and playing around with the resource editor.
Saturday, August 16, 2008
New LWUIT Eye Candy Video
Posted this new video to youtube showing off some of the latest features in LWUIT together with some tried and true features.
The video has some popups along the way to explain what is going on, it has some artifacts and hiccups due to the capture software. All of the features illustrated here are running on devices I hope to post a couple of videos showing these features off on the devices themselves.
The video has some popups along the way to explain what is going on, it has some artifacts and hiccups due to the capture software. All of the features illustrated here are running on devices I hope to post a couple of videos showing these features off on the devices themselves.
Press Release And Article Links
The press release for LWUIT is making the rounds quite a few publications are picking it up.InfoWorld has a great article that got syndicated allot, the registar made some minor mistakes but is a nice article too. The JavaLobby is blogging about LWUIT as well. VNU also has some thoughts about LWUIT.
Ed tries to be a bit sensational with his article I also think he didn't quite get the bottom line correctly. A couple of things he missed are the Android port and the fact that LWUIT runs really well on Phone ME which is free and available for Windows Mobile... The only blocker for iPhone portability is Apples licensing terms. He did however get some iPhone bloggers to link to us, which is a shame since my bandwidth reached its cap and I have some really cool demos I can show.
ZDNet itself has an article too, which was syndicated all over.
JDJ has some coverage, Heise online as well. The mobile phone development blog which discussed us in the past also has a post about the source release. All of this with lots of other smaller publications and links.
As a side note Java.net also posted a new introductory article about LWUIT to join the other great articles already published.
Subscribe to:
Posts (Atom)