Is CSS the best metaphor for styling for a UIToolkit? Maybe not

Writing your own UI Toolkit is, if nothing else, educational. As the OpenPyro framework continues to evolve, every time a new feature is added, I look around at prior art in the domain and evaluate the choices made by different frameworks which has been fascinating. Of course, the first framework I look at (since I have had most experience with that) has always been Flex (both Flex 3 and 4 separatly since they are so different), but often I do compare that with choices made by the IPhone’s UIKit, HTML/CSS and (rarely) Swing or any of the Java toolkits.

One of the features that I know I will need to add in a future version will be a simpler way to style/skin the controls. OpenPyro controls are based around composition so creating new UI assets and passing them in as skin elements is simple enough but there is always a need to do something simpler. A blue scrollbar for example shouldn’t need blue assets, more the ability to tell the scrollbar to draw itself with a stroke/fill of blue color.

Flex’s choice in this domain has been CSS and thats not surprising. A lot of the way Flex was developed was to enable it to be a gateway drug to ActionScript for developers from other technology domains and who doesn’t know CSS? Flex 3’s CSS capabilities were very basic and I keep reading how Flex 4’s CSS engine is so much more complete. And considering how much easier it is to create a Flex 3 theme compared to a Look and Feel in Swing, that seems to have been a decent choice. Someone recently asked when OpenPyro would support that functionality which led to this post.

I have often found writing CSS for Flex a chore, for most of the reasons I find writing CSS rules boring: complete loss of any logic system. Deep in ActionScript land while developing an application, switching to CSS is irritating. Suddenly I am in a file where I cannot really code any logic or rules. One of the first libraries of ActionScript I wrote over 3 years back had explicitly defined style objects. For example, ScrollBars would have a corresponding ScrollBarStyle class that listed all style properties. Being a pure AS class, I could also code logic in that, so conditionally apply style properties because I could inspect the properties of the UI element the style was being applied to. Heck, I could even get code hinting of relevant styles for a particular component.

What spurred this post today was seeing how the engineering team I work with at Comcast Interactive Media adopting the Less CSS engine. I have personally not worked with this yet but I might in a coming sprint. By accounts so far, its awesome to work with and I completely don’t doubt that. Most of the logic here seems something that you can write pretty easily in pure AS3 classes and pass them around as something equivalent to Flex/Javascript’s CSSStyleDeclaration object (link to JS CSSStyleDeclaration object)

Anyway, the point of this post was, while CSS may be the most familiar styling metaphor, there may be better ones. I hope OpenPyro can probably adopt something more powerful like lessCSS rather than pure CSS.

Update: Another flavor of a *better CSS* system: SASS

Update 2: Smashing Magazine has a pretty good writeup on CSS ideas and debates. More food for thought as I spec out a styling language for OpenPyro.

On Toolkits vs Frameworks: Why not both and how OpenPyro does it

I was just catching up on Keith Peter’s blog and one of the posts that really caught my attention was on Toolkits vs Frameworks. The defining difference between the two, as Keith quotes Gamma, is “Toolkits do not attempt to take control for you…”.The Framework vs. Toolkit debate was in my mind when I started OpenPyro, but I feel I never stressed that enough so I felt it was worth a blog post.

OpenPyro was written in a way that it can be leveraged in either fashion. Lets take a few of examples:

The “Sprite” equivalent in OpenPyro is the UIControl, which does a few things like interpret percent based measurements, etc. It can also have a painter attached to it that can paint solid colors, gradients, stripes etc. So to create a gradient on a UIControl, all you have to do is:


var uic:UIControl = new UIControl();
var painter:GradientFillPainter = new GradientFillPainter([0xdddddd, 0xffffff]);
uic.backgroundPainter = painter

Now everytime the UIControl resizes, the painter repaints the gradient on its graphics context. However if you are not using a UIControl, and just plain sprites, you can leverage the painters again as so:

var sprite:Sprite = new Sprite();
var painter:GradientFillPainter = new GradientFillPainter([0xdddddd, 0xffffff]);
painter.draw(sprite, 200,200);

Now the painter paints the gradient on the Sprite’s graphics context. Its up to the developer to decide when to repaint the Sprite.

Here is another example with the layouts package:

var container:UIContainer = new UIContainer();
container.skin = new AuroraContainerSkin();
container.size(600,100);
container.layout = new VLayout(10);

