UXNib
UXNib loads an interface from a .rsc file. The rest of the design follows
from one property: there is no inflation step.
#use <UXKit> // or #import "UXNib.xc"Overview
Section titled “Overview”A GEM resource already contains an OBJECT tree, and a
UXView is backed by an OBJECT. Loading a
nib means loading that tree and binding a view onto each entry. Nothing is
copied or rebuilt, and on GEM the AES walks the resource’s own array
directly.
Rocks (macOS) --writes--> app.rsc --load--> OBJECT[] --bind--> UXViewTreeThe resource editor is the interface builder. A dialog designed there becomes a live view hierarchy with no conversion, rather than a description that a loader reconstructs.
UXViewTree* tree = UXNib.load((u8*)"app.rsc", 0); // tree 0 of the fileViews are chosen by ob_type. The resource supplies the type, frame, flags
and state; your code supplies the behaviour.
Wiring by name
Section titled “Wiring by name”Loading gives you a hierarchy. Connecting it to a controller is the other half, and it needs no per-application code:
UXViewTree* tree = UXNib.loadWired((u8*)"app.rsc", 0, (UXDesignable*)controller);loadWired reaches your controller through
UXDesignable and connects the nib’s
outlets and actions by name.
Your controller declares, the compiler generates
Section titled “Your controller declares, the compiler generates”class MainController : Object{ outlet UXLabel* statusLabel; outlet UXView* canvas;
void onSave(UXControl* sender) :action { … } void onQuit(UXControl* sender) :action { … }}Declaring any outlet field or :action method auto-conforms the class to
UXDesignable, and the compiler generates both method bodies from the
decorations:
setOutlet(name, value): a checked assignment per outlet, returning false on an unknown name or a type mismatchwireAction(name, control):control.setAction(&self.<method>)per action
There is no reflection beyond what the decorations declare, and the compiler checks every connection. A nib naming an outlet your controller does not have fails at load with a false return, instead of leaving a null field that crashes later.
Topics
Section titled “Topics”load · loadWired · loadWiredMem · loadDoc · viewForType · make · registerViewFactory · registerObjectFactory · classOverride
static UXViewTree* load(u8* path, i32 treeIndex)Loads one tree from a .rsc file and binds views onto it. A resource holds
several trees (a dialog, a menu, an about box), addressed by index.
loadWired
Section titled “loadWired”static UXViewTree* loadWired(u8* path, i32 treeIndex, UXDesignable* owner)load, then connect outlets and actions on owner by name.
loadWiredMem
Section titled “loadWiredMem”static UXViewTree* loadWiredMem(u8* data, i32 len, i32 treeIndex, UXDesignable* owner)The same from bytes already in memory: a resource compiled into the binary, or fetched rather than read from disk.
loadDoc
Section titled “loadDoc”static UXViewTree* loadDoc(pointer doc, i32 treeIndex, UXDesignable* owner)From an already-parsed document, when you load several trees out of one file and do not want to re-read it per tree.
viewForType
Section titled “viewForType”static UXView* viewForType(u16 gtype)The default type-to-view mapping: G_BUTTON becomes a
UXButton, G_FTEXT a
UXTextField, and so on.
registerViewFactory
Section titled “registerViewFactory”static void registerViewFactory(pointer fn)Overrides the mapping, so a resource object can become your view subclass instead of the stock one. A custom widget designed in the editor comes back this way as the class that implements it.
registerObjectFactory
Section titled “registerObjectFactory”static void registerObjectFactory(pointer fn)The same for non-view objects named by the nib.
static Object* make(u8* cls)Instantiates by class name, through the registered factory.
classOverride
Section titled “classOverride”static u8* classOverride(pointer doc, i32 ncl, i32 tree, i32 obj)The class name a resource records for a particular object, when it wants
something other than the default for that type. This is the stored form of
“this button is a FancyButton”.
Two things to know before you rely on it
Section titled “Two things to know before you rely on it”The resource owns the layout; you own the behaviour. Frames, flags and initial state come from the file, so moving a control is an edit in the editor instead of a recompile. Anything you set in code after load is overwritten on the next load, because the file is the source of truth for those fields.
A tree index is positional. Trees are addressed by number, not name, because
.rsc does not store tree names. If you delete a tree in the editor, every index
after it shifts. Rocks renumbers the links it owns, but you must keep any index
hard-coded in your source correct.
See also
Section titled “See also”UXDesignable: the two generated methods, and theoutlet/:actiondecorationsUXNibV2: the newer format, with variants per form factorUXViewTree: what a load producesUXView:adoptObject, the binding step