Table of Contents
Widget Queues
The queues are ordered by the execution order on a global queue flush.
Element Queue
As a DOM based javascript toolkit, qooxdoo needs to dynamically create DOM-Nodes and configure them (attach styles and classnames, events, names, ids, ...). Each widget which should be created informs the global element queue manager to add itself to the queue.
qooxdoo is currently not able to (re-)use already created elements. This means you can not use elements from the HTML-document and “transform” them into qooxdoo widgets.
State Queue
The state queue is one of the parts of the new behaviour idea. It contains all widgets which have had a change in state. Before the rest of the layout, the state queue will be flushed and apply new color, border, and other styles to widgets depending on whether the widget is focused, selected, leading or whatever. In the flush, as application developer, you can also define the handle the combinations (focused and selected could be styles differenly from focused and not selected) of current selected states. This easily gives many more possibilites as you are able to get with complex css rules if we use classnames as in previous versions of qooxdoo.
Job Queue
In previous versions of qooxdoo we sometimes had the problem that we needed to modify multiple properties of a widget at once. In some widgets the modifiers depend on each other. Especially then and sometimes in other scenarios, too, the multiple update of the widget required by this type of implementation has a negative impact on the overall performance of the whole application.
The new job queue fixes this problem. This queue allows the modifier to simply add a job to the queue. It will be handled by the next flush of the queue. Each modifier can - as before - do its job and directly update the widget. For all properties which apply complex layout changes or which have impacts on other properties, the “auto” sizing or the inner and outer dimensions of the widget we recommend that the modifiers use the job queue.
Each job entry in the queue can be transferred to the layout queue. Also, the combination of jobs can be used to add layout todos. For example the property “orientation” could impact the outer and inner dimensions of the widget (if it is sized “auto”). There is an intersection with the property “horizontalAlign”. Both of them would affect the layout of the children. So it is better to wait and apply both properties at once.
Layout Queue
qooxdoo comes with two layout queues. As the development continues this has been overthought and is in our current opinion incorrect. In the current CVS version we have a combined layout queue which applies the values for the x- and the y-axis at the same time. This was especially needed for some richer layout controls like the QxFlowLayout and the QxDockLayout.
The layout process is again able to group property changes together. In Internet Explorer there is no style support for limiting dimensions (minWidth, maxWidth, ...). So we need to work around missing functions in qooxdoo sometimes.
Imagine you change both at once, the width and the minWidth property of your qooxdoo widget. Each change normally will lead to a re-evaluation of the applied width. We need to manually limit the applied width for the Internet Explorer to be sure that it will never be smaller than the defined minWidth. Without the layout queue the style of the widget would have to be updated twice, not just once. The resulting speedup might seem negligible but in big and complex applications built with qooxdoo these are some of the things that could improve performance.
The layout jobs are stored inside each widget. After some reworking of the codebase, we found this to be the best solution. It allows the qooxdoo user to move children from one parent to another without losing any job information or the need to transfer them to another parent.
If you add a layout job to any axis the widget will register itself to its parent widget. This registering to the parent also occurs if you add a child (which already has layout jobs) to a widget. This means each instance of QxParent has one layout queue for all layout tasks of itself and its children. If a child gets a layout job it will ask the parent to add the job to the parent’s queue. The parent then adds itself to the global layout queue. Somewhat complex?
You might already be asking, is this complexity needed? You think that it should be possible to handle this in an easier way? Well, we thought the same. For some lightweight layout API and small requirements this would be appropriate and overhead would be minimal if you only code really small qooxdoo applications. But qooxdoo has to include a full-blown layout engine to allow you to do all kinds of crazy things. For example, we have experienced that it is best to give the parent widget full control over the order in which the children will be laid out. This is because sometimes the widgets in a layout (the layout of the parent) are depending on each other. Simply think about a box layout where some widget in the middle changes its width. If the box layout is centered you have to move all children to their new positions.
Display Queue
If the layout of the widget includes the “initial” layout job (which will be added through the creation of the element node or the move of the element to a new (visible) parent) then this widget will be added to the display queue of qooxdoo. The display queue is “only” responsible for showing and hiding widgets in the fastest possible way.
The display queue appends a widget element to the parent element node. qooxdoo first tries to insert the children into each other before adding them to higher-level widgets (the instance of QxClientDocument or any already visible widget from any previous flush).
Examples
First you define a new widget
var myWidget = new QxWidget;
and then you add it to the client document (or any other widget). In the context of QxApplication you can simply use the following (as seen in many examples in the qooxdoo distribution):
this.getClientWindow().getClientDocument().add(myWidget);
It is important to understand that this will only define the parent widget of the newly created instance and push the widget to the job queue (with a job named “initial”). Now you configure some properties important for its visual appearance:
myWidget.setWidth(100); myWidget.setHeight(100); myWidget.setBackgroundColor("red"); myWidget.setBorder(QxBorder.presets.black);
This will add the following jobs to the job queue:
- width
- height
- borderX
- borderWidthX
- borderY
- borderWidthY
There is no job “backgroundColor”. The color of the widget will be directly applied because it has no other impact on other widgets (through dimension changes) and properties. The border change will be split into x and y-axis pieces. The modifier of the border property is smart enough to detect the “real” visible changes and only add those to queue.
Modification of the width adds both jobs “width” and “height” to the job queue. The change of the border adds the other four jobs. The borderWidth* jobs will be added because the old border size (0 pixel) is different from the new one (1 pixel). The border* jobs only define that there is a visible change of the border for this axis.
Remember: The modifier is able to compare the old and the newly stored values, too. This allows the modifier to only add the borderWidth* jobs if you really change the border width. This also works with the already created border instances which you can find in QxBorder.presets.
After flushing the job queue, the jobs will be transferred to the layout queue. Then the layout jobs will be flushed. The display queue will finalize the flush of the queues.
