Replace Command with a new Task API with chain support

This commit is contained in:
Héctor Ramón Jiménez 2024-06-14 01:47:39 +02:00
parent e6d0b3bda5
commit a25b1af456
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
74 changed files with 1351 additions and 1767 deletions

View file

@ -10,7 +10,6 @@ use crate::{
Widget,
};
use std::any::Any;
use std::borrow::Borrow;
/// A generic [`Widget`].
@ -305,63 +304,9 @@ where
tree: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<B>,
operation: &mut dyn widget::Operation<()>,
) {
struct MapOperation<'a, B> {
operation: &'a mut dyn widget::Operation<B>,
}
impl<'a, T, B> widget::Operation<T> for MapOperation<'a, B> {
fn container(
&mut self,
id: Option<&widget::Id>,
bounds: Rectangle,
operate_on_children: &mut dyn FnMut(
&mut dyn widget::Operation<T>,
),
) {
self.operation.container(id, bounds, &mut |operation| {
operate_on_children(&mut MapOperation { operation });
});
}
fn focusable(
&mut self,
state: &mut dyn widget::operation::Focusable,
id: Option<&widget::Id>,
) {
self.operation.focusable(state, id);
}
fn scrollable(
&mut self,
state: &mut dyn widget::operation::Scrollable,
id: Option<&widget::Id>,
bounds: Rectangle,
translation: Vector,
) {
self.operation.scrollable(state, id, bounds, translation);
}
fn text_input(
&mut self,
state: &mut dyn widget::operation::TextInput,
id: Option<&widget::Id>,
) {
self.operation.text_input(state, id);
}
fn custom(&mut self, state: &mut dyn Any, id: Option<&widget::Id>) {
self.operation.custom(state, id);
}
}
self.widget.operate(
tree,
layout,
renderer,
&mut MapOperation { operation },
);
self.widget.operate(tree, layout, renderer, operation);
}
fn on_event(
@ -495,7 +440,7 @@ where
state: &mut Tree,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<Message>,
operation: &mut dyn widget::Operation<()>,
) {
self.element
.widget

View file

@ -35,6 +35,7 @@ mod color;
mod content_fit;
mod element;
mod length;
mod maybe;
mod padding;
mod pixels;
mod point;
@ -59,6 +60,7 @@ pub use font::Font;
pub use gradient::Gradient;
pub use layout::Layout;
pub use length::Length;
pub use maybe::{MaybeSend, MaybeSync};
pub use overlay::Overlay;
pub use padding::Padding;
pub use pixels::Pixels;

35
core/src/maybe.rs Normal file
View file

@ -0,0 +1,35 @@
#[cfg(not(target_arch = "wasm32"))]
mod platform {
/// An extension trait that enforces `Send` only on native platforms.
///
/// Useful for writing cross-platform async code!
pub trait MaybeSend: Send {}
impl<T> MaybeSend for T where T: Send {}
/// An extension trait that enforces `Sync` only on native platforms.
///
/// Useful for writing cross-platform async code!
pub trait MaybeSync: Sync {}
impl<T> MaybeSync for T where T: Sync {}
}
#[cfg(target_arch = "wasm32")]
mod platform {
/// An extension trait that enforces `Send` only on native platforms.
///
/// Useful for writing cross-platform async code!
pub trait MaybeSend {}
impl<T> MaybeSend for T {}
/// An extension trait that enforces `Sync` only on native platforms.
///
/// Useful for writing cross-platform async code!
pub trait MaybeSync {}
impl<T> MaybeSync for T {}
}
pub use platform::{MaybeSend, MaybeSync};

View file

@ -41,7 +41,7 @@ where
&mut self,
_layout: Layout<'_>,
_renderer: &Renderer,
_operation: &mut dyn widget::Operation<Message>,
_operation: &mut dyn widget::Operation<()>,
) {
}

View file

