pub fn apply_text_bindings(
store: Res<'_, PropertyStore>,
q: Query<'_, '_, (&BindText, &mut TextContent, Option<&mut TextInput>, Option<&BindTextLabels>, Option<&TextFormat>, Option<&Focused>, Has<EditCommitted>), Without<ImeState>>,
new_binds: Query<'_, '_, (), Added<BindText>>,
committed: Query<'_, '_, (), Added<EditCommitted>>,
blurred: RemovedComponents<'_, '_, Focused>,
i18n: Option<Res<'_, AppI18n>>,
)Expand description
Copies PropertyStore[Global(name)] into TextContent for every BindText entity.
Entities whose property has no entry keep their existing text.
A BindTextLabels on the same entity says what to show for a value
instead of the value itself, which is how a closed <dropdown> reads
its selected option’s label while the signal holds that option’s
value. A value it does not name is written as it stands.
A TextFormat renders what is left for the app’s locale, through
the app’s own crate::i18n::AppI18n when the world holds one and
the process-wide crate::i18n::format hook otherwise. The per-app
handle is what keeps a process running two Lumen apps from writing one
app’s numbers in the other’s locale, the same reason the spawner reads
it. Labels come first: a label is what the element says for a value,
and only a value with nothing to say for it is a value to format. A
format the app has no formatter for, or text that is not what the
format expects, writes the text unchanged.
An app that changes locale while it runs re-renders every bound value
too: a <label format="number" bind-text="count"/> would otherwise
keep the old locale’s grouping until the next write to count.
Editing-protection gate: an entity is skipped while an edit is in flight on
it, meaning a focused TextInput or an active ImeState preedit.
Overwriting TextContent mid-edit would race the keystroke / IME path in
[crate::input::route_ime_events] and lumen_input::type_into_focused,
wiping the user’s in-progress typing or leaving the caret dangling past the
new (shorter) string. Focus alone is not an edit: a focused element with no
text buffer, such as the <dropdown> header the popup hands focus back to on
close, has no keystroke to protect and keeps tracking its signal. A write the
gate held back is applied when the field loses focus: the blur re-reads every
binding, so a handler that clears the signal clears the field once the user
leaves it, rather than leaving the typed text on screen. Enter in a
single-line field ends the edit too (EditCommitted): the field takes the
write it held back, and any write after it, while it keeps focus, so a
submit handler that clears the signal clears the field. When
apply_text_bindings does overwrite an entity, any co-resident
[TextInput.cursor] is clamped to <= new_text.len() so the cursor cannot
point past the buffer end.