pub struct TextEdit<Msg: Clone> {Show 17 fields
pub placeholder: String,
pub value: String,
pub on_change: Option<Arc<dyn Fn(String) -> Msg>>,
pub on_submit: Option<Msg>,
pub secure: bool,
pub multiline: bool,
pub rows: u32,
pub cursor_pos: usize,
pub id: Option<WidgetId>,
pub cursor: Option<CursorShape>,
pub align: TextAlign,
pub borderless: bool,
pub fixed_width: Option<f32>,
pub font_size: f32,
pub select_on_focus: bool,
pub password_toggle: Option<(bool, Msg)>,
pub read_only: bool,
}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.
Fields§
§placeholder: StringPlaceholder text shown when the field is empty.
value: StringCurrent field value.
on_change: Option<Arc<dyn Fn(String) -> Msg>>Callback invoked with the new value on every keystroke.
Arc (not Box) so the layout pass can clone it into the per-leaf
handler snapshot for O(1) dispatch on input events.
on_submit: Option<Msg>Message emitted when the user presses Enter.
secure: boolWhen true, the value is rendered as bullet characters (password mode).
multiline: boolWhen true, the widget renders as a multi-row text area: the
box grows to Self::rows visible rows, line breaks in the
value are honoured at draw time, and pressing Enter inserts a
\n rather than firing Self::on_submit. Ignored when
Self::secure is set — passwords are always single-line.
rows: u32Visible row count when multiline is true. Drives
preferred_size’s height calculation so a multiline field
claims a sensible vertical slot in the parent layout. Ignored
when multiline is false.
cursor_pos: usizeByte offset of the text cursor within value (used by insert_str/backspace).
id: Option<WidgetId>Optional stable identifier for focus management.
cursor: Option<CursorShape>Override the pointer cursor shape on hover. None falls back
to the I-beam default that matches every desktop convention.
align: TextAlignHorizontal alignment of the displayed text inside the inner
content rect. Only takes effect on the single-line path when
the value fits inside the inner width — once the value
overflows, the internal single_line_scroll_x helper takes
over and the alignment offset collapses to 0 so scrolling
reads naturally. Default TextAlign::Left.
borderless: boolSkip the field’s background fill and border stroke. Useful
when the TextEdit is dropped inside another container
that paints its own surface (e.g. the digit cells inside
crate::widget::time_picker::TimePicker) and a second pill
would only add visual noise.
fixed_width: Option<f32>Override the preferred width reported to the parent layout.
Without this the single-line TextEdit claims max_width and
fills whatever rect the parent allocates — which is the right
default for forms but wrong when the field needs to be sized
to fit a fixed number of glyphs (date / time pickers, inline
numeric inputs).
font_size: f32Font size in pixels for the single-line draw path. Defaults to
the theme’s FONT_SIZE constant. Multiline mode ignores this
for now and always uses the default — multiline soft-wrap
layout depends on the constant in several places that are not
yet parameterised.
select_on_focus: boolWhen true, focusing the field selects the whole value so the
next keystroke replaces it. Standard behaviour for numeric
pickers and short-form fields where the user usually wants to
retype rather than edit. Default false — long-form fields
keep the cursor at the end on focus.
password_toggle: Option<(bool, Msg)>Self-managed “show / hide password” eye affordance — when
Some( ( visible, on_toggle ) ) the field renders an
actions/visible ↔ actions/invisible icon at its right
edge, taps on that icon dispatch on_toggle instead of
placing the cursor, and the bullet substitution flips with
visible (overriding secure). Set on a field that already
has secure( true ) and the explicit flag becomes redundant
— the toggle controls the visibility from then on.
read_only: boolWhen true, the field renders its box and value but takes no keyboard
focus and accepts no input — a read-only display styled as a text field.
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,
)
pub fn draw( &self, canvas: &mut Canvas, rect: Rect, focused: bool, cursor_pos: usize, selection_anchor: usize, )
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.
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, px: f32) -> Self
pub fn font_size(self, px: f32) -> Self
Override the font size used by the single-line draw path.
Defaults to the theme’s FONT_SIZE constant. Ignored in
multiline mode.
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 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 fixed_width(self, w: f32) -> Self
pub fn fixed_width(self, w: f32) -> Self
Override the preferred width reported to the parent layout.
Pass None (default) to fall back to claiming 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 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 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 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,
) -> usize
pub fn byte_offset_at_self( &self, canvas: &Canvas, rect: Rect, pos: Point, cursor_pos: usize, ) -> usize
Translate a pointer position inside rect to the byte offset
in Self::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