Debug
This commit is contained in:
parent
faf8fb546f
commit
4eb58acf66
|
@ -1,3 +1,6 @@
|
|||
* `easing` attribute in when conditions not working.
|
||||
- They don't apply.
|
||||
|
||||
# TextInput
|
||||
|
||||
* Touch selection.
|
||||
|
@ -28,6 +31,8 @@ TextInput! {
|
|||
|
||||
# Accessibility
|
||||
|
||||
* panicked at 'assertion failed: self.nodes.contains_key(&self.focus)'
|
||||
- Run icon example, search z, click a button.
|
||||
* All examples must be fully useable with a screen reader.
|
||||
- Test OS defaults and NVDA.
|
||||
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
use std::{any::Any, sync::Arc, time::Duration};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use zero_ui_var::{
|
||||
animation::{
|
||||
easing::{EasingStep, EasingTime},
|
||||
AnimationHandle, Transitionable,
|
||||
Transitionable,
|
||||
},
|
||||
*,
|
||||
};
|
||||
|
@ -319,99 +318,6 @@ impl_easing_property_inputs! {
|
|||
I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
|
||||
}
|
||||
|
||||
/// Easing when extension for ArcWhenVar.
|
||||
pub trait VarEasingWhen<T: VarValue>: Var<T> {
|
||||
/// Create a variable similar to [`Var::easing`], but with different duration and easing functions for each condition.
|
||||
///
|
||||
/// The `condition_easing` must contain one entry for each when condition, entries can be `None`, the easing used
|
||||
/// is the first entry that corresponds to a `true` condition, or falls-back to the `default_easing`.
|
||||
fn easing_when(
|
||||
&self,
|
||||
condition_easing: Vec<Option<(Duration, EasingFn)>>,
|
||||
default_easing: (Duration, EasingFn),
|
||||
) -> types::ContextualizedVar<T, ReadOnlyArcVar<T>>
|
||||
where
|
||||
T: Transitionable;
|
||||
}
|
||||
impl<T: VarValue> VarEasingWhen<T> for super::types::ArcWhenVar<T> {
|
||||
fn easing_when(
|
||||
&self,
|
||||
condition_easing: Vec<Option<(Duration, EasingFn)>>,
|
||||
default_easing: (Duration, EasingFn),
|
||||
) -> types::ContextualizedVar<T, ReadOnlyArcVar<T>>
|
||||
where
|
||||
T: Transitionable,
|
||||
{
|
||||
let source = self.clone();
|
||||
types::ContextualizedVar::new(Arc::new(move || {
|
||||
debug_assert_eq!(source.conditions().len(), condition_easing.len());
|
||||
|
||||
let source_wk = source.downgrade();
|
||||
let easing_var = super::var(source.get());
|
||||
|
||||
let condition_easing = condition_easing.clone();
|
||||
let default_easing = default_easing.clone();
|
||||
let mut _anim_handle = AnimationHandle::dummy();
|
||||
var_bind(&source, &easing_var, move |value, _, easing_var| {
|
||||
let source = source_wk.upgrade().unwrap();
|
||||
for ((c, _), easing) in source.conditions().iter().zip(&condition_easing) {
|
||||
if let Some((duration, func)) = easing {
|
||||
if c.get() {
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (duration, func) = &default_easing;
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
})
|
||||
.perm();
|
||||
easing_var.read_only()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
fn var_bind<I, O, V>(
|
||||
input: &impl Var<I>,
|
||||
output: &V,
|
||||
update_output: impl FnMut(&I, &VarHookArgs, <V::Downgrade as WeakVar<O>>::Upgrade) + Send + 'static,
|
||||
) -> VarHandle
|
||||
where
|
||||
I: VarValue,
|
||||
O: VarValue,
|
||||
V: Var<O>,
|
||||
{
|
||||
var_bind_ok(input, output.downgrade(), update_output)
|
||||
}
|
||||
|
||||
fn var_bind_ok<I, O, W>(
|
||||
input: &impl Var<I>,
|
||||
wk_output: W,
|
||||
update_output: impl FnMut(&I, &VarHookArgs, W::Upgrade) + Send + 'static,
|
||||
) -> VarHandle
|
||||
where
|
||||
I: VarValue,
|
||||
O: VarValue,
|
||||
W: WeakVar<O>,
|
||||
{
|
||||
let update_output = Mutex::new(update_output);
|
||||
input.hook(Box::new(move |args| {
|
||||
if let Some(output) = wk_output.upgrade() {
|
||||
if output.capabilities().contains(VarCapabilities::MODIFY) {
|
||||
if let Some(value) = args.downcast_value::<I>() {
|
||||
update_output.lock()(value, args, output);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
/// Variable for state properties (`is_*`, `has_*`).
|
||||
///
|
||||
/// State variables are `bool` probes that are set by the property, they are created automatically
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
use std::{any::Any, sync::Arc, time::Duration};
|
||||
|
||||
use crate::{
|
||||
units::*,
|
||||
var::{animation::AnimationHandle, WeakVar},
|
||||
widget_builder::{AnyPropertyBuildAction, PropertyBuildAction, PropertyInputTypes, WhenBuildAction},
|
||||
};
|
||||
|
||||
use super::{animation::Transitionable, types, BoxedVar, ReadOnlyArcVar, Var, VarValue};
|
||||
|
||||
type EasingFn = Arc<dyn Fn(EasingTime) -> EasingStep + Send + Sync>;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait easing_property: Send + Sync + Clone + Copy {
|
||||
fn easing_property_unset(self);
|
||||
fn easing_property(self, duration: Duration, easing: EasingFn) -> Vec<Box<dyn AnyPropertyBuildAction>>;
|
||||
fn easing_when_data(self, duration: Duration, easing: EasingFn) -> WhenBuildAction;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait easing_property_input_Transitionable: Any + Send {
|
||||
fn easing(self, duration: Duration, easing: EasingFn, when_conditions_data: &[Option<Arc<dyn Any + Send + Sync>>]) -> Self;
|
||||
}
|
||||
impl<T: VarValue + Transitionable> easing_property_input_Transitionable for BoxedVar<T> {
|
||||
fn easing(self, duration: Duration, easing: EasingFn, when_conditions_data: &[Option<Arc<dyn Any + Send + Sync>>]) -> Self {
|
||||
if let Some(when) = self.as_any().downcast_ref::<types::ContextualizedVar<T, types::ArcWhenVar<T>>>() {
|
||||
let conditions: Vec<_> = when_conditions_data
|
||||
.iter()
|
||||
.map(|d| d.as_ref().and_then(|d| d.downcast_ref::<(Duration, EasingFn)>().cloned()))
|
||||
.collect();
|
||||
|
||||
if conditions.iter().any(|c| c.is_some()) {
|
||||
let when = when.clone();
|
||||
return types::ContextualizedVar::new(Arc::new(move || {
|
||||
when.borrow_init().easing_when(conditions.clone(), (duration, easing.clone()))
|
||||
}))
|
||||
.boxed();
|
||||
}
|
||||
}
|
||||
Var::easing(&self, duration, move |t| easing(t)).boxed()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_easing_property_inputs {
|
||||
($T0:ident, $($T:ident,)*) => {
|
||||
impl_easing_property_inputs! {
|
||||
$($T,)*
|
||||
}
|
||||
|
||||
impl<
|
||||
$T0: easing_property_input_Transitionable,
|
||||
$($T: easing_property_input_Transitionable),*
|
||||
> easing_property for PropertyInputTypes<($T0, $($T,)*)> {
|
||||
fn easing_property_unset(self) { }
|
||||
fn easing_property(self, duration: Duration, easing: EasingFn) -> Vec<Box<dyn AnyPropertyBuildAction>> {
|
||||
if duration == Duration::ZERO {
|
||||
vec![]
|
||||
} else {
|
||||
vec![
|
||||
Box::new(PropertyBuildAction::<$T0>::new(clmv!(easing, |a| easing_property_input_Transitionable::easing(a.input, duration, easing.clone(), &a.when_conditions_data)))),
|
||||
$(Box::new(PropertyBuildAction::<$T>::new(clmv!(easing, |a| easing_property_input_Transitionable::easing(a.input, duration, easing.clone(), &a.when_conditions_data)))),)*
|
||||
]
|
||||
}
|
||||
}
|
||||
fn easing_when_data(self, duration: Duration, easing: EasingFn) -> WhenBuildAction {
|
||||
if duration == Duration::ZERO {
|
||||
WhenBuildAction::new_no_default((duration, easing))
|
||||
} else {
|
||||
WhenBuildAction::new(
|
||||
(duration, easing),
|
||||
|| {
|
||||
let easing = Arc::new($crate::var::animation::easing::linear) as EasingFn;
|
||||
vec![
|
||||
Box::new(PropertyBuildAction::<$T0>::new(clmv!(easing, |a| easing_property_input_Transitionable::easing(a.input, 0.ms(), easing.clone(), &a.when_conditions_data)))),
|
||||
$(Box::new(PropertyBuildAction::<$T>::new(clmv!(easing, |a| easing_property_input_Transitionable::easing(a.input, 0.ms(), easing.clone(), &a.when_conditions_data)))),)*
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
() => { };
|
||||
}
|
||||
impl_easing_property_inputs! {
|
||||
I0, I1, I2, I3, I4, I5, I6, I7, I8, I9, I10, I11, I12, I13, I14, I15,
|
||||
}
|
||||
|
||||
impl<T: VarValue> super::types::ArcWhenVar<T> {
|
||||
/// Create a variable similar to [`Var::easing`], but with different duration and easing functions for each condition.
|
||||
///
|
||||
/// The `condition_easing` must contain one entry for each when condition, entries can be `None`, the easing used
|
||||
/// is the first entry that corresponds to a `true` condition, or falls-back to the `default_easing`.
|
||||
pub fn easing_when(
|
||||
&self,
|
||||
condition_easing: Vec<Option<(Duration, EasingFn)>>,
|
||||
default_easing: (Duration, EasingFn),
|
||||
) -> types::ContextualizedVar<T, ReadOnlyArcVar<T>>
|
||||
where
|
||||
T: Transitionable,
|
||||
{
|
||||
let source = self.clone();
|
||||
types::ContextualizedVar::new(Arc::new(move || {
|
||||
debug_assert_eq!(source.conditions().len(), condition_easing.len());
|
||||
|
||||
let source_wk = source.downgrade();
|
||||
let easing_var = super::var(source.get());
|
||||
|
||||
let condition_easing = condition_easing.clone();
|
||||
let default_easing = default_easing.clone();
|
||||
let mut _anim_handle = AnimationHandle::dummy();
|
||||
crate::var::var_bind(&source, &easing_var, move |value, _, easing_var| {
|
||||
let source = source_wk.upgrade().unwrap();
|
||||
for ((c, _), easing) in source.conditions().iter().zip(&condition_easing) {
|
||||
if let Some((duration, func)) = easing {
|
||||
if c.get() {
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (duration, func) = &default_easing;
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
})
|
||||
.perm();
|
||||
easing_var.read_only()
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
use std::sync::{Arc, Weak};
|
||||
|
||||
use crate::animation::AnimationHandle;
|
||||
|
||||
use super::*;
|
||||
|
||||
///<span data-del-macro-root></span> Initializes a new conditional var.
|
||||
|
@ -385,6 +387,49 @@ impl<T: VarValue> ArcWhenVar<T> {
|
|||
pub fn default(&self) -> &BoxedVar<T> {
|
||||
&self.0.default
|
||||
}
|
||||
|
||||
/// Create a variable similar to [`Var::easing`], but with different duration and easing functions for each condition.
|
||||
///
|
||||
/// The `condition_easing` must contain one entry for each when condition, entries can be `None`, the easing used
|
||||
/// is the first entry that corresponds to a `true` condition, or falls-back to the `default_easing`.
|
||||
pub fn easing_when(
|
||||
&self,
|
||||
condition_easing: Vec<Option<(Duration, Arc<dyn Fn(EasingTime) -> EasingStep + Send + Sync>)>>,
|
||||
default_easing: (Duration, Arc<dyn Fn(EasingTime) -> EasingStep + Send + Sync>),
|
||||
) -> types::ContextualizedVar<T, ReadOnlyArcVar<T>>
|
||||
where
|
||||
T: Transitionable,
|
||||
{
|
||||
let source = self.clone();
|
||||
types::ContextualizedVar::new(Arc::new(move || {
|
||||
debug_assert_eq!(source.conditions().len(), condition_easing.len());
|
||||
|
||||
let source_wk = source.downgrade();
|
||||
let easing_var = super::var(source.get());
|
||||
|
||||
let condition_easing = condition_easing.clone();
|
||||
let default_easing = default_easing.clone();
|
||||
let mut _anim_handle = AnimationHandle::dummy();
|
||||
var_bind(&source, &easing_var, move |value, _, easing_var| {
|
||||
let source = source_wk.upgrade().unwrap();
|
||||
for ((c, _), easing) in source.conditions().iter().zip(&condition_easing) {
|
||||
if let Some((duration, func)) = easing {
|
||||
if c.get() {
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (duration, func) = &default_easing;
|
||||
let func = func.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), *duration, move |t| func(t));
|
||||
})
|
||||
.perm();
|
||||
easing_var.read_only()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for ArcWhenVar<T> {
|
||||
|
|
Loading…
Reference in New Issue