pub struct Editor { /* private fields */ }Expand description
One text buffer bound to a signal, over any number of paragraphs.
The editor holds the text and the selection; the signal mirrors the text
without any composing preedit. Every mutating method writes the signal,
so Editor::text and the signal always agree. A write to the signal
from outside is applied with Editor::set_text, which replaces the
text and moves the caret to the end.
The editor lays out lazily and per paragraph: an edit drops the layouts of the paragraphs it touched, and the next call that needs geometry rebuilds them, alone. A document far larger than the screen costs an edit only the work its own lines take.
§Panics
Every method that edits the text, moves the caret or reads geometry can
build layouts, so it runs the thread’s TextSystem and panics under
the conditions of TextSystem::with, in particular when called from
inside another with call on the same thread. No input text or edit
sequence panics.
Implementations§
Source§impl Editor
impl Editor
Sourcepub fn new(value: RwSignal<String>) -> Editor
pub fn new(value: RwSignal<String>) -> Editor
Creates an editor bound to value, starting empty.
The text the signal holds is not read: an editor starts empty and
fills when its widget applies the signal’s current value. Binding
value through a widget does that on mount.
Sourcepub fn single_line(value: RwSignal<String>) -> Editor
pub fn single_line(value: RwSignal<String>) -> Editor
Creates an editor of one line bound to value, starting empty.
The editor works as Editor::new makes it, except that every line
break in text that reaches it becomes one space: typed or committed
text, a paste and a write through Editor::set_text alike, with a
carriage return and line feed pair counted as one break. The bound
signal is written with the line the editor kept. A preedit an input
method is composing is shown as the method sends it, since it is not
the editor’s text until it commits.
use smudge_core::reactive::{RwSignal, prelude::*};
use smudge_text::{Editor, TextSystem};
TextSystem::bundled_only().install();
let value = RwSignal::new(String::new());
let editor = Editor::single_line(value.clone());
editor.paste("one\ntwo");
assert_eq!(value.get(), "one two");Sourcepub fn set_style(&self, style: &TextStyle)
pub fn set_style(&self, style: &TextStyle)
Applies style to the text the editor lays out.
The next layout rebuild picks the style up. Changing the font size changes what the editor measures, so a widget applies this before it measures.
Sourcepub fn set_wrap_width(&self, width: Option<f32>)
pub fn set_wrap_width(&self, width: Option<f32>)
Sets the width the editor wraps its lines to, in logical pixels, or
None to lay each paragraph out as one unbroken line.
An editor starts unwrapped. The paragraphs already laid out break their lines again at the new width without shaping their text again, and the caret and selection geometry follow. The same width again does nothing.
Sourcepub fn raw_text(&self) -> String
pub fn raw_text(&self) -> String
Returns the text of the editor, including any composing preedit.
Sourcepub fn selection(&self) -> Range<usize> ⓘ
pub fn selection(&self) -> Range<usize> ⓘ
Returns the byte range of the selection, into Editor::raw_text.
The range is empty and both ends equal when the caret is collapsed.
Sourcepub fn is_composing(&self) -> bool
pub fn is_composing(&self) -> bool
Returns whether an input method is composing text in the editor.
Sourcepub fn ime_area(&self) -> Rect
pub fn ime_area(&self) -> Rect
Returns the area the input method should anchor to, in the editor’s own coordinates.
This bounds the preedit while one is being composed, and the selected part of the focused line otherwise, inflated a little so a candidate window does not jump while the user types.
Sourcepub fn compose_geometry(&self) -> Vec<Rect>
pub fn compose_geometry(&self) -> Vec<Rect>
Returns one rectangle per piece of the composing preedit, in the editor’s own coordinates, for the underline drawn beneath it.
The rectangles sit just below the baseline of each piece, in visual order, and the list is empty while no input method is composing.
Sourcepub fn set_text(&self, text: &str)
pub fn set_text(&self, text: &str)
Replaces the whole text and moves the caret to the end.
This is how an outside write to the bound signal reaches the editor: the user typed somewhere else, or the application replaced the value. The selection collapses at the end, because a selection into text the editor no longer has means nothing. The undo history is cleared, so undo never brings back text the application replaced, and any composition stops, because the text it was composing into is gone.
Every carriage return and line feed pair, and every lone carriage return, becomes one line feed, or every line break one space in a single-line editor, and the bound signal is written with the text the editor kept.
Sourcepub fn insert(&self, text: &str)
pub fn insert(&self, text: &str)
Inserts text at the caret, replacing the selection.
Typed characters group into one undo step until the caret moves, a different edit runs, or a whitespace character starts the next step, so undo removes text a word at a time. Inserting more than one character at once, as a paste does, is a step of its own. The text may hold line breaks, which cut the document into more paragraphs. A carriage return and line feed pair, or a lone carriage return, is inserted as one line feed. A single-line editor inserts every line break as one space instead.
Sourcepub fn paste(&self, text: &str)
pub fn paste(&self, text: &str)
Inserts text from a clipboard, replacing the selection, as one undo
step.
Line breaks in the text cut the document into more paragraphs, with a carriage return and line feed pair, or a lone carriage return, taken as one line feed. A single-line editor pastes every line break as one space instead, so a paste from a multi-line source lands on its one line. An empty paste inserts nothing.
Sourcepub fn delete_selection(&self)
pub fn delete_selection(&self)
Deletes the selected text, or nothing when the caret is collapsed.
This is the deletion a cut pairs with the copy, and it is an undo step of its own.
Sourcepub fn selected_text(&self) -> Option<String>
pub fn selected_text(&self) -> Option<String>
Returns the selected text, or None when the selection is collapsed.
Sourcepub fn compose(&self, text: &str, cursor: Option<(usize, usize)>)
pub fn compose(&self, text: &str, cursor: Option<(usize, usize)>)
Shows, updates or clears the text an input method is composing.
Non-empty text becomes the preedit, which replaces the previous
preedit, and cursor, the byte range of the input method’s cursor
inside text, moves the caret into the preedit, or hides it when
None. A composition that starts over a selection deletes the
selection first, the way typing over it would, and that deletion is an
undo step of its own. Empty text removes the preedit and leaves the
caret where the preedit started.
The preedit is not the editor’s text: Editor::text leaves it out
and the bound signal is not written, so a canceled or lost
composition leaves the value as it was. Only Editor::commit makes
composing text stick.
Cursor offsets past the end of text, or inside one of its
characters, which a broken input method could report, are clamped or
snapped to the text.
Sourcepub fn commit(&self, text: &str)
pub fn commit(&self, text: &str)
Commits text from an input method, replacing any preedit with it.
A commit can arrive while the preedit is still showing, in which case the committed text takes its place, or after the platform already cleared it, in which case it is inserted at the caret. The committed text groups for undo like typed text: one character joins the word around it, and longer text is a step of its own. An empty commit only removes the preedit.
Sourcepub fn backspace(&self)
pub fn backspace(&self)
Deletes one grapheme before the caret, or the selection.
A backspace before a combining mark takes the mark off first, and one after a line break joins the two lines. Repeated deletes group into one undo step until the caret moves or a different edit runs.
Sourcepub fn backspace_word(&self)
pub fn backspace_word(&self)
Deletes one word before the caret, or the selection, as one undo step.
Sourcepub fn delete(&self)
pub fn delete(&self)
Deletes one grapheme after the caret, or the selection.
A delete before a line break joins the two lines. Repeated deletes group into one undo step until the caret moves or a different edit runs.
Sourcepub fn delete_word(&self)
pub fn delete_word(&self)
Deletes one word after the caret, or the selection, as one undo step.
Sourcepub fn undo(&self)
pub fn undo(&self)
Undoes the last undo step, restoring the text and the selection from before it, or does nothing when there is none.
Nothing is undone while an input method is composing, because the composition owns the text around the caret until it commits.
Sourcepub fn redo(&self)
pub fn redo(&self)
Redoes the last undone step, or does nothing when there is none.
Any edit after an undo discards the steps it could have redone.
Sourcepub fn move_right(&self)
pub fn move_right(&self)
Moves the caret one grapheme to the right, in visual order.
Sourcepub fn move_word_left(&self)
pub fn move_word_left(&self)
Moves the caret one word to the left, in visual order.
Sourcepub fn move_word_right(&self)
pub fn move_word_right(&self)
Moves the caret one word to the right, in visual order.
Sourcepub fn move_lines(&self, lines: isize)
pub fn move_lines(&self, lines: isize)
Moves the caret lines visual lines down, or up when negative,
keeping its horizontal position where the move can.
Sourcepub fn move_to_start(&self)
pub fn move_to_start(&self)
Moves the caret to the start of the text.
Sourcepub fn move_to_end(&self)
pub fn move_to_end(&self)
Moves the caret to the end of the text.
Sourcepub fn move_to_line_start(&self)
pub fn move_to_line_start(&self)
Moves the caret to the start of the visual line it sits on.
A paragraph wrapped over several lines moves within the wrapped line, not to the start of the paragraph.
Sourcepub fn move_to_line_end(&self)
pub fn move_to_line_end(&self)
Moves the caret to the end of the visual line it sits on.
The end of a wrapped line sits after the space the line broke at, on the same line.
Sourcepub fn extend_left(&self)
pub fn extend_left(&self)
Moves the selection focus one grapheme to the left.
Sourcepub fn extend_right(&self)
pub fn extend_right(&self)
Moves the selection focus one grapheme to the right.
Sourcepub fn extend_word_left(&self)
pub fn extend_word_left(&self)
Moves the selection focus one word to the left.
Sourcepub fn extend_word_right(&self)
pub fn extend_word_right(&self)
Moves the selection focus one word to the right.
Sourcepub fn extend_down(&self)
pub fn extend_down(&self)
Moves the selection focus one visual line down.
Sourcepub fn extend_lines(&self, lines: isize)
pub fn extend_lines(&self, lines: isize)
Moves the selection focus lines visual lines down, or up when
negative.
Sourcepub fn extend_to_start(&self)
pub fn extend_to_start(&self)
Moves the selection focus to the start of the text.
Sourcepub fn extend_to_end(&self)
pub fn extend_to_end(&self)
Moves the selection focus to the end of the text.
Sourcepub fn extend_to_line_start(&self)
pub fn extend_to_line_start(&self)
Moves the selection focus to the start of the visual line it sits on.
Sourcepub fn extend_to_line_end(&self)
pub fn extend_to_line_end(&self)
Moves the selection focus to the end of the visual line it sits on.
Sourcepub fn select_all(&self)
pub fn select_all(&self)
Selects the whole text.
Sourcepub fn move_to_point(&self, x: f32, y: f32)
pub fn move_to_point(&self, x: f32, y: f32)
Places the caret at the point, in the editor’s own coordinates.
The coordinates are relative to the top left of the text, which a widget gets by subtracting where it draws the text from the pointer position. A point below the last line places the caret at the end of its paragraph, and one past a line’s end places it at that line’s end.
Sourcepub fn extend_to_point(&self, x: f32, y: f32)
pub fn extend_to_point(&self, x: f32, y: f32)
Moves the selection focus to the point, in the editor’s own coordinates, keeping the anchor where it was.
The extension follows the granularity a double or triple click left the selection at: by cluster after a plain drag, and by word after a double click.
Sourcepub fn select_word_at_point(&self, x: f32, y: f32)
pub fn select_word_at_point(&self, x: f32, y: f32)
Selects the word under the point, in the editor’s own coordinates.
Sourcepub fn cursor_geometry(&self, width: f32) -> Option<Rect>
pub fn cursor_geometry(&self, width: f32) -> Option<Rect>
Returns the rectangle of the caret, width logical pixels wide, in
the editor’s own coordinates, or None when there is no caret.
A caret an input method hid, by composing without a cursor, is none.
Sourcepub fn selection_geometry(&self) -> Vec<Rect>
pub fn selection_geometry(&self) -> Vec<Rect>
Returns one rectangle per selected piece of a line, in the editor’s own coordinates.
A collapsed selection yields no rectangles.
Sourcepub fn layout_size(&self) -> Size
pub fn layout_size(&self) -> Size
Returns the width and height of the laid out text.
The width is the longest paragraph, and the height is the sum of every paragraph’s lines.
§Panics
Panics under the conditions of TextSystem::with.
Sourcepub fn glyph_runs_at(&self, origin: Point, color: Color) -> Vec<GlyphRun>
pub fn glyph_runs_at(&self, origin: Point, color: Color) -> Vec<GlyphRun>
Converts the laid out text into glyph runs at origin, in paint
order, with every run in color.
origin is where the top left corner of the text box goes, in the
caller’s paint coordinates. A widget that paints a large document
walks Editor::paragraphs instead and builds the runs of the
paragraphs it shows, so an edit elsewhere does not rebuild them.
§Panics
Panics under the conditions of TextSystem::with, in particular
when called from inside another with call on the same thread.
Sourcepub fn paragraphs(&self, f: impl FnMut(EditorParagraph<'_>))
pub fn paragraphs(&self, f: impl FnMut(EditorParagraph<'_>))
Walks the editor’s laid out paragraphs, top to bottom, handing each
to f.
A painter walks these to build its glyph runs one paragraph at a time: each paragraph carries a stamp that changes when its layout does, so a cache keyed on the stamp rebuilds only the paragraphs an edit touched, and a painter that shows part of the text builds the paragraphs it shows alone.
§Panics
Panics under the conditions of TextSystem::with.