My last post about stdgui was over 5 months ago. Although family life has been busy I have not been entirely idle.
I have concluded that the existing GUI frameworks don't meet
the goals of stdgui. The project will proceed.
However, a few months ago I sat down with my prototype "SnapLayout" layout system and attempted to layout a simple example. I was surprised at how much mental effort it required. Granted, it had been awhile since working with SnaypLayout and I was probably a bit tired but I got the same feeling of tedium I've had in the past trying to mix-n-match layout managers to get the desired look. SnapLayout is perhaps only marginally better than the status-quo. I want a true advancement.
I started pondering: what if we could specify exactly how widgets align to each other with some sort of declarative syntax. I came up with something like this:
---
lblTemplate
|lstTemplate
|btnShowBanner|
---
CenterV: lblTemplate lstTemplate
Top: lstTemplate txtMessage
lblMessage txtMessage|
lblColor selColor
lblSpeed rdoSlow
rdoNorm
rdoFast
chkReverse
Right: lblMessage lblColor lblSpeed
Left: txtMessage selColor rdo* chkReverse
FillH: txtMessage
lstTemplate fraPreview|
btnShowBanner
fraPreview {
|lblPreview
}
Here's the idea. A block such as:
---
lblTemplate
|lstTemplate
|btnShowBanner|
---
means:
- the top of lblTemplate aligns to the parent window top edge (---).
- the top of lstTemplate aligns to the bottom of lblTemplate
- the left of lstTemplate aligns to the parent window left edge
- the top of btnShowBanner aligns to the bottom of lstTemplate
- the left and right edge of btnShowBanner aligns to the parent window left and right edge, respectively.
I call this an "implicit block". I think it's a pretty concise expression of intent and fairly intuitive for programmers who read left-to-right and top-to-bottom.
Next we have explicit constraints such as:
Right: lblMessage lblColor lblSpeed
which means: align the right edges of lblMessage, lblColor and lblSpeed. Explicit constraints are used to express that which cannot be expressed in an implicit block.
The only thing I don't like is having to give a name to every widget.
With this concept in mind I started trying to design an algorithm to render such layouts. After a few fruitless weeks with pen and paper I had to give up. I was out of my depth.
Thankfully, some lucky online searching pointed me in the right direction. Such problems are known as
Linear programming and algorithms have already been developed for solving systems of linear equations of the type found in user interfaces. Specifically the
Cassowary Constraint Solving Toolkit.
Here I thought I was exploring revolutionary territory. Not so! Apparently there have been a wide number constraint-based UI layout tools over the past few decades. My question is, why didn't they take off? Why don't we see them in popular toolkits? Perhaps it's finally starting to take hold because in 2011, Apple integrated Cassowary into their interface builder (see
AutoLayout). Also a new python-based framework called
enaml uses Cassowary.
With Cassowary in my toolchest I've begun prototyping a layout system based upon the above syntax. So far I have the parser working (thanks to
Lemon) and I'm able to isolate all the distinct lines which widgets align to.