Skip to content

UXTextField

UXTextField is an editable field that contains no text-editing code. The field gives the backend a buffer, and the platform’s edit engine does insert, delete, arrows, the caret, and per-position validation. The engine is GEM’s objc_edit, an NSTextField, a Win32 EDIT, a UITextField, an EditText, or a GtkEntry. UXButton follows the same rule and contains no drawing code: the toolkit does not re-implement what the platform already does.

Whatever edits it, the buffer holds the current text. Native backends sync it before announcing a change, so a change handler always reads what the user typed.

#use <UXKit>
UXTextField* name = new UXTextField();
name.setPlaceholder((u8*)"Full name");
name.setOnChange(&controller.onNameEdited);
content.addSubview(name, UXGeom.make(8, 8, 180, 24));

The change hook fires on every keystroke, after the buffer is synced:

void onNameEdited(UXTextField* sender) {
validate(sender.text());
}

For a password, choose the secure treatment before attach, because the native control type is selected at realization:

UXTextField* pw = new UXTextField();
pw.setSecure(true);
  • Inherits UXControl: geometry, enablement, first-responder focus (focus is the caret).

Text · text · setText Change reporting · setOnChange · fieldDidChange Treatment · setPlaceholder · setSecure · setValidation

u8* text(void)

The buffer itself, which every editor operates on.

void setText(u8* s)

Replaces the content (clamped to capacity), places the caret at the end, and marks the field dirty. It does not fire the change hook, since the code that sets the text already knows about the change.

void setOnChange(callback c void(UXTextField* sender))

A per-keystroke change hook. Like every action it is a callback, so the field never owns its controller, and the hook stops firing if that controller is released. When it fires, the buffer is already synced; read sender.text().

void fieldDidChange(void)

The single announcement path. Every backend calls it after its native field changes (with the buffer synced first), and GEM’s neutral edit path calls it directly. It also feeds the event tap (UXEventTextChanged) with a copy of the text, because a recording must hold what was typed at that moment, not what the buffer contains later.

void setPlaceholder(u8* s)

A grey prompt shown while the field is empty, where the platform supports one. Set it before or after attach.

void setSecure(bool on)

Masks input as a password. Set it before attach, because the native control type is chosen at realization.

void setValidation(u8* v)

A validation string with one character per input position: 9 digits, A upper case and space, a letters, X anything. The edit engine enforces it on every keystroke with no extra code.

UXTextField on the web backend

The theme’s field bezel with the shared edit engine’s caret, drawn on canvas with the same Aristo art as GEM.

A validated numeric field with live feedback:

UXTextField* port = new UXTextField();
port.setPlaceholder((u8*)"Port");
port.setValidation((u8*)"99999"); // five digit positions
port.setOnChange(&controller.onPortEdited);
content.addSubview(port, UXGeom.make(8, 8, 80, 24));
void onPortEdited(UXTextField* sender) {
apply.setEnabled(sender.text()[(i32)0] != (u8)0);
}