summaryrefslogtreecommitdiffstats
path: root/native/src/widget/text_input
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/widget/text_input')
-rw-r--r--native/src/widget/text_input/cursor.rs189
-rw-r--r--native/src/widget/text_input/editor.rs70
-rw-r--r--native/src/widget/text_input/value.rs133
3 files changed, 0 insertions, 392 deletions
diff --git a/native/src/widget/text_input/cursor.rs b/native/src/widget/text_input/cursor.rs
deleted file mode 100644
index 4f3b159b..00000000
--- a/native/src/widget/text_input/cursor.rs
+++ /dev/null
@@ -1,189 +0,0 @@
-//! Track the cursor of a text input.
-use crate::widget::text_input::Value;
-
-/// The cursor of a text input.
-#[derive(Debug, Copy, Clone)]
-pub struct Cursor {
- state: State,
-}
-
-/// The state of a [`Cursor`].
-#[derive(Debug, Copy, Clone)]
-pub enum State {
- /// Cursor without a selection
- Index(usize),
-
- /// Cursor selecting a range of text
- Selection {
- /// The start of the selection
- start: usize,
- /// The end of the selection
- end: usize,
- },
-}
-
-impl Default for Cursor {
- fn default() -> Self {
- Cursor {
- state: State::Index(0),
- }
- }
-}
-
-impl Cursor {
- /// Returns the [`State`] of the [`Cursor`].
- pub fn state(&self, value: &Value) -> State {
- match self.state {
- State::Index(index) => State::Index(index.min(value.len())),
- State::Selection { start, end } => {
- let start = start.min(value.len());
- let end = end.min(value.len());
-
- if start == end {
- State::Index(start)
- } else {
- State::Selection { start, end }
- }
- }
- }
- }
-
- /// Returns the current selection of the [`Cursor`] for the given [`Value`].
- ///
- /// `start` is guaranteed to be <= than `end`.
- pub fn selection(&self, value: &Value) -> Option<(usize, usize)> {
- match self.state(value) {
- State::Selection { start, end } => {
- Some((start.min(end), start.max(end)))
- }
- _ => None,
- }
- }
-
- pub(crate) fn move_to(&mut self, position: usize) {
- self.state = State::Index(position);
- }
-
- pub(crate) fn move_right(&mut self, value: &Value) {
- self.move_right_by_amount(value, 1)
- }
-
- pub(crate) fn move_right_by_words(&mut self, value: &Value) {
- self.move_to(value.next_end_of_word(self.right(value)))
- }
-
- pub(crate) fn move_right_by_amount(
- &mut self,
- value: &Value,
- amount: usize,
- ) {
- match self.state(value) {
- State::Index(index) => {
- self.move_to(index.saturating_add(amount).min(value.len()))
- }
- State::Selection { start, end } => self.move_to(end.max(start)),
- }
- }
-
- pub(crate) fn move_left(&mut self, value: &Value) {
- match self.state(value) {
- State::Index(index) if index > 0 => self.move_to(index - 1),
- State::Selection { start, end } => self.move_to(start.min(end)),
- _ => self.move_to(0),
- }
- }
-
- pub(crate) fn move_left_by_words(&mut self, value: &Value) {
- self.move_to(value.previous_start_of_word(self.left(value)));
- }
-
- pub(crate) fn select_range(&mut self, start: usize, end: usize) {
- if start == end {
- self.state = State::Index(start);
- } else {
- self.state = State::Selection { start, end };
- }
- }
-
- pub(crate) fn select_left(&mut self, value: &Value) {
- match self.state(value) {
- 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(crate) fn select_right(&mut self, value: &Value) {
- match self.state(value) {
- 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(crate) fn select_left_by_words(&mut self, value: &Value) {
- match self.state(value) {
- 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(crate) fn select_right_by_words(&mut self, value: &Value) {
- match self.state(value) {
- 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(crate) fn select_all(&mut self, value: &Value) {
- self.select_range(0, value.len());
- }
-
- pub(crate) fn start(&self, value: &Value) -> usize {
- let start = match self.state {
- State::Index(index) => index,
- State::Selection { start, .. } => start,
- };
-
- start.min(value.len())
- }
-
- pub(crate) fn end(&self, value: &Value) -> usize {
- let end = match self.state {
- State::Index(index) => index,
- State::Selection { end, .. } => end,
- };
-
- end.min(value.len())
- }
-
- fn left(&self, value: &Value) -> usize {
- match self.state(value) {
- State::Index(index) => index,
- State::Selection { start, end } => start.min(end),
- }
- }
-
- fn right(&self, value: &Value) -> usize {
- match self.state(value) {
- State::Index(index) => index,
- State::Selection { start, end } => start.max(end),
- }
- }
-}
diff --git a/native/src/widget/text_input/editor.rs b/native/src/widget/text_input/editor.rs
deleted file mode 100644
index d53fa8d9..00000000
--- a/native/src/widget/text_input/editor.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-use crate::widget::text_input::{Cursor, Value};
-
-pub struct Editor<'a> {
- value: &'a mut Value,
- cursor: &'a mut Cursor,
-}
-
-impl<'a> Editor<'a> {
- pub fn new(value: &'a mut Value, cursor: &'a mut Cursor) -> Editor<'a> {
- Editor { value, cursor }
- }
-
- pub fn contents(&self) -> String {
- self.value.to_string()
- }
-
- pub fn insert(&mut self, character: char) {
- if let Some((left, right)) = self.cursor.selection(self.value) {
- self.cursor.move_left(self.value);
- self.value.remove_many(left, right);
- }
-
- self.value.insert(self.cursor.end(self.value), character);
- self.cursor.move_right(self.value);
- }
-
- pub fn paste(&mut self, content: Value) {
- let length = content.len();
- if let Some((left, right)) = self.cursor.selection(self.value) {
- self.cursor.move_left(self.value);
- self.value.remove_many(left, right);
- }
-
- self.value.insert_many(self.cursor.end(self.value), content);
-
- self.cursor.move_right_by_amount(self.value, length);
- }
-
- pub fn backspace(&mut self) {
- match self.cursor.selection(self.value) {
- Some((start, end)) => {
- self.cursor.move_left(self.value);
- self.value.remove_many(start, end);
- }
- None => {
- let start = self.cursor.start(self.value);
-
- if start > 0 {
- self.cursor.move_left(self.value);
- self.value.remove(start - 1);
- }
- }
- }
- }
-
- pub fn delete(&mut self) {
- match self.cursor.selection(self.value) {
- Some(_) => {
- self.backspace();
- }
- None => {
- let end = self.cursor.end(self.value);
-
- if end < self.value.len() {
- self.value.remove(end);
- }
- }
- }
- }
-}
diff --git a/native/src/widget/text_input/value.rs b/native/src/widget/text_input/value.rs
deleted file mode 100644
index cf4da562..00000000
--- a/native/src/widget/text_input/value.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-use unicode_segmentation::UnicodeSegmentation;
-
-/// The value of a [`TextInput`].
-///
-/// [`TextInput`]: crate::widget::TextInput
-// TODO: Reduce allocations, cache results (?)
-#[derive(Debug, Clone)]
-pub struct Value {
- graphemes: Vec<String>,
-}
-
-impl Value {
- /// Creates a new [`Value`] from a string slice.
- pub fn new(string: &str) -> Self {
- let graphemes = UnicodeSegmentation::graphemes(string, true)
- .map(String::from)
- .collect();
-
- Self { graphemes }
- }
-
- /// Returns whether the [`Value`] is empty or not.
- ///
- /// A [`Value`] is empty when it contains no graphemes.
- pub fn is_empty(&self) -> bool {
- self.len() == 0
- }
-
- /// Returns the total amount of graphemes in the [`Value`].
- pub fn len(&self) -> usize {
- self.graphemes.len()
- }
-
- /// Returns the position of the previous start of a word from the given
- /// grapheme `index`.
- pub fn previous_start_of_word(&self, index: usize) -> usize {
- let previous_string =
- &self.graphemes[..index.min(self.graphemes.len())].concat();
-
- UnicodeSegmentation::split_word_bound_indices(previous_string as &str)
- .filter(|(_, word)| !word.trim_start().is_empty())
- .next_back()
- .map(|(i, previous_word)| {
- index
- - UnicodeSegmentation::graphemes(previous_word, true)
- .count()
- - UnicodeSegmentation::graphemes(
- &previous_string[i + previous_word.len()..] as &str,
- true,
- )
- .count()
- })
- .unwrap_or(0)
- }
-
- /// Returns the position of the next end of a word from the given grapheme
- /// `index`.
- pub fn next_end_of_word(&self, index: usize) -> usize {
- let next_string = &self.graphemes[index..].concat();
-
- UnicodeSegmentation::split_word_bound_indices(next_string as &str)
- .find(|(_, word)| !word.trim_start().is_empty())
- .map(|(i, next_word)| {
- index
- + UnicodeSegmentation::graphemes(next_word, true).count()
- + UnicodeSegmentation::graphemes(
- &next_string[..i] as &str,
- true,
- )
- .count()
- })
- .unwrap_or(self.len())
- }
-
- /// Returns a new [`Value`] containing the graphemes from `start` until the
- /// given `end`.
- pub fn select(&self, start: usize, end: usize) -> Self {
- let graphemes =
- self.graphemes[start.min(self.len())..end.min(self.len())].to_vec();
-
- Self { graphemes }
- }
-
- /// Returns a new [`Value`] containing the graphemes until the given
- /// `index`.
- pub fn until(&self, index: usize) -> Self {
- let graphemes = self.graphemes[..index.min(self.len())].to_vec();
-
- Self { graphemes }
- }
-
- /// Converts the [`Value`] into a `String`.
- pub fn to_string(&self) -> String {
- self.graphemes.concat()
- }
-
- /// Inserts a new `char` at the given grapheme `index`.
- pub fn insert(&mut self, index: usize, c: char) {
- self.graphemes.insert(index, c.to_string());
-
- self.graphemes =
- UnicodeSegmentation::graphemes(&self.to_string() as &str, true)
- .map(String::from)
- .collect();
- }
-
- /// Inserts a bunch of graphemes at the given grapheme `index`.
- pub fn insert_many(&mut self, index: usize, mut value: Value) {
- let _ = self
- .graphemes
- .splice(index..index, value.graphemes.drain(..));
- }
-
- /// Removes the grapheme at the given `index`.
- pub fn remove(&mut self, index: usize) {
- let _ = self.graphemes.remove(index);
- }
-
- /// Removes the graphemes from `start` to `end`.
- pub fn remove_many(&mut self, start: usize, end: usize) {
- let _ = self.graphemes.splice(start..end, std::iter::empty());
- }
-
- /// Returns a new [`Value`] with all its graphemes replaced with the
- /// dot ('•') character.
- pub fn secure(&self) -> Self {
- Self {
- graphemes: std::iter::repeat(String::from("•"))
- .take(self.graphemes.len())
- .collect(),
- }
- }
-}