diff --git a/editor/src/keyboard_input.rs b/editor/src/keyboard_input.rs index af3741aca4..3327680241 100644 --- a/editor/src/keyboard_input.rs +++ b/editor/src/keyboard_input.rs @@ -1,13 +1,8 @@ -use crate::mvc; -use crate::mvc::ed_model::{EdModel, Position}; use crate::error::EdResult; use crate::mvc::app_model::AppModel; -use crate::mvc::update::{ - move_caret_down, move_caret_left, move_caret_right, move_caret_up, MoveCaretFun, -}; +use crate::mvc::app_update::{pass_keydown_to_focused, handle_copy, handle_paste}; use winit::event::{ElementState, ModifiersState, VirtualKeyCode}; use winit::event::VirtualKeyCode::*; -use crate::error::EdError::{ClipboardWriteFailed, ClipboardReadFailed}; pub fn handle_keydown( elem_state: ElementState, @@ -21,127 +16,29 @@ pub fn handle_keydown( } match virtual_keycode { - Left => pass_to_focused(app_model, &modifiers, virtual_keycode), - Up => pass_to_focused(app_model, &modifiers, virtual_keycode), - Right => pass_to_focused(app_model, &modifiers, virtual_keycode), - Down => pass_to_focused(app_model, &modifiers, virtual_keycode), + Left => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), + Up => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), + Right => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), + Down => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), - Copy => handle_copy(app_model), - Paste => handle_paste(app_model), + Copy => handle_copy(app_model)?, + Paste => handle_paste(app_model)?, Cut => { + //handle_cut(app_model)? todo!("cut"); } C => if modifiers.ctrl() { - handle_copy(app_model) - } else { Ok(()) }, + handle_copy(app_model)? + }, V => if modifiers.ctrl() { - handle_paste(app_model) - } else { Ok(()) }, - _ => Ok(()) - } -} - -fn pass_to_focused( - app_model: &mut AppModel, - modifiers: &ModifiersState, - virtual_keycode: VirtualKeyCode, -) -> EdResult<()> { - if let Some(ref mut ed_model) = app_model.ed_model_opt { - if ed_model.has_focus { - match virtual_keycode { - Left => handle_arrow(move_caret_left, modifiers, ed_model), - Up => handle_arrow(move_caret_up, modifiers, ed_model), - Right => handle_arrow(move_caret_right, modifiers, ed_model), - Down => handle_arrow(move_caret_down, modifiers, ed_model), - _ => {} - } - } - } - - Ok(()) -} - -fn handle_arrow(move_caret_fun: MoveCaretFun, modifiers: &ModifiersState, ed_model: &mut EdModel) { - let (new_caret_pos, new_selection_opt) = move_caret_fun( - ed_model.caret_pos, - ed_model.selection_opt, - modifiers.shift(), - &ed_model.text_buf, - ); - ed_model.caret_pos = new_caret_pos; - ed_model.selection_opt = new_selection_opt; -} - -fn handle_copy(app_model: &mut AppModel) -> EdResult<()> { - if let Some(ref mut ed_model) = app_model.ed_model_opt { - if ed_model.has_focus { - let selected_str_opt = mvc::ed_model::get_selected_str(ed_model)?; - - if let Some(selected_str) = selected_str_opt { - if let Some(ref mut clipboard) = app_model.clipboard_opt { - clipboard.set_content(selected_str.to_owned())?; - } else { - return Err(ClipboardWriteFailed { - err_msg: "Clipboard was never initialized succesfully.".to_owned() - }) - } - } - } - } - - Ok(()) -} - -fn handle_paste(app_model: &mut AppModel) -> EdResult<()> { - - if let Some(ref mut ed_model) = app_model.ed_model_opt { - if ed_model.has_focus { - if let Some(ref mut clipboard) = app_model.clipboard_opt { - let clipboard_content = clipboard.get_content()?; - - if !clipboard_content.is_empty() { - - let mut rsplit_iter = clipboard_content.rsplit('\n'); - // safe unwrap because we checked if empty - let last_line_nr_chars = rsplit_iter.next().unwrap().len(); - let clipboard_nr_lines = rsplit_iter.count(); - - let old_caret_pos = ed_model.caret_pos; - - if let Some(selection) = ed_model.selection_opt { - let start_caret_pos = selection.start_pos; - ed_model.text_buf.del_selection(selection)?; - ed_model.selection_opt = None; - - ed_model.text_buf.insert_str( - start_caret_pos, - &clipboard_content - )?; - - ed_model.caret_pos = Position { - line: start_caret_pos.line + clipboard_nr_lines, - column: start_caret_pos.column + last_line_nr_chars - } - } else { - ed_model.text_buf.insert_str( - old_caret_pos, - &clipboard_content - )?; - - ed_model.caret_pos = Position { - line: old_caret_pos.line + clipboard_nr_lines, - column: old_caret_pos.column + last_line_nr_chars - } - } - } - - } else { - return Err(ClipboardReadFailed { - err_msg: "Clipboard was never initialized succesfully.".to_owned() - }) - } - } + handle_paste(app_model)? + }, + X => if modifiers.ctrl() { + //handle_cut(app_model)? + todo!("cut"); + }, + _ => () } Ok(()) diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 76f4bcc6d2..9146fe6de7 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -25,7 +25,7 @@ use crate::graphics::style::CODE_FONT_SIZE; use crate::graphics::style::CODE_TXT_XY; use crate::mvc::app_model::AppModel; use crate::mvc::ed_model::EdModel; -use crate::mvc::{ed_model, ed_view, update}; +use crate::mvc::{ed_model, ed_view, ed_update}; use crate::resources::strings::NOTHING_OPENED; use crate::vec_result::get_res; use bumpalo::Bump; @@ -213,7 +213,7 @@ fn run_event_loop(file_path_opt: Option<&Path>) -> Result<(), Box> { event: event::WindowEvent::ReceivedCharacter(ch), .. } => { - if let Err(e) = update::handle_new_char(&mut app_model, &ch) { + if let Err(e) = ed_update::handle_new_char(&mut app_model, &ch) { print_err(&e) } } diff --git a/editor/src/mvc/app_model.rs b/editor/src/mvc/app_model.rs index 12021fd49d..9acda4cd73 100644 --- a/editor/src/mvc/app_model.rs +++ b/editor/src/mvc/app_model.rs @@ -4,6 +4,7 @@ use crate::error::EdError::{ClipboardReadFailed, ClipboardWriteFailed, Clipboard use clipboard::{ClipboardContext, ClipboardProvider}; use std::fmt; + #[derive(Debug)] pub struct AppModel { pub ed_model_opt: Option, diff --git a/editor/src/mvc/app_update.rs b/editor/src/mvc/app_update.rs new file mode 100644 index 0000000000..5e37ea1cfe --- /dev/null +++ b/editor/src/mvc/app_update.rs @@ -0,0 +1,92 @@ +use super::app_model::AppModel; +use super::ed_update; +use super::ed_model::{Position}; +use crate::error::EdResult; +use crate::error::EdError::{ClipboardWriteFailed, ClipboardReadFailed}; +use winit::event::{ModifiersState, VirtualKeyCode}; + +pub fn handle_copy(app_model: &mut AppModel) -> EdResult<()> { + if let Some(ref mut ed_model) = app_model.ed_model_opt { + if ed_model.has_focus { + let selected_str_opt = super::ed_model::get_selected_str(ed_model)?; + + if let Some(selected_str) = selected_str_opt { + if let Some(ref mut clipboard) = app_model.clipboard_opt { + clipboard.set_content(selected_str.to_owned())?; + } else { + return Err(ClipboardWriteFailed { + err_msg: "Clipboard was never initialized succesfully.".to_owned() + }) + } + } + } + } + + Ok(()) +} + +pub fn handle_paste(app_model: &mut AppModel) -> EdResult<()> { + + if let Some(ref mut ed_model) = app_model.ed_model_opt { + if ed_model.has_focus { + if let Some(ref mut clipboard) = app_model.clipboard_opt { + let clipboard_content = clipboard.get_content()?; + + if !clipboard_content.is_empty() { + + let mut rsplit_iter = clipboard_content.rsplit('\n'); + // safe unwrap because we checked if empty + let last_line_nr_chars = rsplit_iter.next().unwrap().len(); + let clipboard_nr_lines = rsplit_iter.count(); + + let old_caret_pos = ed_model.caret_pos; + + if let Some(selection) = ed_model.selection_opt { + let start_caret_pos = selection.start_pos; + ed_model.text_buf.del_selection(selection)?; + ed_model.selection_opt = None; + + ed_model.text_buf.insert_str( + start_caret_pos, + &clipboard_content + )?; + + ed_model.caret_pos = Position { + line: start_caret_pos.line + clipboard_nr_lines, + column: start_caret_pos.column + last_line_nr_chars + } + } else { + ed_model.text_buf.insert_str( + old_caret_pos, + &clipboard_content + )?; + + ed_model.caret_pos = Position { + line: old_caret_pos.line + clipboard_nr_lines, + column: old_caret_pos.column + last_line_nr_chars + } + } + } + + } else { + return Err(ClipboardReadFailed { + err_msg: "Clipboard was never initialized succesfully.".to_owned() + }) + } + } + } + + Ok(()) +} + +pub fn pass_keydown_to_focused( + modifiers: &ModifiersState, + virtual_keycode: VirtualKeyCode, + app_model: &mut AppModel, +) { + if let Some(ref mut ed_model) = app_model.ed_model_opt { + if ed_model.has_focus { + ed_update::handle_key_down(modifiers, virtual_keycode, ed_model); + } + } +} \ No newline at end of file diff --git a/editor/src/mvc/update.rs b/editor/src/mvc/ed_update.rs similarity index 94% rename from editor/src/mvc/update.rs rename to editor/src/mvc/ed_update.rs index 9c25b5a6f3..e6d699549e 100644 --- a/editor/src/mvc/update.rs +++ b/editor/src/mvc/ed_update.rs @@ -5,6 +5,8 @@ use crate::error::EdResult; use crate::text_buffer::TextBuffer; use crate::util::is_newline; use std::cmp::{max, min}; +use winit::event::{ModifiersState, VirtualKeyCode}; +use winit::event::VirtualKeyCode::*; pub type MoveCaretFun = fn(Position, Option, bool, &TextBuffer) -> (Position, Option); @@ -299,6 +301,17 @@ pub fn move_caret_down( (new_caret_pos, new_selection_opt) } +fn handle_arrow(move_caret_fun: MoveCaretFun, modifiers: &ModifiersState, ed_model: &mut EdModel) { + let (new_caret_pos, new_selection_opt) = move_caret_fun( + ed_model.caret_pos, + ed_model.selection_opt, + modifiers.shift(), + &ed_model.text_buf, + ); + ed_model.caret_pos = new_caret_pos; + ed_model.selection_opt = new_selection_opt; +} + fn del_selection(selection: RawSelection, ed_model: &mut EdModel) -> EdResult<()> { ed_model.text_buf.del_selection(selection)?; ed_model.caret_pos = selection.start_pos; @@ -340,7 +353,7 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu ed_model.selection_opt = None; } - '\u{0}'..='\u{32}' | '\u{e000}'..='\u{f8ff}' | '\u{f0000}'..='\u{ffffd}' | '\u{100000}'..='\u{10fffd}' => { + '\u{3}' | '\u{16}' | '\u{30}' | '\u{e000}'..='\u{f8ff}' | '\u{f0000}'..='\u{ffffd}' | '\u{100000}'..='\u{10fffd}' => { // chars that can be ignored } _ => { @@ -371,11 +384,25 @@ pub fn handle_new_char(app_model: &mut AppModel, received_char: &char) -> EdResu Ok(()) } +pub fn handle_key_down( + modifiers: &ModifiersState, + virtual_keycode: VirtualKeyCode, + ed_model: &mut EdModel +) { + match virtual_keycode { + Left => handle_arrow(move_caret_left, modifiers, ed_model), + Up => handle_arrow(move_caret_up, modifiers, ed_model), + Right => handle_arrow(move_caret_right, modifiers, ed_model), + Down => handle_arrow(move_caret_down, modifiers, ed_model), + _ => {} + } +} + #[cfg(test)] mod test_update { use crate::mvc::app_model::AppModel; use crate::mvc::ed_model::{EdModel, Position, RawSelection}; - use crate::mvc::update::handle_new_char; + use crate::mvc::ed_update::handle_new_char; use crate::selection::test_selection::{ all_lines_vec, convert_dsl_to_selection, convert_selection_to_dsl, text_buffer_from_dsl_str, }; diff --git a/editor/src/mvc/mod.rs b/editor/src/mvc/mod.rs index e401205005..330ec21022 100644 --- a/editor/src/mvc/mod.rs +++ b/editor/src/mvc/mod.rs @@ -1,4 +1,5 @@ pub mod app_model; +pub mod app_update; pub mod ed_model; pub mod ed_view; -pub mod update; +pub mod ed_update; diff --git a/editor/src/selection.rs b/editor/src/selection.rs index 502f48fa52..f0bedab2ce 100644 --- a/editor/src/selection.rs +++ b/editor/src/selection.rs @@ -126,7 +126,7 @@ pub fn create_selection_rects<'a>( pub mod test_selection { use crate::error::{EdResult, OutOfBounds}; use crate::mvc::ed_model::{Position, RawSelection}; - use crate::mvc::update::{ + use crate::mvc::ed_update::{ move_caret_down, move_caret_left, move_caret_right, move_caret_up, MoveCaretFun, }; use crate::text_buffer::TextBuffer;