Make a textbox¶
Textboxes in Tick UI use the invisible-widget idiom.
ui.Textbox(...) claims input, updates the bound string, and
returns a layout struct holding the text, view, caret, and
selection-highlight rects so the caller can draw the visual itself.
To make a textbox¶
- Push a layout rect for the textbox.
- Build a
TextboxConfig. Start fromTextboxConfig.Defaultand override only what differs: - Declare an output layout struct.
- Call
Textbox. The call updates the bound string and fillslayoutwith the rects for text, view, caret, and selection. - Draw the visual using the layout rects:
- Background fill (or rounded fill).
- Selection highlight at
layout.HighlightRect. - Caret at
layout.CaretRect. - Text at
layout.TextRect(orlayout.ViewRectfor the clipped viewport). Draw the text fromlayout.RenderText, not from the boundrefstring. Refer to Render fromlayout.RenderText.
The full pattern¶
using (ui.Auto().Top(28))
{
var config = TextboxConfig.Default;
config.Font = "roboto_mono";
config.FontSize = 14;
TextboxLayout layout;
TextboxAction action = ui.Textbox("username", ref m_username,
config, out layout);
ui.FillRounded(backgroundColor, 4);
ui.PushRelativeRect(layout.HighlightRect);
ui.Fill(selectionColor);
ui.Pop();
ui.PushRelativeRect(layout.CaretRect);
ui.Fill(Color.white);
ui.Pop();
ui.PushRelativeRect(layout.TextRect);
ui.Text(layout.RenderText, config.Font, config.FontSize,
textColor, TextAlign.MiddleLeft);
ui.Pop();
if (action == TextboxAction.Enter)
OnUsernameSubmitted(m_username);
}
TextboxConfig fields¶
TextboxConfig carries every per-textbox knob:
| Field | Purpose |
|---|---|
Font |
Font name to look up through the resource provider chain. |
FontSize |
Font size variant. |
Filter |
A TextboxKeyFilter delegate that vets each typed character. |
ReadOnly |
Disables typing. |
IsNumber |
Restricts input to numeric characters. |
Padding |
A Margin applied around the text rect. |
CaretWidth |
Caret thickness in pixels. |
CaretTopBottomPadding |
Vertical padding inside the caret rect. |
CaretBlinkTime |
Blink period in seconds. |
TextboxConfig.Default provides reasonable values for every
field; override only what you need. Note the default Font is
"roboto_mono", which is not in the bundled DefaultTickConfig.
For projects relying on the bundled fonts, set config.Font to
"roboto_mono" (the bundled monospace font) or to a font registered
through your own GUIResourceProvider.
Selecting text with the keyboard¶
Holding Shift while moving the caret selects instead of moving: Shift+Left, Shift+Right, Shift+Home, and Shift+End all extend the selection from wherever the caret was when the run began. Releasing Shift and moving again collapses the selection, and shrinking a selection back onto its starting point leaves nothing selected.
Typing, Backspace, and Delete act on the selected range, so the keyboard reaches everything a click-drag or double-click selection does.
Shift is read directly from the input provider (GetShiftHeld), not
through TextboxBindings, so there is no separate action to rebind —
customising CaretLeft and friends changes the shifted variants with
them.
Focus and the action return¶
Tick UI tracks the focused textbox internally. Clicking a textbox gives it focus; pressing Tab or clicking elsewhere takes focus away. Type-input is routed to the focused textbox.
The Textbox call returns an TextboxAction:
| Value | Meaning |
|---|---|
None |
No state change this frame. |
Enter |
The user pressed Enter. |
Escape |
The user pressed Escape. |
Changed |
The bound string changed (any keystroke that produced a different string). |
Use the return value to commit on Enter, cancel on Escape, or react to every change.
To set focus programmatically, call ui.SetFocus("textbox_id")
from outside the textbox call.
Render from layout.RenderText¶
Both Textbox and TextboxSubmit fill layout.RenderText with
the live working buffer every frame, including any uncommitted
keystrokes. Draw the textbox from layout.RenderText. Under
TextboxSubmit, the ref string updates on Enter and
RenderText updates per keystroke. Drawing from layout.RenderText
keeps the textbox responsive between keystroke and Enter in both
modes.
The rule is the same in both modes, so the call site applies one convention:
Read
layout.RenderTextto render. Read theref textfor the value your program acts on.
Choose live or commit-on-Enter¶
Two methods set the contract on ref text:
ui.Textbox(...): live edit. The boundref textupdates per keystroke.Changedfires on each frame the string changes.Enterfires when the user presses Return.ui.TextboxSubmit(...): commit on Enter. The boundref textholds its value while the user types. Pressing Return commits the working buffer intotextand returnsEnter. The visible textbox stays live throughout, because rendering comes fromlayout.RenderText.
Choose the method by the contract you want on ref text. The method
name states that contract at the call site.
Pitfalls¶
The caret does not appear. : The drawing order is wrong. Fill the background first, then draw highlight, caret, and text on top.
Two textboxes share state.
: Both calls passed the same string ID. Use unique IDs, or wrap
repeated textboxes in PushID(item.Id).
Type-input goes to the wrong textbox. : Focus belongs to a textbox in a non-hovered panel. Click the visible textbox to give it focus, or audit panel input priority via Input and focus.
The configured font does not appear.
: The font name in config.Font is not registered with any
provider in the chain. Add it to a GUIResourceProvider. The
bundled DefaultTickConfig ships roboto_mono only.
Additional resources¶
- Make a button: the related invisible-widget idiom.
- State: why Tick UI owns focus state.
- Add a custom font: register fonts the textbox draws with.
- Compile flags:
ENABLE_INPUT_SYSTEMaffects how typed input arrives.