use std::rc::Rc;
use unicode_segmentation::UnicodeSegmentation;
use super::{TextFieldBuffer, TextFieldValue, TextRange};
#[derive(Clone)]
pub struct InputTransformation(Rc<Transform>);
type Transform = dyn Fn(&TextFieldValue, &mut TextFieldBuffer);
impl InputTransformation {
pub fn new(transform: impl Fn(&TextFieldValue, &mut TextFieldBuffer) + 'static) -> Self {
Self(Rc::new(transform))
}
pub fn max_length(max: usize) -> Self {
Self::new(move |original, buffer| {
if buffer.len() >= original.text.len()
&& buffer.text().graphemes(true).nth(max).is_some()
{
buffer.reset_to(original);
}
})
}
pub fn by_value(filter: impl Fn(&str, &str) -> Option<String> + 'static) -> Self {
Self::new(move |original, buffer| {
let Some(replacement) = filter(&original.text, buffer.text()) else {
return;
};
if replacement == original.text {
buffer.reset_to(original);
} else {
buffer.replace(TextRange::all(buffer.len()), &replacement);
}
})
}
pub fn then(self, next: Self) -> Self {
Self::new(move |original, buffer| {
(self.0)(original, buffer);
(next.0)(original, buffer);
})
}
pub(crate) fn transform(&self, original: &TextFieldValue, buffer: &mut TextFieldBuffer) {
(self.0)(original, buffer);
}
}
impl std::fmt::Debug for InputTransformation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("InputTransformation")
}
}
impl PartialEq for InputTransformation {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}