Lately I’ve been working on a couple of exciting customer projects, involving HTML5-based UIs on embedded (TV) platforms. Due to the fabulous work some of my colleagues put into QtWebkit and QtDirectFB, and the ongoing work from MIPS Technologies on their Webkit JIT, the paint performance is very good, and Javascript is getting faster and faster.
However, while working on these projects, I’ve ran into a few issues that were not solvable by JIT-accelerated JavaScript or by hardware accelerated painting.
The main problem was that when you write a dynamic UI for a full application, the complexity starts to be difficult to manage. I started by dividing the app to a few HTML pages, but that of course created unacceptable delays when switching between the pages. So I looked online for dynamic web-app solutions. Those include the amazing Javascript libraries Dojo and JQuery. The problem with those is that they manage the complexity by selecting elements with custom-built CSS-like selectors (which are slow) and by modifying the HTML DOM tree in runtime (which is slower).
An alternate way to handle HTML performance is with the HTML5 canvas element (which is nicely accelerated) – the problem is that canvas API is currently too low level, and the widget libraries on top of it are not mature yet, definitely not in time for my customer projects.
So I asked myself: what components are really needed in order to make a dynamic UI?
Looking at the Qt Kinetic project, I need 4 main elements:
- Animations
- State Machine
- Graphic effects
- Declarative Syntax
Now HTML and CSS are already a declarative syntax, and CSS3 (supported in webkit) contains all the animations and graphic effects I currently need. The missing element, which is also my personal favorite, is the State Machine.
Why do I keep going on and on about state-machines?
If you think about it, both CSS, HTML, and Qt widgets are optimized to handle complexity in space. State machines, however, are optimized to handle complexity in time. An application can be dynamic only if it’s rich both in space and in time. That’s why to me state-machines are of outmost importance for dynamic UIs.
Enough philosophy, what’s this about?
Now I’ve had the pleasure to work with the SCXML standard in the last year, both by prototyping the Qt-SCXML library (which later helped with the evolution of the Qt State Machine Framework), and by joining the w3c group that defines the SCXML standard.
While working on my latest HTML-based project, I was thinking – what if I could define the flow of my web-app with an SCXML statechart? Wouldn’t that allow for managing the complexity of my web app, without incurring the performance overhead of modifying and re-modifying the DOM?
Introducing Statechartz
So I took the time to write an SCXML library for Javascript. I basically had to copy the SCXML algorithm to Javascript syntax, which took a while, but has already saved me hours of work by having the code of my web-apps cleaner and smaller.
The result can be found at the statechartz branch on the SCXML lab GIT repo., and the demo can be viewed online. Note that the library is currently only tested on webkit-based browsers (QtWebkit/Arora, Safari, Chrome), but porting it to other browsers shouldn’t be too difficult.
Looking a bit at the HTML code of the demo, you’ll notice the following:
This is the line that connects an HTML page with an SCXML statechart, defining the page’s flow. The state-machine would start running as soon as the page is loaded.
But hey! rel=”statechart” isn’t standard!
Well, I was surprised to learn that HTML5 allows you to add your own link types, which become legal if you register them in the WHATWG Wiki, which I did; so now <link rel=”statechart” href=”somefile.scxml” /> is completely standard ![]()
Though using the link tag would cover most cases, it’s completely optional and the Statechartz library can be used more dynamically, either by loading an SCXML file whenever wanted:
var myStateMachine = Statechartz.loadScxml(someURL);
or by using a dynamic javascript syntax that looks like this:
var myStateMachine;
with (Statechartz) {
myStateMachine = build(
State("root",
Entry(function() { doSomething(); }),
Parallel("s1",Initial,
Exit(function()(doSomethingElse(); }),
Transition(Event("EVENT.QUIT"), Target("exit"))
),
Final("exit")
)
);
}
Another thing to look at, is the DOM:
...
Even though screen_weather, screen_shopping and screen_calc exist in the DOM to begin with, only one of them is shown at a time. Also, there’s no particular Javascript code that shows and hides them. That’s done by a trick I added to the Statechartz library: the CSS class of the document BODY element changes when the state changes. So, if I’m in a state with ID “calc”, the body would have a CSS class “state_calc”, and now all it takes is adding this to the CSS (it’s a little different in the actual CSS, but I’m trying to make a point):
#screen_calc {
left: -350px;
-webkit-transition-duration: 600ms;
opacity: 0.5;
}
.state_calc #screen_calc {
left: 0px;
-webkit-transform: rotate(360deg) scale(1);
opacity: 1;
}
This code, like states and transitions in Qt 4.6, would animate the opacity and geometry of my calculator screen, and would create an animated transition when the calculator is entered to / exited from.
The Demo, and performance
The demo that comes with the statechartz library demonstrates 3 uses of the Statechartz library:
- Dynamic UIs with states and transitions (switching between the 3 widgets)
- Managing UI complexity (e.g. the instructions popup)
- Business logic (the calculator ‘engine’)
Note that the demo specifically is too animation-heavy to run well on embedded platforms, and of course webkit could use some more optimizations. but the concepts (don’t mess with the DOM, use Statecharts to manage time) are the same, and are working on other webkit-based projects with a cvery nice performance gain.
The next step on the SCXML path
After this project, SCXML is now supported in 3 implementations: Qt C++ (with scc), QtScript (with QScxml), and web (with Statechartz). The next natural step is a statechart graphical tool (Creator plugin) that can help author SCXML files for all of those 3 implementations. Though it’s not on our roadmap, some of us (including the undersigned) were working on prototypes, and any help from the community would be appreciated!
Links
The code: http://qt.gitorious.org/qt-labs/scxml/trees/statechartz
The live demo (webkit browsers only): http://labs.trolltech.com/blogs/wp-content/uploads/2009/11/demo.html
Video capture of the live demo: http://labs.trolltech.com/blogs/wp-content/uploads/2009/11/statechartz-capture_0001.wmv
Possibly related posts:
10 comments
> “But hey! rel=”statechart” isn’t standard!”
AFAIK HTML has always allowed custom rel values, both in LINK and in A elements.
Anyway, very interesting work!
hi there, that’s quite some interesting work. lately, i have been trying to implement kinetic scrolling in javascript. and it’s a real pain. i started with maestro Ariya code port to python[1].
the work presented here is a great solution to my problem. unfortunately, i needed support for all the current browsers. i’m actually riding on the back of jquery. and yes, there is some slowness.
i hope to see this work evolve.
[1]: http://labs.trolltech.com/blogs/2008/11/15/flick-list-or-kinetic-scrolling/
I feel honored, my surname is in the name
Great post No’am!
Sweet!
Incidentally the demo also demonstrates a strange bug in my Safari that makes the graphics in the last widget look garbage until it settles.
Hmmm…
> The live demo (webkit browsers only) …
And what about other browsers? Or this possibilities are intended to use in webkit-based local applications, not on websites? I’ve remembered time of Browser Wars… And I don’t want it again 0_o.
@Flavio: in order for a custom rel attribute to be standard, you have to define it in the WhatWG wiki (for HTML5) or in microformats (for HTML4). This formalism protects extensions from colliding with future versions of the standard, though in the HTML5 case the overhead is minimal.
@arg0: right now this is more for webkit based apps than for websites, though the statechartz library should be pretty easy to port, and would probably be useful for web-sites (I just didn’t have time to do it myself yet, but I had to start with something…).
The demo, however, makes heavy use of CSS3 features, some of which are not yet fully supported by non-webkit browsers.
It is my opinion that browser engines HAVE to go beyond from the standard in order to differentiate, and without that web technologies can never evolve.
Interesting post — especially for a Qt group!
>> Lately I’ve been working on a couple of exciting customer projects, involving HTML5-based UIs on embedded (TV) platforms.
Hey Jo,
awesome!!!
Works in firefox too.
Would love to see a combination of this + :
http://raphaeljs.com/
http://labs.trolltech.com/blogs/2009/09/18/qt-in-the-cloud-with-qwebclient/
regards
rn
I did something similar with QT 4.5 Embedded on an ARM-CPU:
Differences:
- Because of the amount of different screens, i’m loading them with AJAX in the main dom-node, to keep the memory footprint low
- every screen can have a custom javascript-file to execute special screenfuntions
- utility-qtclasses are connected to the javascript-namespace, to execute special functions.
- i’m using prototype, scripty2* for effects, and raphaeljs for SVG-Charts
regards
boecko
*scripty2 has builtin support for -webkit-transitions
@boecko: scripty2 seems really awesome. For some reason I didn’t come across it when I was doing my JS library research (my overlook).
Also the eBook they have on JS performance seems really interesting.
I hope in the future to offer integration of the Statechartz library with browser-compatibility JS frameworks like Scripty2/Dojo/jQuery and that bunch, but first of all I wanted to see if the core value is interesting to others
Comments on this entry are closed.