-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: lay groundwork for deferred elements
- Loading branch information
1 parent
47d7a4c
commit 39a825a
Showing
31 changed files
with
482 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
use std::{any::Any, sync::Arc}; | ||
|
||
use crate::{ | ||
element::{ | ||
deferred::{resolver::DeferredResolver, ElementDeferred}, | ||
ElementLifecycle, | ||
}, | ||
unit::Constraints, | ||
widget::Widget, | ||
}; | ||
|
||
pub trait ErasedElementDeferred: ElementLifecycle { | ||
#[allow(private_interfaces)] | ||
fn create_resolver(&self) -> Arc<dyn DeferredResolver>; | ||
|
||
#[allow(private_interfaces)] | ||
fn build(&self, resolver: &dyn DeferredResolver) -> Widget; | ||
} | ||
|
||
impl<T> ErasedElementDeferred for T | ||
where | ||
T: ElementDeferred, | ||
{ | ||
#[allow(private_interfaces)] | ||
fn create_resolver(&self) -> Arc<dyn DeferredResolver> { | ||
Arc::new(ErasedDeferredResolver { | ||
resolver: self.create_resolver(), | ||
|
||
current_param: None, | ||
}) | ||
} | ||
|
||
#[allow(private_interfaces)] | ||
fn build(&self, resolver: &dyn DeferredResolver) -> Widget { | ||
let param = resolver | ||
.param() | ||
.expect("deferred elements must be resolved before being built") | ||
.downcast_ref::<T::Param>() | ||
.expect("failed to downcast deferred element param"); | ||
|
||
ElementDeferred::build(self, param) | ||
} | ||
} | ||
|
||
pub(crate) struct ErasedDeferredResolver<ResolverFn, Param> { | ||
resolver: ResolverFn, | ||
|
||
current_param: Option<Param>, | ||
} | ||
|
||
impl<ResolverFn, Param> DeferredResolver for ErasedDeferredResolver<ResolverFn, Param> | ||
where | ||
ResolverFn: Fn(Constraints) -> Param + Send + Sync + 'static, | ||
Param: Any + PartialEq + Send + Sync, | ||
{ | ||
fn resolve(&mut self, constraints: Constraints) -> bool { | ||
let param = (self.resolver)(constraints); | ||
|
||
if self | ||
.current_param | ||
.as_ref() | ||
.map(|p| p == ¶m) | ||
.unwrap_or(false) | ||
{ | ||
return false; | ||
} | ||
|
||
self.current_param = Some(param); | ||
|
||
true | ||
} | ||
|
||
fn param(&self) -> Option<&(dyn Any + Send)> { | ||
self.current_param.as_ref().map(|p| p as &(dyn Any + Send)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use crate::{unit::Constraints, widget::Widget}; | ||
|
||
use super::lifecycle::ElementLifecycle; | ||
|
||
pub mod erased; | ||
pub mod resolver; | ||
|
||
/// A deferred element is an element that is not immediately build its children, | ||
/// but instead waits until the layout phase to do so. | ||
/// | ||
/// It creates a resolver that is passed into the layout phase, which is used to | ||
/// determine if the element needs to be rebuilt. If the resolver returns a value | ||
/// that is not equal to the previous value, the element will be rebuilt. | ||
/// | ||
/// Resolver functions should be cheap to call, and should _only_ return a different | ||
/// value if it is absolutely necessary, as it will stall the rendering phase in | ||
/// order to rebuild the element leading to a poor user experience. | ||
pub trait ElementDeferred: ElementLifecycle { | ||
type Param: PartialEq + Send + Sync; | ||
|
||
fn create_resolver(&self) -> impl Fn(Constraints) -> Self::Param + Send + Sync + 'static; | ||
|
||
fn build(&self, param: &Self::Param) -> Widget; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use std::any::Any; | ||
|
||
use crate::unit::Constraints; | ||
|
||
pub(crate) trait DeferredResolver: Any + Send + Sync { | ||
fn resolve(&mut self, constraints: Constraints) -> bool; | ||
|
||
fn param(&self) -> Option<&(dyn Any + Send)>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.