use crate::Rectangle;
use crate::widget::Id;
use crate::widget::operation::Operation;
pub trait TextInput {
fn text(&self) -> &str;
fn move_cursor_to_front(&mut self);
fn move_cursor_to_end(&mut self);
fn move_cursor_to(&mut self, position: usize);
fn select_all(&mut self);
fn select_range(&mut self, start: usize, end: usize);
}
pub fn move_cursor_to_front<T>(target: Id) -> impl Operation<T> {
struct MoveCursor {
target: Id,
}
impl<T> Operation<T> for MoveCursor {
fn text_input(
&mut self,
id: Option<&Id>,
_bounds: Rectangle,
state: &mut dyn TextInput,
) {
match id {
Some(id) if id == &self.target => {
state.move_cursor_to_front();
}
_ => {}
}
}
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
operate(self);
}
}
MoveCursor { target }
}
pub fn move_cursor_to_end<T>(target: Id) -> impl Operation<T> {
struct MoveCursor {
target: Id,
}
impl<T> Operation<T> for MoveCursor {
fn text_input(
&mut self,
id: Option<&Id>,
_bounds: Rectangle,
state: &mut dyn TextInput,
) {
match id {
Some(id) if id == &self.target => {
state.move_cursor_to_end();
}
_ => {}
}
}
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
operate(self);
}
}
MoveCursor { target }
}
pub fn move_cursor_to<T>(target: Id, position: usize) -> impl Operation<T> {
struct MoveCursor {
target: Id,
position: usize,
}
impl<T> Operation<T> for MoveCursor {
fn text_input(
&mut self,
id: Option<&Id>,
_bounds: Rectangle,
state: &mut dyn TextInput,
) {
match id {
Some(id) if id == &self.target => {
state.move_cursor_to(self.position);
}
_ => {}
}
}
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
operate(self);
}
}
MoveCursor { target, position }
}
pub fn select_all<T>(target: Id) -> impl Operation<T> {
struct MoveCursor {
target: Id,
}
impl<T> Operation<T> for MoveCursor {
fn text_input(
&mut self,
id: Option<&Id>,
_bounds: Rectangle,
state: &mut dyn TextInput,
) {
match id {
Some(id) if id == &self.target => {
state.select_all();
}
_ => {}
}
}
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
operate(self);
}
}
MoveCursor { target }
}
pub fn select_range<T>(
target: Id,
start: usize,
end: usize,
) -> impl Operation<T> {
struct SelectRange {
target: Id,
start: usize,
end: usize,
}
impl<T> Operation<T> for SelectRange {
fn text_input(
&mut self,
id: Option<&Id>,
_bounds: Rectangle,
state: &mut dyn TextInput,
) {
match id {
Some(id) if id == &self.target => {
state.select_range(self.start, self.end);
}
_ => {}
}
}
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<T>)) {
operate(self);
}
}
SelectRange { target, start, end }
}