Implement Operation::finish for action::widget::Map

This commit is contained in:
Héctor Ramón Jiménez 2022-11-14 00:14:28 +01:00
parent cfdfec9770
commit cbb3475d4c
No known key found for this signature in database
GPG key ID: 140CC052C94F138E

View file

@ -3,6 +3,8 @@ use crate::widget::Id;
use iced_futures::MaybeSend;
use std::rc::Rc;
/// An operation to be performed on the widget tree.
#[allow(missing_debug_implementations)]
pub struct Action<T>(Box<dyn Operation<T>>);
@ -24,7 +26,7 @@ impl<T> Action<T> {
{
Action(Box::new(Map {
operation: self.0,
f: Box::new(f),
f: Rc::new(f),
}))
}
@ -37,7 +39,7 @@ impl<T> Action<T> {
#[allow(missing_debug_implementations)]
struct Map<A, B> {
operation: Box<dyn Operation<A>>,
f: Box<dyn Fn(A) -> B>,
f: Rc<dyn Fn(A) -> B>,
}
impl<A, B> Operation<B> for Map<A, B>
@ -50,38 +52,44 @@ where
id: Option<&Id>,
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
) {
struct MapRef<'a, A, B> {
struct MapRef<'a, A> {
operation: &'a mut dyn Operation<A>,
f: &'a dyn Fn(A) -> B,
}
impl<'a, A, B> Operation<B> for MapRef<'a, A, B> {
impl<'a, A, B> Operation<B> for MapRef<'a, A> {
fn container(
&mut self,
id: Option<&Id>,
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
) {
let Self { operation, f } = self;
let Self { operation, .. } = self;
operation.container(id, &mut |operation| {
operate_on_children(&mut MapRef { operation, f });
operate_on_children(&mut MapRef { operation });
});
}
fn scrollable(&mut self, state: &mut dyn Scrollable, id: Option<&Id>) {
fn scrollable(
&mut self,
state: &mut dyn Scrollable,
id: Option<&Id>,
) {
self.operation.scrollable(state, id);
}
fn focusable(&mut self, state: &mut dyn Focusable, id: Option<&Id>) {
fn focusable(
&mut self,
state: &mut dyn Focusable,
id: Option<&Id>,
) {
self.operation.focusable(state, id);
}
}
let Self { operation, f } = self;
let Self { operation, .. } = self;
MapRef {
operation: operation.as_mut(),
f,
}
.container(id, operate_on_children);
}
@ -109,4 +117,19 @@ where
) {
self.operation.text_input(state, id);
}
fn finish(&self) -> operation::Outcome<B> {
match self.operation.finish() {
operation::Outcome::None => operation::Outcome::None,
operation::Outcome::Some(output) => {
operation::Outcome::Some((self.f)(output))
}
operation::Outcome::Chain(next) => {
operation::Outcome::Chain(Box::new(Map {
operation: next,
f: self.f.clone(),
}))
}
}
}
}