summaryrefslogtreecommitdiffstats
path: root/native
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-08-02 04:20:47 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2022-08-02 04:20:47 +0200
commit77c6864e7c772c5e228bc09fe40c2c0b8884386d (patch)
treebad8540154db00567937a2e357e3bd271b509f23 /native
parent6dac049db5824e3af06bc16df0fdf51f8809aeb4 (diff)
downloadiced-77c6864e7c772c5e228bc09fe40c2c0b8884386d.tar.gz
iced-77c6864e7c772c5e228bc09fe40c2c0b8884386d.tar.bz2
iced-77c6864e7c772c5e228bc09fe40c2c0b8884386d.zip
Implement `focus_next` operation
... as well as a `count_focusable` composable helper!
Diffstat (limited to 'native')
-rw-r--r--native/src/widget/operation.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/native/src/widget/operation.rs b/native/src/widget/operation.rs
index 2cfba005..5a0f0c18 100644
--- a/native/src/widget/operation.rs
+++ b/native/src/widget/operation.rs
@@ -58,3 +58,96 @@ pub fn focus<T>(target: Id) -> impl Operation<T> {
Focus { target }
}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub struct FocusCount {
+ focused: Option<usize>,
+ total: usize,
+}
+
+pub fn count_focusable<T, O>(f: fn(FocusCount) -> O) -> impl Operation<T>
+where
+ O: Operation<T> + 'static,
+{
+ struct CountFocusable<O> {
+ count: FocusCount,
+ next: fn(FocusCount) -> O,
+ }
+
+ impl<T, O> Operation<T> for CountFocusable<O>
+ where
+ O: Operation<T> + 'static,
+ {
+ fn focusable(
+ &mut self,
+ state: &mut dyn state::Focusable,
+ _id: Option<&Id>,
+ ) {
+ if state.is_focused() {
+ self.count.focused = Some(self.count.total);
+ }
+
+ self.count.total += 1;
+ }
+
+ fn container(
+ &mut self,
+ _id: Option<&Id>,
+ operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
+ ) {
+ operate_on_children(self)
+ }
+
+ fn finish(&self) -> Outcome<T> {
+ Outcome::Chain(Box::new((self.next)(self.count)))
+ }
+ }
+
+ CountFocusable {
+ count: FocusCount::default(),
+ next: f,
+ }
+}
+
+pub fn focus_next<T>() -> impl Operation<T> {
+ struct FocusNext {
+ count: FocusCount,
+ current: usize,
+ }
+
+ impl<T> Operation<T> for FocusNext {
+ fn focusable(
+ &mut self,
+ state: &mut dyn state::Focusable,
+ _id: Option<&Id>,
+ ) {
+ if self.count.total == 0 {
+ return;
+ }
+
+ match self.count.focused {
+ None if self.current == 0 => state.focus(),
+ Some(focused) if focused == self.current => state.unfocus(),
+ Some(focused) if focused + 1 == self.current => state.focus(),
+ Some(focused)
+ if focused == self.count.total - 1 && self.current == 0 =>
+ {
+ state.focus()
+ }
+ _ => {}
+ }
+
+ self.current += 1;
+ }
+
+ fn container(
+ &mut self,
+ _id: Option<&Id>,
+ operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
+ ) {
+ operate_on_children(self)
+ }
+ }
+
+ count_focusable(|count| FocusNext { count, current: 0 })
+}