From e56c45470c9a00e31d92e4e7d4b1cb1894d4de7d Mon Sep 17 00:00:00 2001 From: mtkennerly Date: Fri, 11 Nov 2022 09:15:35 +0800 Subject: Add widget operation to find currently focused widget --- native/src/widget/operation/focusable.rs | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'native/src/widget/operation') diff --git a/native/src/widget/operation/focusable.rs b/native/src/widget/operation/focusable.rs index f17bf178..0067006b 100644 --- a/native/src/widget/operation/focusable.rs +++ b/native/src/widget/operation/focusable.rs @@ -167,3 +167,37 @@ pub fn focus_next() -> impl Operation { count(|count| FocusNext { count, current: 0 }) } + +/// Produces an [`Operation`] that searches for the current focused widget +/// and stores its ID. This ignores widgets that do not have an ID. +pub fn find_focused() -> impl Operation { + struct FindFocused { + focused: Option, + } + + impl Operation for FindFocused { + fn focusable(&mut self, state: &mut dyn Focusable, id: Option<&Id>) { + if state.is_focused() && id.is_some() { + self.focused = id.cloned(); + } + } + + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + + fn finish(&self) -> Outcome { + if let Some(id) = &self.focused { + Outcome::Some(id.clone()) + } else { + Outcome::None + } + } + } + + FindFocused { focused: None } +} -- cgit From c4bca3f2af7ae9b2c8dfc3af48ab73dad852ed34 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Fri, 11 Nov 2022 08:43:36 -0800 Subject: Add text input operations --- native/src/widget/operation/text_input.rs | 131 ++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 native/src/widget/operation/text_input.rs (limited to 'native/src/widget/operation') diff --git a/native/src/widget/operation/text_input.rs b/native/src/widget/operation/text_input.rs new file mode 100644 index 00000000..4c773e99 --- /dev/null +++ b/native/src/widget/operation/text_input.rs @@ -0,0 +1,131 @@ +//! Operate on widgets that have text input. +use crate::widget::operation::Operation; +use crate::widget::Id; + +/// The internal state of a widget that has text input. +pub trait TextInput { + /// Moves the cursor of the text input to the front of the input text. + fn move_cursor_to_front(&mut self); + /// Moves the cursor of the text input to the end of the input text. + fn move_cursor_to_end(&mut self); + /// Moves the cursor of the text input to an arbitrary location. + fn move_cursor_to(&mut self, position: usize); + /// Selects all the content of the text input. + fn select_all(&mut self); +} + +/// Produces an [`Operation`] that moves the cursor of the widget with the given [`Id`] to the +/// front. +pub fn move_cursor_to_front(target: Id) -> impl Operation { + struct MoveCursor { + target: Id, + } + + impl Operation for MoveCursor { + fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { + match id { + Some(id) if id == &self.target => { + state.move_cursor_to_front(); + } + _ => {} + } + } + + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + } + + MoveCursor { target } +} + +/// Produces an [`Operation`] that moves the cursor of the widget with the given [`Id`] to the +/// end. +pub fn move_cursor_to_end(target: Id) -> impl Operation { + struct MoveCursor { + target: Id, + } + + impl Operation for MoveCursor { + fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { + match id { + Some(id) if id == &self.target => { + state.move_cursor_to_end(); + } + _ => {} + } + } + + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + } + + MoveCursor { target } +} + +/// Produces an [`Operation`] that moves the cursor of the widget with the given [`Id`] to the +/// provided position. +pub fn move_cursor_to(target: Id, position: usize) -> impl Operation { + struct MoveCursor { + target: Id, + position: usize, + } + + impl Operation for MoveCursor { + fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { + match id { + Some(id) if id == &self.target => { + state.move_cursor_to(self.position); + } + _ => {} + } + } + + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + } + + MoveCursor { target, position } +} + +/// Produces an [`Operation`] that selects all the content of the widget with the given [`Id`]. +pub fn select_all(target: Id) -> impl Operation { + struct MoveCursor { + target: Id, + } + + impl Operation for MoveCursor { + fn text_input(&mut self, state: &mut dyn TextInput, id: Option<&Id>) { + match id { + Some(id) if id == &self.target => { + state.select_all(); + } + _ => {} + } + } + + fn container( + &mut self, + _id: Option<&Id>, + operate_on_children: &mut dyn FnMut(&mut dyn Operation), + ) { + operate_on_children(self) + } + } + + MoveCursor { target } +} -- cgit