Home + End keys, refactoring for seperate ui folder/lib

This commit is contained in:
Anton-4 2021-02-12 19:38:20 +01:00
parent 299018aa34
commit 9dda23cf8b
13 changed files with 2490 additions and 49 deletions

View file

@ -15,10 +15,7 @@ pub fn handle_keydown(
} }
match virtual_keycode { match virtual_keycode {
Left => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), Left | Up | Right | Down => 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)?, Copy => handle_copy(app_model)?,
Paste => handle_paste(app_model)?, Paste => handle_paste(app_model)?,
@ -39,7 +36,7 @@ pub fn handle_keydown(
} }
} }
A => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model), A | Home | End => pass_keydown_to_focused(&modifiers, virtual_keycode, app_model),
_ => (), _ => (),
} }

View file

@ -53,6 +53,7 @@ mod keyboard_input;
pub mod lang; pub mod lang;
mod mvc; mod mvc;
//pub mod mvc; // for benchmarking //pub mod mvc; // for benchmarking
mod ui;
mod resources; mod resources;
mod selection; mod selection;
mod text_buffer; mod text_buffer;

View file

@ -2,8 +2,6 @@ use crate::error::EdResult;
use crate::graphics::primitives::rect::Rect; use crate::graphics::primitives::rect::Rect;
use crate::text_buffer; use crate::text_buffer;
use crate::text_buffer::TextBuffer; use crate::text_buffer::TextBuffer;
use std::cmp::Ordering;
use std::fmt;
use std::path::Path; use std::path::Path;
#[derive(Debug)] #[derive(Debug)]
@ -47,45 +45,3 @@ impl EdModel {
Ok(()) Ok(())
} }
} }
#[derive(Debug, Copy, Clone)]
pub struct Position {
pub line: usize,
pub column: usize,
}
impl Ord for Position {
fn cmp(&self, other: &Self) -> Ordering {
(self.line, self.column).cmp(&(other.line, other.column))
}
}
impl PartialOrd for Position {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Position {
fn eq(&self, other: &Self) -> bool {
(self.line, self.column) == (other.line, other.column)
}
}
impl Eq for Position {}
#[derive(Debug, Copy, Clone)]
pub struct RawSelection {
pub start_pos: Position,
pub end_pos: Position,
}
impl std::fmt::Display for RawSelection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"RawSelection: start_pos: line:{} col:{}, end_pos: line:{} col:{}",
self.start_pos.line, self.start_pos.column, self.end_pos.line, self.end_pos.column
)
}
}

View file

@ -332,6 +332,83 @@ pub fn handle_select_all(ed_model: &mut EdModel) {
} }
} }
impl EdModel {
pub fn move_caret_w_mods(&mut self, new_pos: Position, mods: &ModifiersState) {
let caret_pos = self.caret_pos;
// one does not simply move the caret
if new_pos != caret_pos {
if mods.shift() {
if let Some(selection) = self.selection_opt {
if new_pos < selection.start_pos {
if caret_pos > selection.start_pos {
self.set_selection(
new_pos,
selection.start_pos
)
} else {
self.set_selection(
new_pos,
selection.end_pos
)
}
} else if new_pos > selection.end_pos {
if caret_pos < selection.end_pos {
self.set_selection(
selection.end_pos,
new_pos
)
} else {
self.set_selection(
selection.start_pos,
new_pos
)
}
} else if new_pos > caret_pos {
self.set_selection(
new_pos,
selection.end_pos
)
} else if new_pos < caret_pos {
self.set_selection(
selection.start_pos,
new_pos
)
}
} else if new_pos < self.caret_pos {
self.set_selection(
new_pos,
caret_pos
)
} else {
self.set_selection(
caret_pos,
new_pos
)
}
} else {
self.selection_opt = None;
}
self.caret_pos = new_pos;
}
}
pub fn set_selection(&mut self, start_pos: Position, end_pos: Position) {
self.selection_opt =
if start_pos != end_pos {
Some(
RawSelection {
start_pos,
end_pos
}
)
} else {
None
}
}
}
pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<()> { pub fn handle_new_char(received_char: &char, ed_model: &mut EdModel) -> EdResult<()> {
let old_caret_pos = ed_model.caret_pos; let old_caret_pos = ed_model.caret_pos;
@ -418,6 +495,53 @@ pub fn handle_key_down(
handle_select_all(ed_model) handle_select_all(ed_model)
} }
} }
Home => {
let curr_line_nr = ed_model.caret_pos.line;
// TODO no unwrap
let curr_line_str = ed_model.text_buf.line(curr_line_nr).unwrap();
let line_char_iter = curr_line_str.chars();
let mut first_no_space_char_col = 0;
let mut non_space_found = false;
for c in line_char_iter {
if !c.is_whitespace() {
non_space_found = true;
break;
} else {
first_no_space_char_col += 1;
}
}
if !non_space_found {
first_no_space_char_col = 0;
}
ed_model.move_caret_w_mods(
Position {
line: ed_model.caret_pos.line,
column: first_no_space_char_col
},
modifiers
)
}
End => {
let curr_line = ed_model.caret_pos.line;
// TODO no unwrap
let new_col =
max(
0,
ed_model.text_buf.line_len(curr_line).unwrap() - 1
);
let new_pos =
Position {
line: curr_line,
column: new_col
};
ed_model.move_caret_w_mods(new_pos, modifiers);
}
_ => {} _ => {}
} }
} }
@ -622,4 +746,8 @@ pub mod test_ed_update {
Ok(()) Ok(())
} }
// TODO hometest
// TODO endtest
} }

