pub struct TextInput<'a> { /* private fields */ }Expand description
A single-line editable text field: the stateless drawing half of TextInputState, the
same split List has with ListState.
Draws state.value() (masked with mask if set, or placeholder while state.value() is
empty), scrolled horizontally by state.scroll() and clipped to surface.area()’s width,
with a caret cell at the cursor’s display column. Neither scrolling nor the caret’s column is
byte- or char-based: both go
through retroglyph_core::text::width_usize, the same display-width measurement
truncate uses, so a value containing a double-width character
(CJK, most emoji) still puts the caret in the right screen column.
This widget does not call TextInputState::ensure_visible: like
List/ListState::ensure_visible, that’s
the caller’s job, once per frame, with the actual current field width (which can change on
resize).
The caret always renders as an inverted-color cell (caret_style), not by driving a real
terminal cursor via a backend’s Cursor facet: render only has a Surface, not a
Backend, and a cell-drawn caret renders identically (including in headless snapshot tests)
on every backend. An app that wants a blinking, backend-native caret instead can position
one itself from state.cursor()/state.scroll() alongside this widget.
As an InteractiveWidget, sense is Sense::click: a click
(or Tab) focuses the field the same way it would a Button, via the shared
Interaction’s FocusRing.
Routing keystrokes to whichever field currently holds focus is still the app’s job, via
TextInputState::handle_event: InteractiveWidget::render never sees raw input events,
only the already-resolved Response, so it can’t do that itself. What Enter does,
validation, and layout are the app’s job too. IME/text composition and multi-line editing are
out of scope for this crate entirely.
§Examples
use retroglyph_core::grid::{Grid, Rect};
use retroglyph_ui::state::TextInputState;
use retroglyph_ui::widget::{StatefulWidget, TextInput};
use retroglyph_ui::Surface;
let mut state = TextInputState::new();
state.set_value("hello");
let area = Rect::new(0, 0, 10, 1);
let mut grid = Grid::new(10, 1);
TextInput::new().render(&mut Surface::new(&mut grid, area, 0), &mut state);Implementations§
Source§impl<'a> TextInput<'a>
impl<'a> TextInput<'a>
Sourcepub fn new() -> Self
pub fn new() -> Self
An empty-placeholder, unmasked text input, styled from Theme::DARK (as if
TextInput::theme had been called); call TextInput::theme/TextInput::theme_on
for a different Theme.
Sourcepub const fn placeholder(self, placeholder: &'a str) -> Self
pub const fn placeholder(self, placeholder: &'a str) -> Self
Text shown, in placeholder_style, when state.value() is
empty.
Sourcepub const fn mask(self, mask: char) -> Self
pub const fn mask(self, mask: char) -> Self
Render every character of state.value() as mask instead of its real glyph, e.g. '*'
for a password field. Column math (scrolling, caret position) still uses the real value’s
display width, not the mask’s: masking only ever substitutes one fixed-width glyph, so
this is exact as long as mask itself is a single-column character.
Sourcepub const fn style(self, style: Style) -> Self
pub const fn style(self, style: Style) -> Self
Set the style of the value/placeholder text (placeholder uses
placeholder_style instead of this while shown).
Sourcepub const fn placeholder_style(self, style: Style) -> Self
pub const fn placeholder_style(self, style: Style) -> Self
Set the style of the placeholder text, shown in place of the value while it’s empty.
Sourcepub const fn caret_style(self, style: Style) -> Self
pub const fn caret_style(self, style: Style) -> Self
Set the style of the caret cell.
Sourcepub fn theme(self, theme: Theme) -> Self
pub fn theme(self, theme: Theme) -> Self
Applies theme’s named roles: style becomes theme.fg on theme.panel_bg,
placeholder_style becomes theme.dim on the same background, and caret_style becomes
theme.bg on theme.accent. See List::theme for why an explicit
background is baked in rather than left unset.
Sourcepub fn theme_on(self, theme: Theme, bg: Color) -> Self
pub fn theme_on(self, theme: Theme, bg: Color) -> Self
Same as TextInput::theme, but text is drawn on bg instead of theme.panel_bg.
Trait Implementations§
impl<'a> Copy for TextInput<'a>
Source§impl<Id> InteractiveWidget<Id> for TextInput<'_>
impl<Id> InteractiveWidget<Id> for TextInput<'_>
Source§fn sense(&self) -> Sense
fn sense(&self) -> Sense
Sense::click, the same as Button/List: a click
focuses the field (and joins the shared Interaction’s
Tab order) via Sense::FOCUSABLE, which Sense::click already includes. This impl’s
render still never reads response: routing keystrokes to whichever field holds focus,
and calling TextInputState::handle_event on it, is the caller’s job, the same as
List leaves arrow-key row navigation to the caller.
Source§type State = TextInputState
type State = TextInputState
() for
widgets that have none.Source§impl MinSize for TextInput<'_>
impl MinSize for TextInput<'_>
Source§fn min_size(&self, density: Density) -> Size
fn min_size(&self, density: Density) -> Size
placeholder’s display width (0 with no placeholder set)
plus 2 columns of padding on each side, matching Button’s own padding,
one row tall, floored at density’s min_target_size so an
empty field still claims a usable click/tap target.
Source§impl StatefulWidget for TextInput<'_>
impl StatefulWidget for TextInput<'_>
Auto Trait Implementations§
impl<'a> Freeze for TextInput<'a>
impl<'a> RefUnwindSafe for TextInput<'a>
impl<'a> Send for TextInput<'a>
impl<'a> Sync for TextInput<'a>
impl<'a> Unpin for TextInput<'a>
impl<'a> UnsafeUnpin for TextInput<'a>
impl<'a> UnwindSafe for TextInput<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<C> WithAlpha for Cwhere
C: Copy,
impl<C> WithAlpha for Cwhere
C: Copy,
§fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
fn with_alpha_first<A>(self, alpha: A) -> AlphaFirst<A, Self>
self with alpha, storing alpha before the color in memory
(see [AlphaFirst]).§fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
fn with_alpha_last<A>(self, alpha: A) -> AlphaLast<A, Self>
self with alpha, storing alpha after the color in memory
(see [AlphaLast]).