diff options
author | 2020-02-24 18:03:42 +0100 | |
---|---|---|
committer | 2020-02-24 18:03:42 +0100 | |
commit | c6c8cabdaf03f90b1739be828cf140d8ddb92e65 (patch) | |
tree | 07986c2132fd6f66904170e7f745a9d680fd17a7 /native/src/widget/text_input | |
parent | 190dcef1553efa181b68caa91b109f83fe289412 (diff) | |
download | iced-c6c8cabdaf03f90b1739be828cf140d8ddb92e65.tar.gz iced-c6c8cabdaf03f90b1739be828cf140d8ddb92e65.tar.bz2 iced-c6c8cabdaf03f90b1739be828cf140d8ddb92e65.zip |
moved cursor into own file
moved click tracking as a new State struct to input::mouse
made cursor field of text_input state private
brought back cursor type(Index, Selection) representation with a state enum
cleaned out some stuff (but not enough/all)
TODO: Documentation (sigh)
TODO: Editor struct
TODO: some (hopefully) small improvements here and there
Diffstat (limited to 'native/src/widget/text_input')
-rw-r--r-- | native/src/widget/text_input/cursor.rs | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/native/src/widget/text_input/cursor.rs b/native/src/widget/text_input/cursor.rs new file mode 100644 index 00000000..bbf5448b --- /dev/null +++ b/native/src/widget/text_input/cursor.rs @@ -0,0 +1,176 @@ +use crate::widget::text_input::Value; + +#[derive(Debug, Copy, Clone)] +enum State { + Index(usize), + Selection { start: usize, end: usize }, +} + +#[derive(Debug, Copy, Clone)] +pub struct Cursor { + state: State, +} + +impl Default for Cursor { + fn default() -> Self { + Cursor { + state: State::Index(0), + } + } +} + +impl Cursor { + /* index move methods */ + pub fn move_to(&mut self, position: usize) { + self.state = State::Index(position); + } + + pub fn move_right(&mut self, value: &Value) { + self.move_right_by_amount(value, 1) + } + + pub fn move_right_by_words(&mut self, value: &Value) { + self.move_to(value.next_end_of_word(self.right())) + } + + pub fn move_right_by_amount(&mut self, value: &Value, amount: usize) { + match self.state { + State::Index(index) => { + self.move_to(index.saturating_add(amount).min(value.len())) + } + State::Selection { .. } => self.move_to(self.right()), + } + } + + pub fn move_left(&mut self) { + match self.state { + State::Index(index) if index > 0 => self.move_to(index - 1), + State::Selection { .. } => self.move_to(self.left()), + _ => self.move_to(0), + } + } + + pub fn move_left_by_words(&mut self, value: &Value) { + self.move_to(value.previous_start_of_word(self.right())); + } + /* end of index move methods */ + + /* expand/shrink selection */ + // TODO: (whole section): Return State::Cursor if start == end after operation + pub fn select_range(&mut self, start: usize, end: usize) { + self.state = State::Selection { start, end }; + } + + pub fn select_left(&mut self) { + match self.state { + State::Index(index) if index > 0 => { + self.select_range(index, index - 1) + } + State::Selection { start, end } if end > 0 => { + self.select_range(start, end - 1) + } + _ => (), + } + } + + pub fn select_right(&mut self, value: &Value) { + match self.state { + State::Index(index) if index < value.len() => { + self.select_range(index, index + 1) + } + State::Selection { start, end } if end < value.len() => { + self.select_range(start, end + 1) + } + _ => (), + } + } + + pub fn select_left_by_words(&mut self, value: &Value) { + match self.state { + State::Index(index) => { + self.select_range(index, value.previous_start_of_word(index)) + } + State::Selection { start, end } => { + self.select_range(start, value.previous_start_of_word(end)) + } + } + } + + pub fn select_right_by_words(&mut self, value: &Value) { + match self.state { + State::Index(index) => { + self.select_range(index, value.next_end_of_word(index)) + } + State::Selection { start, end } => { + self.select_range(start, value.next_end_of_word(end)) + } + } + } + + pub fn select_all(&mut self, value: &Value) { + self.select_range(0, value.len()); + } + /* end of selection section */ + + /* helpers */ + // get start position of selection (can be left OR right boundary of selection) or index + pub(crate) fn start(&self) -> usize { + match self.state { + State::Index(index) => index, + State::Selection { start, .. } => start, + } + } + + // get end position of selection (can be left OR right boundary of selection) or index + pub fn end(&self) -> usize { + match self.state { + State::Index(index) => index, + State::Selection { end, .. } => end, + } + } + + // get left boundary of selection or index + pub fn left(&self) -> usize { + match self.state { + State::Index(index) => index, + State::Selection { start, end } => start.min(end), + } + } + + // get right boundary of selection or index + pub fn right(&self) -> usize { + match self.state { + State::Index(index) => index, + State::Selection { start, end } => start.max(end), + } + } + + pub fn draw_position(&self, value: &Value) -> usize { + self.cursor_position(value) + } + + pub fn cursor_position(&self, value: &Value) -> usize { + match self.state { + State::Index(index) => index.min(value.len()), + State::Selection { end, .. } => end.min(value.len()), + } + } + + // returns Option of left and right border of selection + // a second method return start and end may be useful (see below) + pub fn selection_position(&self) -> Option<(usize, usize)> { + match self.state { + State::Selection { start, end } => { + Some((start.min(end), start.max(end))) + } + _ => None, + } + } + + /* pub fn selection_position(&self) -> Option<(usize, usize)> { + match self.state { + State::Selection { start, end } => Some((start, end)), + _ => None, + } + } */ +} |