summaryrefslogtreecommitdiffstats
path: root/native/src/widget/text_input
diff options
context:
space:
mode:
authorLibravatar FabianLars <fabianlars@fabianlars.de>2020-02-24 18:03:42 +0100
committerLibravatar FabianLars <fabianlars@fabianlars.de>2020-02-24 18:03:42 +0100
commitc6c8cabdaf03f90b1739be828cf140d8ddb92e65 (patch)
tree07986c2132fd6f66904170e7f745a9d680fd17a7 /native/src/widget/text_input
parent190dcef1553efa181b68caa91b109f83fe289412 (diff)
downloadiced-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.rs176
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,
+ }
+ } */
+}