Skip to main content

InputWidget

Struct InputWidget 

Source
pub struct InputWidget<'a> { /* private fields */ }
Expand description

A single-line text field that only draws — an ordinary ratatui Widget with no focus, events, or state of its own.

A themed paint adapter for ratatui-textarea.

It paints the InputState it is given: the text, scrolled to keep the cursor in view, the cursor when focused, and any selection. Driving the editing is the caller’s business, from the editor paint hands back; Input is the field that does it for you, and paints through this widget.

Implementations§

Source§

impl<'a> InputWidget<'a>

Source

pub fn new(state: &InputState) -> Self

A field showing state.

Source

pub fn themed(self, theme: &Theme) -> Self

Take colors from theme.

Source

pub const fn style(self, style: InputStyle) -> Self

Use these exact colors, ignoring any theme.

Source

pub const fn placeholder(self, placeholder: &'a str) -> Self

The muted text shown while the field is empty, focused or not, where the text would start. A focused field shows its cursor on its first character.

Source

pub fn prefix(self, prefix: impl Into<Line<'a>>) -> Self

Muted text before the editable text, inside the field: https:// before a URL, an icon before a search. Never masked; a span’s own style paints over the muted one.

Source

pub fn suffix(self, suffix: impl Into<Line<'a>>) -> Self

Muted text after the editable text, inside the field: a unit, a domain. Never masked; a span’s own style paints over the muted one.

Source

pub const fn title(self, title: &'a str) -> Self

Draw a border around the field with title on it. The field then takes three rows instead of one.

Source

pub const fn mask_char(self, mask_char: char) -> Self

Paint every character as mask_char, for a secret. Only the paint changes: the state keeps the text as typed. A masked field never copies or cuts, so the secret cannot leave it that way.

Source

pub const fn height(&self) -> u16

Rows the field occupies: 1, or 3 with a title.

Source

pub const fn focused(self, focused: bool) -> Self

Paint the focused background and show the cursor.

Source

pub const fn hovered(self, hovered: bool) -> Self

Paint the hovered background.

Source

pub const fn disabled(self, disabled: bool) -> Self

Paint muted, with no cursor.

Source

pub const fn invalid(self, invalid: bool) -> Self

Paint the text, border, and title in the invalid color.

Source

pub fn paint(self, area: Rect, buf: &mut Buffer) -> Editor<'static>

Paint the field and hand back the editor it was painted from, which now knows the view it was drawn in: how far it is scrolled.

Rendering as a Widget throws that editor away. A loop that drives the editing itself edits this one instead, and stores the result with InputState::from_editor, so the next paint scrolls from what is on screen. Which keys reach the editor is the loop’s own policy; this is the least of one, and Input has the whole of it.

use ratatui::{buffer::Buffer, layout::Rect};
use ratcn::{
    InputState, InputWidget,
    runtime::{KeyCode, KeyEvent},
    text_edit::{Editor, editor_input, is_editor_binding},
};

// Beside the state, the editor the last paint handed back, with the
// version of the state it was painted from.
let mut state = InputState::new("Ada Lovelace");
let mut painted: Option<(u64, Editor<'static>)> = None;

// Each frame:
let area = Rect::new(0, 0, 8, 1);
let mut buf = Buffer::empty(area);
let editor = InputWidget::new(&state).focused(true).paint(area, &mut buf);
painted = Some((state.version(), editor));

// When a key arrives:
fn on_key(
    key: KeyEvent,
    state: &mut InputState,
    painted: &mut Option<(u64, Editor<'static>)>,
) {
    match key.code {
        KeyCode::Enter => { /* submit */ }
        // Focus traversal, the enclosing view, and keys with nowhere to
        // go on one line.
        KeyCode::Tab | KeyCode::BackTab | KeyCode::Esc | KeyCode::Up | KeyCode::Down => {}
        // Line breaks, shifted or not: Ctrl+J is a terminal's line feed.
        KeyCode::Char('j' | 'J' | 'm' | 'M') if key.modifiers.ctrl => {}
        KeyCode::Char('\n' | '\r') => {}
        _ => {
            if let Some(input) = editor_input(&key).filter(is_editor_binding) {
                // The painted editor, while the state is still the one
                // it was painted from.
                let mut editor = match painted.take() {
                    Some((version, editor)) if version == state.version() => editor,
                    _ => state.editor().clone(),
                };
                editor.input(input);
                *state = InputState::from_editor(editor);
            }
        }
    }
}

on_key(KeyEvent::new(KeyCode::Left), &mut state, &mut painted);
assert_eq!(state.cursor(), 11);

Trait Implementations§

Source§

impl<'a> Debug for InputWidget<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Widget for InputWidget<'_>

Source§

fn render(self, area: Rect, buf: &mut Buffer)

Draws the current state of the widget in the given buffer. That is the only method required to implement a custom widget.

Auto Trait Implementations§

§

impl<'a> !Freeze for InputWidget<'a>

§

impl<'a> !RefUnwindSafe for InputWidget<'a>

§

impl<'a> !Sync for InputWidget<'a>

§

impl<'a> Send for InputWidget<'a>

§

impl<'a> Unpin for InputWidget<'a>

§

impl<'a> UnsafeUnpin for InputWidget<'a>

§

impl<'a> UnwindSafe for InputWidget<'a>

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

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.