191 lines
4.9 KiB
Rust
191 lines
4.9 KiB
Rust
//! 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>),
|
|
}
|