Rapicorn Technology

Rapicorn is supposed to provide a suitable playground for experiments in consolidating the programming and design interfaces of existing GUI toolkits, and for exploring new GUI ideas, including also possible evolutionary failures. :-)

Lots of design decisions or techniques that Rapicorn employs can be found and have been pioneered in other toolkits, but it is also intentionally distinct in selected areas. In particular, Rapicorn tries to simplify structures and automate developer tasks wherever possible. Convenience in development and UI usage is a paramount design goal.

At the same time, Rapicorn attempts to incorporate all significant usability aspects for which open treatment is available. For a first summary of Usability guidelines and collections of further readings, see.

Fulfillment of the above development intentions comes at a certain cost. That is, implementation simplicity and maintainability is generally regarded higher than micro optimizations or creeping featuritis. Also, programming interface compatibility is prioritized much lower than in comparable other library projects. To compensate for possibly frequent programming interface changes, Rapicorn uses a versioning scheme that allows to reflect major, minor and patch level changes. The API is designed to be as small as possible, ideally just consisting of application data models and XML definitions to specify widget packing and widget properties.

The following list focuses on some of the selected areas where Rapicorn intentionally differs from other toolkits:

Micro-Widget-Composition
The main mechanism to construct composite widgets in Rapicorn is not by programming compositions, but by writing an XML definition that packs multiple micro widgets (GUI components with very limited event processing or drawing elements) together in different configurations.

Composite-Customization
Rapicorn allows customization of composite widgets as suggested in a Gtk+ Bugzilla comment, because by reusing the XML definitions of composites, users can easily alter all visible aspects.

Confined-Motion-Events
Confining motions to motion evens. Rapicorn delivers new pointer motion information in motion events only. All other event types just repeat the last motion event coordinates. This may result in occasional reports of 0-distance motions, but is easy to program with, since motion logic does not need to be replicated across handlers of multiple event types.

0-Distance Motions
If widget event handlers can handle 0-distance motions reliably (e.g. checking for 0 on divisions before doing d/(currentpos-lastpos) calculations), then scheduling (synthesizing) 0-distance motions for every widget state change (widgets becoming insensitive, hidden, loosing grabs, stacking order changes, etc) in combination with automatic enter/leave/cancel event generation can provide reliable widget updates and lay the foundation for paired event guarantees.

Paired-Events
Paired event delivery. Rapicorn event delivery maintains extra state information to ensure that all enter events are followed by their corresponding leaves and that button/key presses are always followed by either a corresponding release or a corresponding cancellation event. So no additional bookkeeping regarding paired events needs to be implemented by event handlers.

Single-Model-Selection
Single view, single selection. Most applications only need a single view onto their data model, and except for very rare exceptions, only a single selection set is ever needed per data model. So the data model framework used by Rapicorn might support multiple views but relies on the selection information to be provided by the model itself, and be supplied only once. This significantly reduces implementation complexity in various places and also avoids problem areas that emerge from application scripting if the scripts and all views don't share the same selection information. Beyond that, multiple selection user interfaces are unmanageable by non-expert users. It also is impossible to implement a consistent per-view selection metaphor, if the application specific model logic requires awareness of the current selection (like models for Piano Roll widgets).

Multi-Pointer
Multi pointer support. Rapicorn is supposed to work well in multi-pointer and multiple window focus scenarios that are currently being developed for X: MPX.

Size-Negotiation
Arbitrary size negotiations. It's not uncommon for GUI elements to have optimal and suboptimal aspect ratios (width/height quotient) for their layout sizes, or arbitrary width/height constraints. This is especially true for text elements which may break lines of text at quasi-random positions (e.g. word boundaries) and ellipsize overlong lines. Or GUI elements may be tailored to be layed out at specific heights, widths and ratios. Supporting arbitrary resizing constraints for an unlimited combination of possibly nested GUI elements can lead to unsolvable optimization problems and is thusly rarely supported by GUI toolkits. Rapicorn does support arbitrary negotiation constraints via a ``tune_requisition`` method that can retrigger the size requisition phase during the size allocation phase: bool tune_requisition (double new_width, double new_height); /* returns whether tuning was honored */ To cope with layout negotiation instabilities and endless resizing loops, the resizing logic in Rapicorn resorts to a simulated annealing variant, which is a probabilistic approach that can guarantee size negotiation termination. This approach is still highly experimental and different resolution strategies might be applied in future versions, the current implementation is summarized in a source code comment: resizing loop behavior.

Spreading Widgets
Most application windows have one main area of iterest (seldomly two or more), that is supposed to expand along manual resizes to the dialog. For instance a file selector will have one huge file list that's supposed to grow as the selector window is resized. Using the traditional horizontal/vertical box packing model with EXPAND and FILL flags, implementing such a layout requires the main resizable area and all ancestry containers to be packed with EXPAND|FILL behaviour. This can be very tedious to achieve and hard to track back in case of packing errors. To help with this situation, Rapicorn introduces HSPREAD and VSPREAD flags, which can be applied to such a resizable area. The spread flags will automatically propagate along the ancestry of a child widget and cause all containers to be treated with EXPAND|FILL packing behaviour. In case of undersized containers (happens when a widget is allocated less space than it requested), spread widgets will be preferred when it comes to shrinking the children into the available space. This allows sizing constraints to be passed through a deep widget hierarchy on to a resizable core widget, while keeping sizes in the vicinity intact. For instance, passing window-manager constraints (like screen size) through to the innermost resizable area in the above file selector example.