diff options
author | 2020-03-24 20:36:33 +0100 | |
---|---|---|
committer | 2020-03-24 20:36:33 +0100 | |
commit | 28382a47d3abd4f79064b610f1a2eca478a08595 (patch) | |
tree | 1ddcfc6f7d15293c8287e569ba0ad99cf0c514ee /native/src/widget/text_input | |
parent | 6b89dd7db9715dd46738677e13ca9d9bd12f9636 (diff) | |
download | iced-28382a47d3abd4f79064b610f1a2eca478a08595.tar.gz iced-28382a47d3abd4f79064b610f1a2eca478a08595.tar.bz2 iced-28382a47d3abd4f79064b610f1a2eca478a08595.zip |
Move `Value` to its own module
Diffstat (limited to 'native/src/widget/text_input')
-rw-r--r-- | native/src/widget/text_input/value.rs | 134 |
1 files changed, 134 insertions, 0 deletions
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(), + } + } +} |