var c1:UIControl = new UIControl();
c1.size(100%, 60);
container.addChild(c1);

var c2:UIControl = new UIControl();
c2.size("100%", 60);
container.addChild(c2);

In the above example, we have bought into the OpenPyro framework and just this code will let you create 2 control, position them vertically with a gap of 10px and automatically create a scrollbar since it will be needed ( The 2 children measure up to 60+10+60 pixels > 100px)

But the layouts package classes can be used for pure sprites too by using something like this:

var layout:VLayout = new VLayout(10)
layout.layout(sprite1, sprite2);

Similar examples can be drawn from the effects package etc. Also, OpenPyro has a fairly complete controls package each of which can be instantiated in a few lines of code as well completely independent of any framework dependencies. In fact almost all my tests are pure AS3 classes applying the package classes to non OpenPyro classes.

Optimized List: A pure AS3 List with renderer recycling

One of the things that the Flex List component does pretty well is handle large data collections (Arrays, ArrayCollections, etc). The List uses renderer recycling when displaying data, ie, it creates an itemRenderer only for the items that are displayed and not for each item in the dataProvider. As items scroll offscreen, the renderers associated with those data items are reused to render the new data that appeared on screen.

For the last few projects I have worked on Flex has not been an option because of file size concerns besides others which prompted me to start working on OpenPyro, a light weight Flex-esque framework and I have been pretty happy with it so far. However its List component is a far cry from Flex’s, implemented more like a Repeater, creating as many renderers as the length of the dataProvider, and as my new projects seem to get more data intensive, I started feeling a real need for a List that does the efficient renderer recycling that Flex does. Not finding any on the web, I decided to write one for myself.

The algorithm is as follows: The List creates an instance of a class called ObjectPool, which manages used and unused renderers. Whenever the List needs a new renderer, it asks the pool for a new one and when it does not need a renderer, it returns it to the pool. The pool tries to find unused renderers to satisfy the request for a new renderer and if it cannot, will create a new object and return that.

The core part of the logic resides in the onVerticalScroll function. The list always maintains a map of all visible renderers and as the scrollbar scrolls, the map is recalculated and renderers managed if the map is changed. The source and embedded example are the first stab at the implementation. The example renders an array of 200 values but ends up creating only the 8 or 9 renderers it needs to display.

The code is not complete but I am blogging it here so that if someone feels I am on a wrong track or should investigate a different approach, you can let me know.

http://www.arpitonline.com/blog/downloads/optimizedList/EfficientList.swf

It should be noted that this technique only works right now for fixed rowHeight lists. I haven’t thought of the variable height renderers yet, so suggestions on that front are welcome.

OpenPyro 0.4 released !

