pub struct TextEdit<Msg: Clone> { /* private fields */ }Expand description
A text input field.
Single-line by default; switches to a multi-row text-area via
Self::multiline. Single-line mode honours the optional inline
builders for picker-style fields:
Self::align— horizontal alignment of the displayed text;Self::borderless— drop the surrounding pill / border so the field can sit inside a parent that already paints its own surface;Self::fixed_width— pin the preferred width to a specific number of pixels instead of claimingmax_width;Self::font_size— override the text font size;Self::select_on_focus— auto-select the value on focus so the next keystroke replaces it (numeric pickers, short-form inputs).Self::password_toggle— pin a built-in show / hide-password eye icon to the right edge of the field; the bullet substitution flips with the externally-ownedvisiblestate on each tap.
text_edit( "Username", &self.username )
.on_change( |s| Msg::UsernameChanged( s ) )
.on_submit( Msg::Submit )
.into()§Password field with show / hide toggle
text_edit( "Password", &self.password )
.on_change( |s| Msg::PasswordChanged( s ) )
.password_toggle( self.password_visible, Msg::TogglePassword )
.into()password_toggle overrides Self::secure when both are set —
the toggle’s visible parameter drives the bullet substitution
from then on. The widget still wipes the buffer on drop and
skips the IME registration (the same hardening
Self::secure gives) regardless of the current visibility,
so flipping the eye does not weaken the field’s threat model
at runtime.
Implementations§
Source§impl<Msg: Clone> TextEdit<Msg>
impl<Msg: Clone> TextEdit<Msg>
Sourcepub fn draw(
&self,
canvas: &mut Canvas,
rect: Rect,
focused: bool,
cursor_pos: usize,
selection_anchor: usize,
scroll: TextScroll,
) -> Option<TextScroll>
pub fn draw( &self, canvas: &mut Canvas, rect: Rect, focused: bool, cursor_pos: usize, selection_anchor: usize, scroll: TextScroll, ) -> Option<TextScroll>
Draw the field into canvas at rect.
cursor_pos is the byte offset of the text cursor — supplied by the runtime
from its persistent cursor state rather than from the widget itself.
selection_anchor is the other end of the selection range; when
selection_anchor == cursor_pos no highlight is painted.
scroll is where a multiline field was last shown, which it
returns as it shows it now, for the next frame to keep.
Source§impl<Msg: Clone> TextEdit<Msg>
impl<Msg: Clone> TextEdit<Msg>
Sourcepub fn new(placeholder: String, value: String) -> Self
pub fn new(placeholder: String, value: String) -> Self
Create a text field with the given placeholder and initial value.
The cursor is placed at the end of the initial value.
Sourcepub fn password_toggle(self, visible: bool, on_toggle: Msg) -> Self
pub fn password_toggle(self, visible: bool, on_toggle: Msg) -> Self
Add a “show / hide password” eye toggle pinned to the right
edge of the field. visible controls whether the value
renders as bullets (false) or plain text (true); a tap on
the icon emits on_toggle so the caller can flip its own
bool state and re-render. Works with or without an explicit
Self::secure — when this is set, the toggle’s visible
drives the bullet substitution and the secure field is
ignored.
Sourcepub fn effective_secure(&self) -> bool
pub fn effective_secure(&self) -> bool
Effective secure flag honoured by drawing / measurement /
hit-testing — Self::password_toggle takes precedence over
the manual Self::secure when both are set.
Sourcepub fn font_size(self, size: impl Into<Length>) -> Self
pub fn font_size(self, size: impl Into<Length>) -> Self
Set the label font size. Accepts logical f32 pixels or any
Length (e.g. Length::vmin( 4.5 ).clamp( 16.0, 32.0 ) to scale
with the surface), resolved in font space exactly like the button
label. Without any font-size call the size follows the process
crate::WidgetScaling mode at the theme default. Ignored in
multiline mode.
Sourcepub fn font_size_fluid(self, design_px: f32) -> Self
pub fn font_size_fluid(self, design_px: f32) -> Self
Set a font size that follows the process crate::WidgetScaling
mode at the given design px — the fluid counterpart of
Self::font_size. Shorthand for .font_size( Length::fluid( n ) ).
Sourcepub fn height(self, h: impl Into<Length>) -> Self
pub fn height(self, h: impl Into<Length>) -> Self
Set the single-line field height. Accepts logical f32 pixels or any
Length (e.g. Length::vmin( 9.0 ).clamp( 44.0, 72.0 ) to scale
the box with the surface, or to match a fluid button). Ignored in
multiline mode, where the height follows Self::rows.
Sourcepub fn select_on_focus(self, on: bool) -> Self
pub fn select_on_focus(self, on: bool) -> Self
Select the whole value when the field receives focus, so the
next keystroke replaces it. Default false.
Sourcepub fn pin_cursor_to_end(self, on: bool) -> Self
pub fn pin_cursor_to_end(self, on: bool) -> Self
Keep the cursor at the end of the displayed value while editing,
for fields whose on_change normalises what was typed (“2” → “02”).
Default false.
Sourcepub fn align(self, a: TextAlign) -> Self
pub fn align(self, a: TextAlign) -> Self
Set the horizontal alignment of the displayed text. Default
TextAlign::Left.
Sourcepub fn borderless(self, on: bool) -> Self
pub fn borderless(self, on: bool) -> Self
Skip the field’s background fill and border stroke — useful when the field is nested inside a container that already paints its own surface.
Sourcepub fn padding_h(self, px: f32) -> Self
pub fn padding_h(self, px: f32) -> Self
Set the horizontal inner padding of a single-line field, in
physical pixels, for a host that lays out its own (0 lets the
text use the whole rect). Without it the padding follows the
field height.
Sourcepub fn fixed_width(self, w: impl Into<Length>) -> Self
pub fn fixed_width(self, w: impl Into<Length>) -> Self
Override the preferred width reported to the parent layout.
Accepts logical f32 pixels or any Length — pair a
Length::fluid width with a fluid font size so box and glyphs
scale together. Without this the field claims max_width.
Sourcepub fn cursor(self, shape: CursorShape) -> Self
pub fn cursor(self, shape: CursorShape) -> Self
Override the pointer cursor shape shown on hover. Defaults to
CursorShape::Text (I-beam).
Sourcepub fn multiline(self, m: bool) -> Self
pub fn multiline(self, m: bool) -> Self
Switch to multiline (text-area) mode. The box is laid out with
Self::rows visible rows of height, line breaks in the value
are rendered as separate rows, and Enter inserts a \n instead
of firing Self::on_submit. Ignored when Self::secure is
true.
Sourcepub fn rows(self, n: u32) -> Self
pub fn rows(self, n: u32) -> Self
Configure the number of visible rows in multiline mode. Defaults
to 5; ignored when Self::multiline is false.
Sourcepub fn highlights(self, runs: Arc<Vec<Highlight>>) -> Self
pub fn highlights(self, runs: Arc<Vec<Highlight>>) -> Self
Draw runs of a multiline value in colours of their own (see
Highlight), as an editor highlights code. Shared through an
Arc, since a view is rebuilt on every frame and a long text has
many runs. Single-line fields draw in one colour.
Sourcepub fn tab_text(self, text: impl Into<String>) -> Self
pub fn tab_text(self, text: impl Into<String>) -> Self
Have the Tab key type text, such as four spaces, while the field
has the focus, as an editor does, instead of moving the focus to
the next widget.
Sourcepub fn line_numbers(self, on: bool) -> Self
pub fn line_numbers(self, on: bool) -> Self
Number the lines of a multiline field in a column at its left, as wide as the number of the last line needs; a line that wraps is numbered on its first row.
Sourcepub fn font(self, face: Arc<FontFace>) -> Self
pub fn font(self, face: Arc<FontFace>) -> Self
Draw a multiline field’s text in face, such as crate::monospace_font
for an editor of code, instead of the theme’s; its size is still
Self::font_size’s.
Sourcepub fn on_change(self, f: impl Fn(String) -> Msg + 'static) -> Self
pub fn on_change(self, f: impl Fn(String) -> Msg + 'static) -> Self
Set the callback invoked on every keystroke with the updated value.
Sourcepub fn on_cursor(self, f: impl Fn(usize) -> Msg + 'static) -> Self
pub fn on_cursor(self, f: impl Fn(usize) -> Msg + 'static) -> Self
Set the callback invoked with the cursor’s byte offset in the value once it has been placed and whenever it moves or the value changes length, as an editor’s status bar showing the line needs.
Sourcepub fn secure(self, s: bool) -> Self
pub fn secure(self, s: bool) -> Self
Enable or disable password mode.
When true, this widget:
- Renders the value as bullet characters (
•) instead of the raw glyphs. - Forces single-line mode (multiline + secure is mutually exclusive — passwords don’t have line breaks).
- Wipes the underlying byte buffer with zero before the
Stringallocation is returned to the allocator. The wipe runs inDropfor both theTextEdititself and for the per-framecrate::widget::WidgetHandlers::TextEditsnapshot the runtime keeps for input dispatch — so the in-tree copies that ltk owns never linger as plain text in freed memory.
§Threat model — what secure covers
Inside the widget tree the runtime keeps two copies of the
value for the lifetime of one frame: the TextEdit itself and
the WidgetHandlers snapshot. Both run the secure_zero wipe
on Drop, so when the next frame replaces them (the typical
case — view() rebuilds every frame) the freed allocations are
overwritten before being released back to the allocator. The
wipe uses volatile writes + a compiler_fence so the optimiser
cannot elide it as dead code (the implementation is in the
crate-private secure_mem module).
§What secure does not cover
- The application’s own state. The
Stringyou pass in throughtext_edit( placeholder, &self.password )lives on your struct, not on the widget. Wiping it is your job — typically aDropimpl on the credential container, or an explicitsecure_mem::secure_zero( password.as_bytes_mut() )after the auth handshake completes. - Callback-allocated copies. Every keystroke passes through
on_change( |s: String| ... ), which receives a freshStringclone. If your closure stores or forwards thatString(e.g. clone it into a worker thread for PAM), each stored copy is the consumer’s responsibility to wipe. ltk only owns the buffers it allocated itself. - OS-level disclosure surfaces. Swap-out, hibernation
images, and core dumps are outside any user-space wipe’s
reach. For threat models that require resistance to these,
compile against an
mlock-aware allocator, disable swap on the credential mount, and restrict core-dump capability withprctl( PR_SET_DUMPABLE, 0 )on the process. - Compositor-side records. Wayland text-input protocols can
surface preedit / commit strings to the compositor’s IME stack.
securedoes not suppress text-input-v3 — the field still registers so the on-screen keyboard activates on it — but it is flaggedPasswordwithSensitiveData | HiddenText, asking the IME / OSK to skip prediction, autocorrect and storing the value. The value still reaches the (trusted) compositor/IME; for a stricter threat model, suppress text-input on secure fields instead (at the cost of losing the OSK there).
See the in-repo SECURITY.md for the full threat-model write-up
(the Hardening features section enumerates each guarantee and
its boundary).
Sourcepub fn purpose(self, purpose: Purpose) -> Self
pub fn purpose(self, purpose: Purpose) -> Self
What the field is for. A Terminal field gets the on-screen keyboard’s row of Escape, Tab, Ctrl, Alt and arrows, and tells the compositor’s input method the same.
Sourcepub fn read_only(self, on: bool) -> Self
pub fn read_only(self, on: bool) -> Self
Render the field read-only: shows the value styled as a field but takes no focus and accepts no input.
Sourcepub fn preferred_size(&self, max_width: f32, canvas: &Canvas) -> (f32, f32)
pub fn preferred_size(&self, max_width: f32, canvas: &Canvas) -> (f32, f32)
Return the preferred (width, height) given available max_width.
Single-line: theme-defined HEIGHT.
Multiline: enough room for Self::rows lines plus padding.
Sourcepub fn is_multiline(&self) -> bool
pub fn is_multiline(&self) -> bool
true when the widget is laid out as a multi-row text area —
i.e. Self::multiline was set and Self::effective_secure
is false. A password_toggle field collapses to single-line
like an explicit secure( true ) does.
Sourcepub fn byte_offset_at_self(
&self,
canvas: &Canvas,
rect: Rect,
pos: Point,
cursor_pos: usize,
scroll: TextScroll,
) -> usize
pub fn byte_offset_at_self( &self, canvas: &Canvas, rect: Rect, pos: Point, cursor_pos: usize, scroll: TextScroll, ) -> usize
Translate a pointer position inside rect to the byte offset
in the field’s value that the cursor should land on. Thin
wrapper around byte_offset_at using this widget’s value /
flags.
Sourcepub fn paint_bounds(&self, rect: Rect) -> Rect
pub fn paint_bounds(&self, rect: Rect) -> Rect
Border stroke is centered on rect, so half the stroke width plus ~1 px
of antialiasing bleed sits outside. The widest stroke is the focused
border, so use that as the envelope.
Sourcepub fn display_text(&self) -> String
pub fn display_text(&self) -> String
Return the display string — bullet characters in secure mode, plain value otherwise.
Sourcepub fn into_element(self) -> Element<Msg>
pub fn into_element(self) -> Element<Msg>
Wrap this widget in an Element.
Sourcepub fn insert_str(&mut self, s: &str) -> Option<Msg>
pub fn insert_str(&mut self, s: &str) -> Option<Msg>
Insert a string at the current cursor position, advance the cursor, and
return the on_change message if one is set.
Trait Implementations§
Auto Trait Implementations§
impl<Msg> Freeze for TextEdit<Msg>where
Msg: Freeze,
impl<Msg> !RefUnwindSafe for TextEdit<Msg>
impl<Msg> !Send for TextEdit<Msg>
impl<Msg> !Sync for TextEdit<Msg>
impl<Msg> Unpin for TextEdit<Msg>where
Msg: Unpin,
impl<Msg> !UnwindSafe for TextEdit<Msg>
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
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more