gfx/text_editor.h
A single-line text field.
#include <sonore/gfx/text_editor.h>- 1type
- Guides: The native editor
On this page
Design notes
Why a plugin needs one
Naming a preset. Typing a cutoff instead of hunting for it with a knob. Searching a sample list. Every one of those was free in a webview and impossible in the native UI until the component tree learned about keys.
Single line, on purpose
A multi-line editor is a different object: it needs line breaking, a scroll position, up and down between lines, and a selection that spans them. Almost nothing in a plugin wants that, and pretending one class can be both is how a text field ends up mediocre at the job it actually has.
Where the text lives
As UTF-32 code points, not as a UTF-8 std::string. Every operation a caret performs -- move left, delete forward, select a range -- is defined on CHARACTERS, and doing that on a UTF-8 buffer means every one of them has to walk continuation bytes. Getting that wrong does not crash; it splits a character in half and leaves the field showing a replacement glyph, on somebody else's keyboard layout, where nobody testing in English will ever see it. Converting at the edges costs a copy on setText and getText and nothing anywhere else.
Composed text
An input method's composition (text_input.h) is shown at the caret, underlined, and is not part of the value until it is committed: getText() never includes it. Everything that DRAWS -- paint, the caret, the scroll -- works on the shown text; everything that EDITS commits a composition first and then works on the committed text, so there is one string being edited at a time.
Types 1
class TextEditor : public Widget, public TextInputTarget
An editable single-line text field. It has the reference's TextEditor's name and its single-line use; the multi-line one here is TextArea. The file comment says why, and how the text and an input method's composition are kept.
Text goes in and out as UTF-8; a pasted line break becomes a space. setText does not notify unless asked. A typed value is committed on onReturn AND on onFocusLost -- listen to both, or a value typed and then clicked away from is lost -- while onTextChange fires on every keystroke. Message thread only.