The object hierarchy contains all 'existing' objects. The root object is
called the universum, it's sons are documents and/or
libraries (which are, in fact, the same). Their sons are Top Level
Objects (called also library objects). This all is called the
namespace and the contents are of type struct obj
. TLOs'
sons are graphic objects and instances of TLOs, these are of type struct
go
.
The things contained in the universe -- objects and grahic objects -- have a common type called 'o'. This type is implemented by a structure containing one number only, the kind of the thing, i.e. object or GO. Thus we can easily find out the kind of the general thing.
The structures o
, obj
and go
have the
same beginning so that typecasts are possible.
Every object lives somewhere. Having been created, the object lives in the temp. The user can then choose to link it somewhere in the universe (and make it 'existing'). And unlink it again sometimes; the unlinked object are in the temp as well. At the end of a transaction, temp is cleaned and these non-linked objects are moved to the zombie. As zombies they can be deleted as soon as their reference count becomes zero.
If the object has some sons, the whole subtree is moved.
Geometric paths are contained in graphic objects (probably something like
go_path
). It is possible to construct a 'superpath' consisting of
several such paths with a common color, fill style etc. This is implemented by
another go -- a goset :-) It lives in the dependency hierarchy as well
and it is dependent on all GOs contained in it, but does not have any own
hangers.
Thus, a 'superpath' consists of some paths, which are invisible, and another "virtual" GO with no own geometry but with some graphic properties and combining the data of all the contained paths. But there is no extra data structure for a superpath.
Every object has a property structure. The structure is an ordinary list now, but might change into a more sophisticated hash table sometimes.
Properties have a name (which is stored in a String), type (unsigned int, pointer
or String), and value stored in an uintptr_t
. So far we identify
the property by both the name and type.
There is a bunch of functions working with properties, using a String or
char *
as the property name, and each in several versions for all
the possible value types. Lookup functions return the value passed as
err
if the property is not found.
TODO: We have not decided whether the property name should be unique or the pair (name, type) should be the key.
Hangers and anchors provide the interface for dependencies of GOs. Every
graphic object has some fixed number of hangers, each with a fixed meaning. For
example, go_segment
has two hangers, each for one endpoint of the
segment. The hangers of GOs are thus part of the particular GO itself.
However, they have node pointers for lists to enable easy recursive walks for
updates.
On the other hand, the inner hangers of a TLO -- mouse-clicks and input hangers -- are created and deleted dynamically and their number is not fixed.
Hangers are not explicitly typed, but we distiguish mouse-clicks, (hangers independent of any objects, contained in a TLO) and other hangers.
Hooks are used to inform about some important events in the kernel structures. We have hooks for objects, hooks for GOs and (TODO:what else?). You can add and remove your functions to be called on these events.
Each object/GO has a list of its hooks. The hoook contains pointers to functions handling all possible events (or NULL) and one extra pointer to any additional data. Object hooks are son link, unlink, selected and unselected. The unlink hook is called before the object is actually unlinked.
The hooks of GOs are not stored in the GOs themselves, but in their parent TLO; so the hook applies to events for all GOs within the TLO. They are link, unlink, selected and unselected.
All hooks are local, i.e. never called recursively.