Search guides and the APICtrl K
  1. API reference
  2. Native GUI

gfx/text_editor.h

A single-line text field.

#include <sonore/gfx/text_editor.h>
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.

↑↓ to move↵ to openEvery public name in the headers, and every guide