EtoileUI is a core part of Étoilé along LanguageKit and CoreObject. EtoileUI provides a uniform Graphics and User Interface model, to all Étoilé applications, that sits atop the GNUstep or Mac OS X AppKit.
This Graphics model is a basic and extensible Compound Document model where User Interfaces and Graphics Documents shares the same representation.
Write Less Code
The Compound Document support put aside, EtoileUI was created to make writing applications much easier and quicker than existing UI toolkits. Another idea was to support exploratory UI development and treat each application as a live or permanent UI prototype. As such, it comes with many high-level abstractions and UI patterns that just work out of the box without writing any code such as:
- tools (move, selection, paint bucket etc.)
- actions (grouping, ungroup, reordering etc.)
- selection-based behavior
- rubber-band selection
- resize handles
- presentation options (scaling, margin etc.)
- pane-based presentation
- template-based presentation
- form-based presentation
- icon view
- drag and drop (and copy/paste)
- model/view inspectors
All these things combined together makes possible to write full-fledged Object Managers and Graphics Editors in 1000 lines of code.
Note: The CoreObject integration is very limited currently and the end-user Compound Document orientation is work-in-progress. In other words, a layout item tree cannot be persisted transparently at this point and undo/redo support is not built-in.
Layout Item Tree and Aspects
EtoileUI is a high-level UI toolkit where elements visible on screen are abstract/semantic nodes (leaf or branch) to which pluggable aspects can be bound. Which means the same uniform tree structure is used to describe any kind of structured content (Compound Document, UI etc.) and the role of each node can be entirely changed at runtime by changing the bound aspects.
The nodes are called:
- layout item (leaf)
- layout item group (branch)
Which are usually customized with one ore several aspects:
- represented object (the object for which the item provides a visual representation on screen)
- style (how the item draws)
- action handler (how the item reacts to actions such click, paint, select etc.)
- layout (how the layout presents its children, but can also be used as mechanism to inject/compose another item tree into a node, apply temporary aspects to the children, or reuse complex widgets such as tree view, column view etc.)
- view (an optional widget, so you can reuse existing widgets provided by a low-level UI toolkit such as the AppKit)
- decorator (an item which decorates another item without changing the tree structure. e.g. window, scrollable area, title bar etc. Presently decorators are mostly a mean to reuse the equivalent widgets provided by the AppKit.)
- controller (a coarse-grained controller put in charge of an entire subtree. e.g. filtering, sorting, editing validation etc.)
From an MVC perspective, the represented object is the model, the layout item is a very fine-grained controller (which can supervised by a more coarse-grained controller higher in the item tree) and the other aspects are the view.
Unlike usual low-level UI toolkits which provide monolithic views/widgets that mix all the concerns (event, drawing, layout etc.) together, EtoileUI treats each concern as a pluggable aspect and new visual component can be built by specializing and combining various aspects together.
Tools and Input-device Independence
You can also attach a tool to a layout. A tool turns the input device events into semantic actions which are passed to the action handlers (e.g. Selection tool, Basic arrow tool, Zoom tool, Brush tool etc.)
In a running application, there is always an active tool in charge of dispatching the events.
In future, we plan to support scenarios where multiple tools are interacting at the same time. For example, multiple pointers per user or collaborative editing where each user edits the document with his own tool.
For example… At runtime you can change the root node layout which uses windows initially to a tree view, rearrange the layout item tree structure, then switch back to the normal window-based layout. All aspects in the tree structure can be changed in this way (usually through inspectors or with the LanguageKit workspace).
In addition to the pluggable aspects, it's also easy to manipulate the tree structure at runtime because all the layout items and aspects (including controllers) can be copied/cloned.
Which means in a running application any elements on screen can be copied as you would usually do it in a GUI builder. This is used in various places to generate items at runtime based on a template item.
e.g. to support multiple browsing windows in a file manager, you can set the layout item that corresponds to a file manager window as a template item of the window layer controller. Then each time the window layer controller receives the message 'new', it copies this template item and inserts the copy as a child and you get a new window.
Pick and Drop
When you combine the uniform tree structure with the possibility to clone subtrees arbitrarily, we get the ability to support drag and drop and copy/paste without writing code inside a running application. It's a just matter of moving/copying the nodes in the tree.
For the fun… You can turn on drag and drop everywhere in a running application to rearrange the UI through direct manipulation.