UXApplication
UXApplication is the program. It boots the backend, owns the window list
and the menu bar, runs the event loop, and sits at the top of the responder
chain. An application’s main() is the same four lines on all six targets,
and the only platform-aware line is the driver choice:
void main(void) { UXApplication* app = new UXApplication(); app.setDriver(new UXWebDriver()); // the ONE platform-aware line Controller* c = new Controller(); app.setDelegate(c); app.run();}#use <UXKit>Overview
Section titled “Overview”Life starts in the delegate. run boots the driver, then calls
your delegate’s applicationDidStart, where you make windows, add views and
install menus. Return 0 to enter the loop. Any other value aborts the run
with that code. A delegate may call stop during start-up (a test, a
one-shot tool), and the stop is honoured.
protocol UXApplicationDelegate { i32 applicationDidStart(UXApplication* app); optional void windowDidResize(UXApplication* app, UXWindow* win, i32 width, i32 height);}The loop has two shapes, and your code sees one. On five of the six
backends, run() is the classic blocking loop: one event from the driver, one
dispatch, one coalesced repaint, repeat. On iOS, the platform owns the main
thread’s loop, so run() detects driverOwnsRunLoop() and hands the thread to
the native loop. Your delegate still starts in applicationDidStart (fired
from the platform’s own start moment) and your actions still fire, so the
app’s source is the same. This is the toolkit’s one sanctioned loop inversion,
and the driver handles it.
Repaints are coalesced. However many views called setNeedsDisplay in
one pass of the loop, displayIfNeeded repaints once, and
each window repaints only the union of the rects its views marked.
Closing windows is deferred. An action that closes its own window would
tear down the view whose event is still on the stack. Control actions
therefore use closeWindowLater, and the loop drains the
list once no window code is running. Closing the last window ends the run.
Resizes reach you after the toolkit is done. When the optional
windowDidResize fires, the native frame has finished its drag, the tree has
reflowed (springs and struts, see
UXView.setAutoresizeMask),
and the repaint has happened. Implement it only if you lay out views by hand.
Conforms to
Section titled “Conforms to”- Inherits
UXResponder, as the chain’s last stop.
Topics
Section titled “Topics”Configuring · setDriver · setDelegate · setMenuBar The loop · run · stop · isRunning · pump Windows · addWindow · closeWindow · closeWindowLater Screen · screenWidth · screenHeight Painting · displayIfNeeded
setDriver
Section titled “setDriver”void setDriver(UXViewDriver* d)Selects the backend. The parameter is the neutral protocol type, so a
library client (#use <UXKit>) can pass a driver without naming any backend
global.
setDelegate
Section titled “setDelegate”void setDelegate(UXApplicationDelegate* d)Sets the app’s owner. run() refuses to start without one.
setMenuBar
Section titled “setMenuBar”void setMenuBar(UXMenuBar* mb)Installs the bar. From then on the platform owns the drawing, tracking and pull-down, and a pick arrives as a neutral menu-select event routed to the bar’s callbacks.
i32 run(void)Boots, starts the delegate, then runs the loop (or the platform’s loop on iOS,
see the overview). Returns 0 after stop on the blocking backends,
1 if boot failed, 2 with no delegate, or the delegate’s own nonzero start
code.
void stop(void)Ends the loop after the current iteration. On iOS a stopped test app exits. A real iOS app does not stop, because the platform owns the process lifetime.
isRunning
Section titled “isRunning”bool isRunning(void)True between a successful start and stop().
void pump(i32 ms)Drains pending window messages (not input) and dispatches them. This is the primitive for waiting on the platform’s answer. Backends answer geometry asynchronously (report a content size, and the scrollbar that appears changes your work area), so a program that sets and then reads without a pump reads its own request back.
addWindow
Section titled “addWindow”void addWindow(UXWindow* w)Registers a window with the app. The first one becomes the key window. Call
this before open so events can route to the window.
closeWindow
Section titled “closeWindow”void closeWindow(UXWindow* w)Closes the window immediately. This is safe only when no code belonging to w
is on the stack. Key status moves to the first remaining window, and closing
the last one stops the run.
closeWindowLater
Section titled “closeWindowLater”void closeWindowLater(UXWindow* w)The safe form for control actions. It queues the close, and the loop performs it once the window’s code has unwound.
screenWidth / screenHeight
Section titled “screenWidth / screenHeight”i32 screenWidth(void)i32 screenHeight(void)The screen (or canvas, or scene) size the driver reported at boot.
displayIfNeeded
Section titled “displayIfNeeded”void displayIfNeeded(void)One repaint pass over every window that marked damage. The loop calls it each iteration, and modal driver paths call it so effects show during tracking.
Example
Section titled “Example”The smallest complete application, with the same shape on every backend:
#use <UXKit>
class App : Object <UXApplicationDelegate>{ weak:UXApplication* app;
i32 applicationDidStart(UXApplication* a) { app = a; UXView* content = new UXView(); UXWindow* win = new UXWindow(); a.addWindow(win); win.open((u8*)"Hello", UXGeom.make(20, 20, 240, 120), content);
UXButton* quit = new UXButton(); quit.setTitle((u8*)"Quit"); quit.setAction(&self.onQuit); content.addSubview(quit, UXGeom.make(80, 46, 80, 28));
win.tree.finalise(); win.displayAll(); return 0; }
void onQuit(UXControl* sender) { app.stop(); }}
void main(void) { UXApplication* app = new UXApplication(); app.setDriver(new UXGemDriver()); App* a = new App(); app.setDelegate(a); app.run();}