implemented selection with up and down arrows, closes #776

This commit is contained in:
Anton-4 2020-12-29 20:18:59 +01:00
parent f67c4324d4
commit 2b0a320734
3 changed files with 170 additions and 9 deletions

View File

@ -1,6 +1,6 @@
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
use crate::tea::model::{Model};
use crate::tea::update::{move_caret_left, move_caret_right};
use crate::tea::update::{move_caret_left, move_caret_right, move_caret_down, move_caret_up};
pub fn handle_keydown(
elem_state: ElementState,
@ -21,7 +21,9 @@ pub fn handle_keydown(
model.selection_opt = new_selection_opt;
},
Up => {
todo!("arrow up");
let (new_caret_pos, new_selection_opt) = move_caret_up(model.caret_pos, model.selection_opt, modifiers.shift(), &model.lines);
model.caret_pos = new_caret_pos;
model.selection_opt = new_selection_opt;
},
Right => {
let (new_caret_pos, new_selection_opt) = move_caret_right(model.caret_pos, model.selection_opt, modifiers.shift(), &model.lines);
@ -29,7 +31,9 @@ pub fn handle_keydown(
model.selection_opt = new_selection_opt;
},
Down => {
todo!("arrow down");
let (new_caret_pos, new_selection_opt) = move_caret_down(model.caret_pos, model.selection_opt, modifiers.shift(), &model.lines);
model.caret_pos = new_caret_pos;
model.selection_opt = new_selection_opt;
},
Copy => {
todo!("copy");

View File

@ -1,3 +1,6 @@
use std::cmp::{Ordering};
#[derive(Debug)]
pub struct Model {
pub lines: Vec<String>,
@ -25,6 +28,26 @@ pub struct Position {
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,

View File

@ -1,6 +1,7 @@
use crate::tea::model::{Position, RawSelection};
use crate::text::{is_newline};
use std::cmp::{min, max};
pub fn move_caret_left(old_caret_pos: Position, old_selection_opt: Option<RawSelection>, shift_pressed: bool, lines: &[String]) -> (Position, Option<RawSelection>) {
let old_line_nr = old_caret_pos.line;
@ -19,6 +20,11 @@ pub fn move_caret_left(old_caret_pos: Position, old_selection_opt: Option<RawSel
(old_line_nr, old_col_nr - 1)
};
let new_caret_pos = Position {
line: line_nr,
column: col_nr
};
let new_selection_opt =
if shift_pressed {
if let Some(old_selection) = old_selection_opt {
@ -62,10 +68,7 @@ pub fn move_caret_left(old_caret_pos: Position, old_selection_opt: Option<RawSel
(
Position {
line: line_nr,
column: col_nr
},
new_caret_pos,
new_selection_opt
)
}
@ -95,6 +98,11 @@ pub fn move_caret_right(old_caret_pos: Position, old_selection_opt: Option<RawSe
(0, 0) // this should never happen, should this method return Result?
};
let new_caret_pos = Position {
line: line_nr,
column: col_nr
};
let new_selection_opt =
if shift_pressed {
if let Some(old_selection) = old_selection_opt {
@ -137,10 +145,136 @@ pub fn move_caret_right(old_caret_pos: Position, old_selection_opt: Option<RawSe
};
(
Position {
line: line_nr,
column: col_nr
},
new_caret_pos,
new_selection_opt
)
}
pub fn move_caret_up(old_caret_pos: Position, old_selection_opt: Option<RawSelection>, shift_pressed: bool, lines: &[String]) -> (Position, Option<RawSelection>) {
let old_line_nr = old_caret_pos.line;
let old_col_nr = old_caret_pos.column;
let (line_nr, col_nr) =
if old_line_nr == 0 {
(old_line_nr, old_col_nr)
} else if let Some(prev_line) = lines.get(old_line_nr - 1) {
if prev_line.len() < old_col_nr {
(old_line_nr - 1, prev_line.len() - 1)
} else {
(old_line_nr - 1, old_col_nr)
}
} else {
(0, 0) // this should never happen, should this method return Result?
};
let new_caret_pos = Position {
line: line_nr,
column: col_nr
};
let new_selection_opt =
if shift_pressed {
if let Some(old_selection) = old_selection_opt {
Some(
RawSelection {
start_pos:
new_caret_pos
,
end_pos:
old_selection.end_pos
,
}
)
} else if !(old_line_nr == line_nr && old_col_nr == col_nr){
Some(
RawSelection {
start_pos:
min(old_caret_pos, new_caret_pos)
,
end_pos:
max(old_caret_pos, new_caret_pos)
,
}
)
} else {
None
}
} else {
None
};
(
new_caret_pos,
new_selection_opt
)
}
pub fn move_caret_down(old_caret_pos: Position, old_selection_opt: Option<RawSelection>, shift_pressed: bool, lines: &[String]) -> (Position, Option<RawSelection>) {
let old_line_nr = old_caret_pos.line;
let old_col_nr = old_caret_pos.column;
let (line_nr, col_nr) =
if old_line_nr + 1 >= lines.len() {
(old_line_nr, old_col_nr)
} else if let Some(next_line) = lines.get(old_line_nr + 1) {
if next_line.len() < old_col_nr {
if let Some(last_char) = next_line.chars().last() {
if is_newline(&last_char) {
(old_line_nr + 1, next_line.len() - 1)
} else {
(old_line_nr + 1, next_line.len())
}
} else {
(old_line_nr + 1, 0)
}
} else {
(old_line_nr + 1, old_col_nr)
}
} else {
(0, 0) // this should never happen, should this method return Result?
};
let new_caret_pos = Position {
line: line_nr,
column: col_nr
};
let new_selection_opt =
if shift_pressed {
if let Some(old_selection) = old_selection_opt {
Some(
RawSelection {
start_pos:
old_selection.start_pos
,
end_pos:
new_caret_pos
,
}
)
} else if !(old_line_nr == line_nr && old_col_nr == col_nr){
Some(
RawSelection {
start_pos:
min(old_caret_pos, new_caret_pos)
,
end_pos:
max(old_caret_pos, new_caret_pos)
,
}
)
} else {
None
}
} else {
None
};
(
new_caret_pos,
new_selection_opt
)
}