I am excited to announce the first official dot release (0.4) of OpenPyro, the open source UI framework I have been working on (on and off) for the last few months. All the information including source code, samples and documentation can be found at OpenPyro.org. I would love to hear some feedback as well. I am really hoping for this to be community powered and would love to integrate or help integrate more features into the framework, so if you are interested in the project and would like to collaborate, please feel free to contact me via blog comments, Twitter (http://twitter.com/arpit) or via the OpenPyro mailing list. And definitely take a look at the OpenPyro Wiki, which has a bunch of examples, samples and some concepts explained.

The biggest feature in 0.4 is the measurement and layout system that is pretty similar to Flex that I love and a fairly decent component set. Because all OpenPyro components use composition rather than inheritance, I am really hoping to build something very Flex4-esque but keeping filesize . Am also hoping to keep the core library pretty small and create a comprehensive library of functionality using plugins, basically libraries whose functionality depends on OpenPyro but not the other way around. For a full set of development themes check out the section here on the wiki.

I have been writing about OpenPyro on this blog for the last few months as well, all those posts can be found here

Hopefully this can grow into a body of code that the community finds useful.

OpenPyro now being ported to Haxe. Can you help ?

Its really awesome to see community interest in OpenPyro, the Flex-lite framework that I have been working on for the last few months. The latest news on that front is an effort to port OpenPyro to HaXe, an open source programming language that can be compiled to a variety of languages like Flash, Javascript, PHP etc by Don-Duong Quach. Don evaluated OpenPyro and has started a Git repository on the porting effort. He was even able to compile a previous example I had built with OpenPyro to a Haxe version which you can find here.

Its really exciting to see this work. My own knowledge of Haxe is minimal so I can’t be as helpful as I would like to be, but if there are other HaXe developers out there, your help in the effort would be really appreciated. The conversation around the port is happening at the OpenPyro mailing list.

In other news, OpenPyro finally has an official home at OpenPyro.org. I am going to start posting architecture documents and examples there. The latest can be found at the OpenPyro wiki and the OpenPyro asdocs page.

OpenPyro wiki updates, and plans going forward

I have been talking a bit around OpenPyro quite a bit in my recent blog posts but I wasn’t sure if the project was gaining traction until MAX SF this year where I actually had more than a few conversations around OpenPyro. Oh wow, that was awesome! But I realize we haven’t been doing a great job communicating progress or direction around this project, or gathering feedback. So I spent a few hours today writing up the Intro and the Development Themes pages on the OpenPyro wiki. Both are also linked off the main project page here.

Please take a few moments to read the pages. If you are interested in this project in any capacity (influence direction, mark bugs, request features or contribute code), please join the OpenPyro google group. To make it even simpler, I am including an inline subscription box here:

Google Groups
Subscribe to AS3 Pyro User Group
Email:

Visit this group

On our side we are going to be busy being even more transparent, by doing things like public code reviews (we use ReviewBoard within CIM and are going to have a public version of it soon).

OpenPyro is definitely a community project and if you have code that would benefit OpenPyro, we would love to include it in our code base.

Thanks and happy coding.

Simple OpenPyro example with source: Image Viewer

Work on OpenPyro goes well, and I keep getting people asking me for examples of the framework in use. After receiving another request today on an OpenPyro example, I figured I’d write a quick widget and release it with the source. So check out this very simple Photo Browser app. The source can be found here. The application is simple on purpose but shows some parts I want to highlight. The widget is a List module on one side and an Image container inside another container on the other side. As you click on a list item, the source of the Image component changes. Here are some key parts of the code:

Measurement:
This of course is the main thing I worked on in OpenPyro. In the main class, the shell lays out a header and a PhotoModule component and a Spacer vertically using a VLayout object. The PhotoModule is sized by setting its percentWidth and percentHeight to 100, and the layout does the rest. Pretty sweet.
The List component within the PhotoModule class is sized similarly with a width of 200 and the ScrollPane is sized at 100% of the unused space.

List with custom renderer:
The List module implementation here is also an interesting example that shows how a List module can work with custom renderers. The code looks like:

[AS]
var list:List = new List();
var itemRendererFactory:ClassFactory = new ClassFactory(DefaultListRenderer)
itemRendererFactory.properties = { percentWidth:100,
height:30,
rollOutBackgroundPainter:new FillPainter(0x444444),
labelFormat:new TextFormat(“Arial”, 12, 0xffffff)}
list.itemRenderer = itemRendererFactory;
list.dataProvider = picData;
list.layout = new VLayout()
list.skin = new AuroraContainerSkin()
list.width = 250;

var listPainter:GradientFillPainter = new GradientFillPainter([0x222222, 0x111111])
listPainter.rotation = Math.PI/2

list.backgroundPainter = listPainter
list.percentHeight = 100;

addChild(list);

[/AS]

Automatic scrollbar creation on containers
The module on the right that shows the photo is basically just an Image control within a UIContainer. If you click on the Asterix photo, the photo is bigger than the container and the container automatically puts the scrollbars in. Its also important to realize that the only reason the photo became bigger than the containing UIContainer was because the image did not have a width,height assigned to it. In that case, all UIControls default into a child based measurement strategy and their sizes are determined by the children they contain.

Using BackgroundPainters
I love the backgroundPainter api on the basic control (UIControl). In one or two lines, you can set the entire look of a component. The code looks something like:

[AS]
var bgPainter:GradientFillPainter = new GradientFillPainter([0,0×333333]);
bgPainter.cornerRadius = 10;
bgPainter.rotation = Math.PI/2
shell.backgroundPainter = bgPainter;

[/AS]
If the shell in the above case resizes, the painter is re-triggered and repaints correctly.

FileSize
Once again the killer part of the framework is the file size. This example is about 21 K.

There is a lot of stuff here I am pretty proud of, but again, it still needs a lot of work. If you are interested in the project and are coming to MAX San Francisco this year, I would love to meet you. My twitter id is @arpit.

me

See you at Max