@ -5,9 +5,7 @@ use crate::layout;
use crate::mouse;
use crate::renderer;
use crate::widget;
use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size, Vector};
use std::any::Any;
use crate::{Clipboard, Layout, Point, Rectangle, Shell, Size};
/// A generic [`Overlay`].
#[allow(missing_debug_implementations)]
@ -94,7 +92,7 @@ where
&mut self,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<Message>,
operation: &mut dyn widget::Operation<()>,
) {
self.overlay.operate(layout, renderer, operation);
}
@ -146,59 +144,9 @@ where
&mut self,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<B>,
operation: &mut dyn widget::Operation<()>,
) {
struct MapOperation<'a, B> {
operation: &'a mut dyn widget::Operation<B>,
}
impl<'a, T, B> widget::Operation<T> for MapOperation<'a, B> {
fn container(
&mut self,
id: Option<&widget::Id>,
bounds: Rectangle,
operate_on_children: &mut dyn FnMut(
&mut dyn widget::Operation<T>,
),
) {
self.operation.container(id, bounds, &mut |operation| {
operate_on_children(&mut MapOperation { operation });
});
}
fn focusable(
&mut self,
state: &mut dyn widget::operation::Focusable,
id: Option<&widget::Id>,
) {
self.operation.focusable(state, id);
}
fn scrollable(
&mut self,
state: &mut dyn widget::operation::Scrollable,
id: Option<&widget::Id>,
bounds: Rectangle,
translation: Vector,
) {
self.operation.scrollable(state, id, bounds, translation);
}
fn text_input(
&mut self,
state: &mut dyn widget::operation::TextInput,
id: Option<&widget::Id>,
) {
self.operation.text_input(state, id);
}
fn custom(&mut self, state: &mut dyn Any, id: Option<&widget::Id>) {
self.operation.custom(state, id);
}
}
self.content
.operate(layout, renderer, &mut MapOperation { operation });
self.content.operate(layout, renderer, operation);
}
fn on_event(

View file

@ -132,7 +132,7 @@ where
&mut self,
layout: Layout<'_>,
renderer: &Renderer,
operation: &mut dyn widget::Operation<Message>,
operation: &mut dyn widget::Operation<()>,
) {
operation.container(None, layout.bounds(), &mut |operation| {
self.children.iter_mut().zip(layout.children()).for_each(

View file

@ -105,7 +105,7 @@ where
_state: &mut Tree,
_layout: Layout<'_>,
_renderer: &Renderer,
_operation: &mut dyn Operation<Message>,
_operation: &mut dyn Operation<()>,
) {
}

View file

@ -8,15 +8,15 @@ pub use scrollable::Scrollable;
pub use text_input::TextInput;
use crate::widget::Id;
use crate::{Rectangle, Vector};
use crate::{MaybeSend, Rectangle, Vector};
use std::any::Any;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
/// A piece of logic that can traverse the widget tree of an application in
/// order to query or update some widget state.
pub trait Operation<T> {
pub trait Operation<T>: MaybeSend {
/// Operates on a widget that contains other widgets.
///
/// The `operate_on_children` function can be called to return control to
@ -81,7 +81,7 @@ where
/// Maps the output of an [`Operation`] using the given function.
pub fn map<A, B>(
operation: Box<dyn Operation<A>>,
f: impl Fn(A) -> B + 'static,
f: impl Fn(A) -> B + Send + Sync + 'static,
) -> impl Operation<B>
where
A: 'static,
@ -90,7 +90,7 @@ where
#[allow(missing_debug_implementations)]
struct Map<A, B> {
operation: Box<dyn Operation<A>>,
f: Rc<dyn Fn(A) -> B>,
f: Arc<dyn Fn(A) -> B + Send + Sync>,
}
impl<A, B> Operation<B> for Map<A, B>
@ -197,7 +197,7 @@ where
Map {
operation,
f: Rc::new(f),
f: Arc::new(f),
}
}