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