Rapicorn - Tech Bits

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 http://beast.gtk.org/wiki:UsabilityGuidelines.

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 employs a specially tailored versioning scheme, and the actual API is designed to be as small as possible, ideally just consisting of application data models and XML definitions to specify gadget packing and gadget properties.

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

Micro-Gadget-Composition

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

Composite-Customization

Rapicorn allows customization of composite gadgets 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.