iced_core/text/
editor.rs

1//! Edit text.
2use crate::text::highlighter::{self, Highlighter};
3use crate::text::{LineHeight, Wrapping};
4use crate::{Pixels, Point, Rectangle, Size};
5
6use std::sync::Arc;
7
8/// A component that can be used by widgets to edit multi-line text.
9pub trait Editor: Sized + Default {
10    /// The font of the [`Editor`].
11    type Font: Copy + PartialEq + Default;
12
13    /// Creates a new [`Editor`] laid out with the given text.
14    fn with_text(text: &str) -> Self;
15
16    /// Returns true if the [`Editor`] has no contents.
17    fn is_empty(&self) -> bool;
18
19    /// Returns the current [`Cursor`] of the [`Editor`].
20    fn cursor(&self) -> Cursor;
21
22    /// Returns the current cursor position of the [`Editor`].
23    ///
24    /// Line and column, respectively.
25    fn cursor_position(&self) -> (usize, usize);
26
27    /// Returns the current selected text of the [`Editor`].
28    fn selection(&self) -> Option<String>;
29
30    /// Returns the text of the given line in the [`Editor`], if it exists.
31    fn line(&self, index: usize) -> Option<&str>;
32
33    /// Returns the amount of lines in the [`Editor`].
34    fn line_count(&self) -> usize;
35
36    /// Performs an [`Action`] on the [`Editor`].
37    fn perform(&mut self, action: Action);
38
39    /// Returns the current boundaries of the [`Editor`].
40    fn bounds(&self) -> Size;
41
42    /// Returns the minimum boundaries to fit the current contents of
43    /// the [`Editor`].
44    fn min_bounds(&self) -> Size;
45
46    /// Updates the [`Editor`] with some new attributes.
47    fn update(
48        &mut self,
49        new_bounds: Size,
50        new_font: Self::Font,
51        new_size: Pixels,
52        new_line_height: LineHeight,
53        new_wrapping: Wrapping,
54        new_highlighter: &mut impl Highlighter,
55    );
56
57    /// Runs a text [`Highlighter`] in the [`Editor`].
58    fn highlight<H: Highlighter>(
59        &mut self,
60        font: Self::Font,
61        highlighter: &mut H,
62        format_highlight: impl Fn(&H::Highlight) -> highlighter::Format<Self::Font>,
63    );
64}
65
66/// An interaction with an [`Editor`].
67#[derive(Debug, Clone, PartialEq)]
68pub enum Action {
69    /// Apply a [`Motion`].
70    Move(Motion),
71    /// Select text with a given [`Motion`].
72    Select(Motion),
73    /// Select the word at the current cursor.
74    SelectWord,
75    /// Select the line at the current cursor.
76    SelectLine,
77    /// Select the entire buffer.
78    SelectAll,
79    /// Perform an [`Edit`].
80    Edit(Edit),
81    /// Click the [`Editor`] at the given [`Point`].
82    Click(Point),
83    /// Drag the mouse on the [`Editor`] to the given [`Point`].
84    Drag(Point),
85    /// Scroll the [`Editor`] a certain amount of lines.
86    Scroll {
87        /// The amount of lines to scroll.
88        lines: i32,
89    },
90}
91
92impl Action {
93    /// Returns whether the [`Action`] is an editing action.
94    pub fn is_edit(&self) -> bool {
95        matches!(self, Self::Edit(_))
96    }
97}
98
99/// An action that edits text.
100#[derive(Debug, Clone, PartialEq)]
101pub enum Edit {
102    /// Insert the given character.
103    Insert(char),
104    /// Paste the given text.
105    Paste(Arc<String>),
106    /// Break the current line.
107    Enter,
108    /// Delete the previous character.
109    Backspace,
110    /// Delete the next character.
111    Delete,
112}
113
114/// A cursor movement.
115#[derive(Debug, Clone, Copy, PartialEq)]
116pub enum Motion {
117    /// Move left.
118    Left,
119    /// Move right.
120    Right,
121    /// Move up.
122    Up,
123    /// Move down.
124    Down,
125    /// Move to the left boundary of a word.
126    WordLeft,
127    /// Move to the right boundary of a word.
128    WordRight,
129    /// Move to the start of the line.
130    Home,
131    /// Move to the end of the line.
132    End,
133    /// Move to the start of the previous window.
134    PageUp,
135    /// Move to the start of the next window.
136    PageDown,
137    /// Move to the start of the text.
138    DocumentStart,
139    /// Move to the end of the text.
140    DocumentEnd,
141}
142
143impl Motion {
144    /// Widens the [`Motion`], if possible.
145    pub fn widen(self) -> Self {
146        match self {
147            Self::Left => Self::WordLeft,
148            Self::Right => Self::WordRight,
149            Self::Home => Self::DocumentStart,
150            Self::End => Self::DocumentEnd,
151            _ => self,
152        }
153    }
154
155    /// Returns the [`Direction`] of the [`Motion`].
156    pub fn direction(&self) -> Direction {
157        match self {
158            Self::Left
159            | Self::Up
160            | Self::WordLeft
161            | Self::Home
162            | Self::PageUp
163            | Self::DocumentStart => Direction::Left,
164            Self::Right
165            | Self::Down
166            | Self::WordRight
167            | Self::End
168            | Self::PageDown
169            | Self::DocumentEnd => Direction::Right,
170        }
171    }
172}
173
174/// A direction in some text.
175#[derive(Debug, Clone, Copy, PartialEq, Eq)]
176pub enum Direction {
177    /// <-
178    Left,
179    /// ->
180    Right,
181}
182
183/// The cursor of an [`Editor`].
184#[derive(Debug, Clone)]
185pub enum Cursor {
186    /// Cursor without a selection
187    Caret(Point),
188
189    /// Cursor selecting a range of text
190    Selection(Vec<Rectangle>),
191}