summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/src/text/editor.rs38
-rw-r--r--graphics/src/text/editor.rs106
-rw-r--r--widget/src/text_editor.rs77
3 files changed, 156 insertions, 65 deletions
diff --git a/core/src/text/editor.rs b/core/src/text/editor.rs
index 09d4efde..f87e18f3 100644
--- a/core/src/text/editor.rs
+++ b/core/src/text/editor.rs
@@ -40,14 +40,8 @@ pub trait Editor: Sized + Default {
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Action {
- MoveLeft,
- MoveRight,
- MoveUp,
- MoveDown,
- MoveLeftWord,
- MoveRightWord,
- MoveHome,
- MoveEnd,
+ Move(Motion),
+ Select(Motion),
SelectWord,
SelectLine,
Insert(char),
@@ -58,6 +52,34 @@ pub enum Action {
Drag(Point),
}
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Motion {
+ Left,
+ Right,
+ Up,
+ Down,
+ WordLeft,
+ WordRight,
+ Home,
+ End,
+ PageUp,
+ PageDown,
+ DocumentStart,
+ DocumentEnd,
+}
+
+impl Motion {
+ pub fn widen(self) -> Self {
+ match self {
+ Self::Left => Self::WordLeft,
+ Self::Right => Self::WordRight,
+ Self::Home => Self::DocumentStart,
+ Self::End => Self::DocumentEnd,
+ _ => self,
+ }
+ }
+}
+
/// The cursor of an [`Editor`].
#[derive(Debug, Clone)]
pub enum Cursor {
diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs
index 3544bde6..747f3a80 100644
--- a/graphics/src/text/editor.rs
+++ b/graphics/src/text/editor.rs
@@ -1,4 +1,4 @@
-use crate::core::text::editor::{self, Action, Cursor};
+use crate::core::text::editor::{self, Action, Cursor, Motion};
use crate::core::text::LineHeight;
use crate::core::{Font, Pixels, Point, Rectangle, Size, Vector};
use crate::text;
@@ -76,10 +76,7 @@ impl editor::Editor for Editor {
let buffer = internal.editor.buffer();
match internal.editor.select_opt() {
- Some(selection)
- if cursor.line != selection.line
- || cursor.index != selection.index =>
- {
+ Some(selection) => {
let line_height = buffer.metrics().line_height;
let scroll_offset = buffer.scroll() as f32 * line_height;
@@ -236,26 +233,87 @@ impl editor::Editor for Editor {
let editor = &mut internal.editor;
- let mut act = |action| editor.action(font_system.raw(), action);
-
match action {
- Action::MoveLeft => act(cosmic_text::Action::Left),
- Action::MoveRight => act(cosmic_text::Action::Right),
- Action::MoveUp => act(cosmic_text::Action::Up),
- Action::MoveDown => act(cosmic_text::Action::Down),
- Action::Insert(c) => act(cosmic_text::Action::Insert(c)),
- Action::Enter => act(cosmic_text::Action::Enter),
- Action::Backspace => act(cosmic_text::Action::Backspace),
- Action::Delete => act(cosmic_text::Action::Delete),
- Action::Click(position) => act(cosmic_text::Action::Click {
- x: position.x as i32,
- y: position.y as i32,
- }),
- Action::Drag(position) => act(cosmic_text::Action::Drag {
- x: position.x as i32,
- y: position.y as i32,
- }),
- _ => todo!(),
+ // Motion events
+ Action::Move(motion) => {
+ if let Some(_selection) = editor.select_opt() {
+ editor.set_select_opt(None);
+ } else {
+ editor.action(
+ font_system.raw(),
+ match motion {
+ Motion::Left => cosmic_text::Action::Left,
+ Motion::Right => cosmic_text::Action::Right,
+ Motion::Up => cosmic_text::Action::Up,
+ Motion::Down => cosmic_text::Action::Down,
+ Motion::WordLeft => cosmic_text::Action::LeftWord,
+ Motion::WordRight => cosmic_text::Action::RightWord,
+ Motion::Home => cosmic_text::Action::Home,
+ Motion::End => cosmic_text::Action::End,
+ Motion::PageUp => cosmic_text::Action::PageUp,
+ Motion::PageDown => cosmic_text::Action::PageDown,
+ Motion::DocumentStart => {
+ cosmic_text::Action::BufferStart
+ }
+ Motion::DocumentEnd => {
+ cosmic_text::Action::BufferEnd
+ }
+ },
+ );
+ }
+ }
+
+ // Selection events
+ Action::Select(_motion) => todo!(),
+ Action::SelectWord => todo!(),
+ Action::SelectLine => todo!(),
+
+ // Editing events
+ Action::Insert(c) => {
+ editor
+ .action(font_system.raw(), cosmic_text::Action::Insert(c));
+ }
+ Action::Enter => {
+ editor.action(font_system.raw(), cosmic_text::Action::Enter);
+ }
+ Action::Backspace => {
+ editor
+ .action(font_system.raw(), cosmic_text::Action::Backspace);
+ }
+ Action::Delete => {
+ editor.action(font_system.raw(), cosmic_text::Action::Delete);
+ }
+
+ // Mouse events
+ Action::Click(position) => {
+ editor.action(
+ font_system.raw(),
+ cosmic_text::Action::Click {
+ x: position.x as i32,
+ y: position.y as i32,
+ },
+ );
+ }
+ Action::Drag(position) => {
+ editor.action(
+ font_system.raw(),
+ cosmic_text::Action::Drag {
+ x: position.x as i32,
+ y: position.y as i32,
+ },
+ );
+
+ // Deselect if selection matches cursor position
+ if let Some(selection) = editor.select_opt() {
+ let cursor = editor.cursor();
+
+ if cursor.line == selection.line
+ && cursor.index == selection.index
+ {
+ editor.set_select_opt(None);
+ }
+ }
+ }
}
editor.shape_as_needed(font_system.raw());
diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs
index a8069069..38c243bd 100644
--- a/widget/src/text_editor.rs
+++ b/widget/src/text_editor.rs
@@ -14,7 +14,7 @@ use crate::core::{
use std::cell::RefCell;
pub use crate::style::text_editor::{Appearance, StyleSheet};
-pub use text::editor::Action;
+pub use text::editor::{Action, Motion};
pub struct TextEditor<'a, Message, Renderer = crate::Renderer>
where
@@ -189,16 +189,16 @@ where
};
match update {
- Update::Unfocus => {
- state.is_focused = false;
- state.is_dragging = false;
- }
Update::Click { click, action } => {
state.is_focused = true;
- state.last_click = Some(click);
state.is_dragging = true;
+ state.last_click = Some(click);
shell.publish(on_edit(action));
}
+ Update::Unfocus => {
+ state.is_focused = false;
+ state.is_dragging = false;
+ }
Update::StopDragging => {
state.is_dragging = false;
}
@@ -352,6 +352,9 @@ impl Update {
padding: Padding,
cursor: mouse::Cursor,
) -> Option<Self> {
+ let edit = |action| Some(Update::Edit(action));
+ let move_ = |motion| Some(Update::Edit(Action::Move(motion)));
+
match event {
Event::Mouse(event) => match event {
mouse::Event::ButtonPressed(mouse::Button::Left) => {
@@ -386,7 +389,7 @@ impl Update {
let cursor_position = cursor.position_in(bounds)?
- Vector::new(padding.top, padding.left);
- Some(Self::Edit(Action::Drag(cursor_position)))
+ edit(Action::Drag(cursor_position))
}
_ => None,
},
@@ -394,37 +397,31 @@ impl Update {
keyboard::Event::KeyPressed {
key_code,
modifiers,
- } if state.is_focused => match key_code {
- keyboard::KeyCode::Left => {
- if platform::is_jump_modifier_pressed(modifiers) {
- Some(Self::Edit(Action::MoveLeftWord))
+ } if state.is_focused => {
+ if let Some(motion) = motion(key_code) {
+ let motion = if modifiers.control() {
+ motion.widen()
} else {
- Some(Self::Edit(Action::MoveLeft))
- }
- }
- keyboard::KeyCode::Right => {
- if platform::is_jump_modifier_pressed(modifiers) {
- Some(Self::Edit(Action::MoveRightWord))
+ motion
+ };
+
+ return edit(if modifiers.shift() {
+ Action::Select(motion)
} else {
- Some(Self::Edit(Action::MoveRight))
- }
- }
- keyboard::KeyCode::Up => Some(Self::Edit(Action::MoveUp)),
- keyboard::KeyCode::Down => {
- Some(Self::Edit(Action::MoveDown))
- }
- keyboard::KeyCode::Enter => Some(Self::Edit(Action::Enter)),
- keyboard::KeyCode::Backspace => {
- Some(Self::Edit(Action::Backspace))
+ Action::Move(motion)
+ });
}
- keyboard::KeyCode::Delete => {
- Some(Self::Edit(Action::Delete))
+
+ match key_code {
+ keyboard::KeyCode::Enter => edit(Action::Enter),
+ keyboard::KeyCode::Backspace => edit(Action::Backspace),
+ keyboard::KeyCode::Delete => edit(Action::Delete),
+ keyboard::KeyCode::Escape => Some(Self::Unfocus),
+ _ => None,
}
- keyboard::KeyCode::Escape => Some(Self::Unfocus),
- _ => None,
- },
+ }
keyboard::Event::CharacterReceived(c) if state.is_focused => {
- Some(Self::Edit(Action::Insert(c)))
+ edit(Action::Insert(c))
}
_ => None,
},
@@ -433,6 +430,20 @@ impl Update {
}
}
+fn motion(key_code: keyboard::KeyCode) -> Option<Motion> {
+ match key_code {
+ keyboard::KeyCode::Left => Some(Motion::Left),
+ keyboard::KeyCode::Right => Some(Motion::Right),
+ keyboard::KeyCode::Up => Some(Motion::Up),
+ keyboard::KeyCode::Down => Some(Motion::Down),
+ keyboard::KeyCode::Home => Some(Motion::Home),
+ keyboard::KeyCode::End => Some(Motion::End),
+ keyboard::KeyCode::PageUp => Some(Motion::PageUp),
+ keyboard::KeyCode::PageDown => Some(Motion::PageDown),
+ _ => None,
+ }
+}
+
mod platform {
use crate::core::keyboard;