diff options
Diffstat (limited to '')
| -rw-r--r-- | native/src/widget/text_input.rs | 147 | ||||
| -rw-r--r-- | native/src/widget/text_input/value.rs | 134 | 
2 files changed, 142 insertions, 139 deletions
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index f5ca16e1..7e77b76a 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -4,9 +4,12 @@  //!  //! [`TextInput`]: struct.TextInput.html  //! [`State`]: struct.State.html +mod value; +  pub mod cursor;  pub use cursor::Cursor; +pub use value::Value;  use crate::{      input::{ @@ -19,7 +22,6 @@ use crate::{  };  use std::u32; -use unicode_segmentation::UnicodeSegmentation;  /// A field that can be filled with text.  /// @@ -362,12 +364,12 @@ where                              self.state.cursor.move_left(&self.value);                          }                          None => { -                            if self.state.cursor.start(&self.value) > 0 { +                            let start = self.state.cursor.start(&self.value); + +                            if start > 0 {                                  self.state.cursor.move_left(&self.value); -                                let _ = self.value.remove( -                                    self.state.cursor.start(&self.value), -                                ); +                                let _ = self.value.remove(start - 1);                              }                          }                      } @@ -383,7 +385,7 @@ where                          None => {                              let end = self.state.cursor.end(&self.value); -                            if end > 0 { +                            if end < self.value.len() {                                  let _ = self.value.remove(end);                              }                          } @@ -691,139 +693,6 @@ impl State {      }  } -/// The value of a [`TextInput`]. -/// -/// [`TextInput`]: struct.TextInput.html -// TODO: Reduce allocations, cache results (?) -#[derive(Debug, Clone)] -pub struct Value { -    graphemes: Vec<String>, -} - -impl Value { -    /// Creates a new [`Value`] from a string slice. -    /// -    /// [`Value`]: struct.Value.html -    pub fn new(string: &str) -> Self { -        let graphemes = UnicodeSegmentation::graphemes(string, true) -            .map(String::from) -            .collect(); - -        Self { graphemes } -    } - -    /// Returns the total amount of graphemes in the [`Value`]. -    /// -    /// [`Value`]: struct.Value.html -    pub fn len(&self) -> usize { -        self.graphemes.len() -    } - -    /// Returns the position of the previous start of a word from the given -    /// grapheme `index`. -    /// -    /// [`Value`]: struct.Value.html -    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`. -    /// -    /// [`Value`]: struct.Value.html -    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) -            .filter(|(_, word)| !word.trim_start().is_empty()) -            .next() -            .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 until the given -    /// `index`. -    /// -    /// [`Value`]: struct.Value.html -    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`. -    /// -    /// [`Value`]: struct.Value.html -    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`. -    /// -    /// [`Value`]: struct.Value.html -    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. -    /// -    /// [`Value`]: struct.Value.html -    pub fn secure(&self) -> Self { -        Self { -            graphemes: std::iter::repeat(String::from("•")) -                .take(self.graphemes.len()) -                .collect(), -        } -    } -} -  // TODO: Reduce allocations  fn find_cursor_position<Renderer: self::Renderer>(      renderer: &Renderer, diff --git a/native/src/widget/text_input/value.rs b/native/src/widget/text_input/value.rs new file mode 100644 index 00000000..1e9ba45b --- /dev/null +++ b/native/src/widget/text_input/value.rs @@ -0,0 +1,134 @@ +use unicode_segmentation::UnicodeSegmentation; + +/// The value of a [`TextInput`]. +/// +/// [`TextInput`]: struct.TextInput.html +// TODO: Reduce allocations, cache results (?) +#[derive(Debug, Clone)] +pub struct Value { +    graphemes: Vec<String>, +} + +impl Value { +    /// Creates a new [`Value`] from a string slice. +    /// +    /// [`Value`]: struct.Value.html +    pub fn new(string: &str) -> Self { +        let graphemes = UnicodeSegmentation::graphemes(string, true) +            .map(String::from) +            .collect(); + +        Self { graphemes } +    } + +    /// Returns the total amount of graphemes in the [`Value`]. +    /// +    /// [`Value`]: struct.Value.html +    pub fn len(&self) -> usize { +        self.graphemes.len() +    } + +    /// Returns the position of the previous start of a word from the given +    /// grapheme `index`. +    /// +    /// [`Value`]: struct.Value.html +    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`. +    /// +    /// [`Value`]: struct.Value.html +    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) +            .filter(|(_, word)| !word.trim_start().is_empty()) +            .next() +            .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 until the given +    /// `index`. +    /// +    /// [`Value`]: struct.Value.html +    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`. +    /// +    /// [`Value`]: struct.Value.html +    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`. +    /// +    /// [`Value`]: struct.Value.html +    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. +    /// +    /// [`Value`]: struct.Value.html +    pub fn secure(&self) -> Self { +        Self { +            graphemes: std::iter::repeat(String::from("•")) +                .take(self.graphemes.len()) +                .collect(), +        } +    } +}  | 