20
editor/src/ui/error.rs Normal file
View file

@ -0,0 +1,20 @@
use snafu::{Backtrace, ErrorCompat, Snafu};
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum UIError {
#[snafu(display(
"OutOfBounds: index {} was out of bounds for {} with length {}.",
index,
collection_name,
len
))]
OutOfBounds {
index: usize,
collection_name: String,
len: usize,
backtrace: Backtrace,
},
}
pub type UIResult<T, E = UIError> = std::result::Result<T, E>;

3
editor/src/ui/mod.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod error;
pub mod model;
pub mod update;

View file

@ -0,0 +1 @@
pub mod text;

View file

@ -0,0 +1,3 @@
pub mod selectable_text_m;
pub mod selection;
pub mod txt_pos;

View file

@ -0,0 +1,48 @@
use crate::ui::error::UIResult;
use super::txt_pos::TxtPos;
use std::fmt;
impl std::fmt::Display for RawSelection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"RawSelection: start_pos: line:{} col:{}, end_pos: line:{} col:{}",
self.start_pos.line, self.start_pos.column, self.end_pos.line, self.end_pos.column
)
}
}
trait SelectableLines {
fn get_line(&self, line_nr: usize) -> UIResult<&str>;
fn line_len(&self, line_nr: usize) -> UIResult<usize>;
fn nr_of_lines(&self) -> usize;
fn nr_of_chars(&self) -> usize;
// TODO use pool allocation here
fn all_lines<'a>(&self, arena: &'a Bump) -> BumpString<'a>;
fn last_TxtPos(&self) -> TxtPos;
fn get_selection(&self, raw_sel: RawSelection) -> UIResult<&str>;
}
trait MutSelectableLines {
fn insert_char(&mut self, caret_pos: TxtPos, new_char: &char) -> UIResult<()>;
fn insert_str(&mut self, caret_pos: TxtPos, new_str: &str) -> UIResult<()>;
fn pop_char(&mut self, caret_pos: TxtPos);
fn del_selection(&mut self, raw_sel: RawSelection) -> UIResult<()>;
}
#[derive(Debug)]
pub struct SelectableText {
pub lines: SelectableLines,
pub caret_pos: TxtPos,
pub selection_opt: Option<RawSelection>,
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
use std::cmp::Ordering;
#[derive(Debug, Copy, Clone)]
pub struct TxtPos {
pub line: usize,
pub column: usize,
}
impl Ord for TxtPos {
fn cmp(&self, other: &Self) -> Ordering {
(self.line, self.column).cmp(&(other.line, other.column))
}
}
impl PartialOrd for TxtPos {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for TxtPos {
fn eq(&self, other: &Self) -> bool {
(self.line, self.column) == (other.line, other.column)
}
}
impl Eq for TxtPos {}

View file

@ -0,0 +1 @@
pub mod SelectableTextU;

View file

@ -0,0 +1,62 @@
impl SelectableText {
pub fn move_caret_w_mods(&mut self, new_pos: Position, mods: &ModifiersState) {
let caret_pos = self.caret_pos;
// one does not simply move the caret
if new_pos != caret_pos {
if mods.shift() {
if let Some(selection) = self.selection_opt {
if new_pos < selection.start_pos {
if caret_pos > selection.start_pos {
self.set_selection(
new_pos,
selection.start_pos
)
} else {
self.set_selection(
new_pos,
selection.end_pos
)
}
} else if new_pos > selection.end_pos {
if caret_pos < selection.end_pos {
self.set_selection(
selection.end_pos,
new_pos
)
} else {
self.set_selection(
selection.start_pos,
new_pos
)
}
} else if new_pos > caret_pos {
self.set_selection(
new_pos,
selection.end_pos
)
} else if new_pos < caret_pos {
self.set_selection(
selection.start_pos,
new_pos
)
}
} else if new_pos < self.caret_pos {
self.set_selection(
new_pos,
caret_pos
)
} else {
self.set_selection(
caret_pos,
new_pos
)
}
} else {
self.selection_opt = None;
}
self.caret_pos = new_pos;
}
}
}