ltk::text_edit

Struct TextEdit

Source
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 claiming max_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-owned visible state 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>

Source

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>

Source

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.

Source

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.

Source

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.

Source

pub fn font_size(self, px: f32) -> Self

Pin the single-line font size to an explicit fixed px. Without any font-size call the size follows the process crate::WidgetScaling mode at the theme default; see Self::font_size_fluid to follow the mode at a custom design px. Ignored in multiline mode.

Source

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. Encoded as a negative sentinel so it flows through the handler snapshot as a plain f32 without threading a canvas; every consumer resolves it via resolve_font_size.

Source

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.

Source

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.

Source

pub fn align(self, a: TextAlign) -> Self

Set the horizontal alignment of the displayed text. Default TextAlign::Left.

Source

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.

Source

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.

Source

pub fn cursor(self, shape: CursorShape) -> Self

Override the pointer cursor shape shown on hover. Defaults to CursorShape::Text (I-beam).

Source

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.

Source

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.

Source

pub fn on_change(self, f: impl Fn(String) -> Msg + 'static) -> Self

Set the callback invoked on every keystroke with the updated value.

Source

pub fn on_submit(self, msg: Msg) -> Self

Set the message emitted when Enter is pressed.

Source

pub fn secure(self, s: bool) -> Self

Enable or disable password mode.

When true, this widget:

  1. Renders the value as bullet characters () instead of the raw glyphs.
  2. Forces single-line mode (multiline + secure is mutually exclusive — passwords don’t have line breaks).
  3. Wipes the underlying byte buffer with zero before the String allocation is returned to the allocator. The wipe runs in Drop for both the TextEdit itself and for the per-frame crate::widget::WidgetHandlers::TextEdit snapshot 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 String you pass in through text_edit( placeholder, &self.password ) lives on your struct, not on the widget. Wiping it is your job — typically a Drop impl on the credential container, or an explicit secure_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 fresh String clone. If your closure stores or forwards that String (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 with prctl( 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. secure does not suppress text-input-v3 — the field still registers so the on-screen keyboard activates on it — but it is flagged Password with SensitiveData | 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).

Source

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.

Source

pub fn id(self, id: WidgetId) -> Self

Assign a stable identifier for focus management.

Source

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.

Source

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.

Source

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 the field’s value that the cursor should land on. Thin wrapper around byte_offset_at using this widget’s value / flags.

Source

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.

Source

pub fn display_text(&self) -> String

Return the display string — bullet characters in secure mode, plain value otherwise.

Source

pub fn into_element(self) -> Element<Msg>

Wrap this widget in an Element.

Source

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.

Source

pub fn backspace(&mut self) -> Option<Msg>

Delete the character before the cursor and return the on_change message if one is set. Does nothing if the cursor is already at position 0.

Trait Implementations§

Source§

impl<Msg: Clone> Drop for TextEdit<Msg>

Source§

fn drop(&mut self)

When secure( true ) is set, scrub the value bytes before the underlying String allocation is returned to the allocator. The non-secure path is a no-op so the cost is paid only by widgets that opted into credential handling.

Source§

impl<Msg: Clone> From<TextEdit<Msg>> for Element<Msg>

Source§

fn from(t: TextEdit<Msg>) -> Self

Converts to this type from the input type.

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert 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>

Convert 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)

Convert &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)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,