Refactored explicit var update requests to propagate across bindings.
This commit is contained in:
parent
00948e3763
commit
b38aa79124
|
@ -64,9 +64,6 @@
|
|||
|
||||
# Vars
|
||||
|
||||
* Previous value in hook?
|
||||
- We are cloning anyway, could have the prev-value in a Cow.
|
||||
- Owned if actually changed.
|
||||
* Merge.
|
||||
|
||||
* Config example and tests with errors.
|
||||
|
|
|
@ -969,21 +969,21 @@ impl<'a, T: VarValue> VarModify<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `(notify, new_value, tags)`.
|
||||
pub fn finish(self) -> (bool, Option<T>, Vec<Box<dyn AnyVarValue>>) {
|
||||
/// Returns `(notify, new_value, update, tags)`.
|
||||
pub fn finish(self) -> (bool, Option<T>, bool, Vec<Box<dyn AnyVarValue>>) {
|
||||
match self.value {
|
||||
Cow::Borrowed(_) => {
|
||||
if self.update {
|
||||
return (true, None, self.tags);
|
||||
return (true, None, true, self.tags);
|
||||
}
|
||||
}
|
||||
Cow::Owned(v) => {
|
||||
if self.update || self.current_value != &v {
|
||||
return (true, Some(v), self.tags);
|
||||
return (true, Some(v), self.update, self.tags);
|
||||
}
|
||||
}
|
||||
}
|
||||
(false, None, vec![])
|
||||
(false, None, false, vec![])
|
||||
}
|
||||
}
|
||||
impl<'a, T: VarValue> ops::Deref for VarModify<'a, T> {
|
||||
|
@ -1002,19 +1002,27 @@ impl<'a, T: VarValue> std::convert::AsRef<T> for VarModify<'a, T> {
|
|||
/// Arguments for [`AnyVar::hook`].
|
||||
pub struct VarHookArgs<'a> {
|
||||
value: &'a dyn AnyVarValue,
|
||||
update: bool,
|
||||
tags: &'a [Box<dyn AnyVarValue>],
|
||||
}
|
||||
impl<'a> VarHookArgs<'a> {
|
||||
/// New from updated value and custom tag.
|
||||
pub fn new(value: &'a dyn AnyVarValue, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
|
||||
Self { value, tags }
|
||||
pub fn new(value: &'a dyn AnyVarValue, update: bool, tags: &'a [Box<dyn AnyVarValue>]) -> Self {
|
||||
Self { value, update, tags }
|
||||
}
|
||||
|
||||
/// Reference the updated value.
|
||||
pub fn value(&self) -> &dyn AnyVarValue {
|
||||
pub fn value(&self) -> &'a dyn AnyVarValue {
|
||||
self.value
|
||||
}
|
||||
|
||||
/// If update was explicitly requested.
|
||||
///
|
||||
/// Note that bindings/mappings propagate this update request.
|
||||
pub fn update(&self) -> bool {
|
||||
self.update
|
||||
}
|
||||
|
||||
/// Value type ID.
|
||||
pub fn value_type(&self) -> TypeId {
|
||||
self.value.as_any().type_id()
|
||||
|
@ -1604,8 +1612,15 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
#[cfg(not(dyn_closure))]
|
||||
let mut map = map;
|
||||
|
||||
var_bind(self, other, move |value, _, other| {
|
||||
let _ = other.set(map(value));
|
||||
var_bind(self, other, move |value, args, other| {
|
||||
let value = map(value);
|
||||
let update = args.update;
|
||||
let _ = other.modify(move |vm| {
|
||||
vm.set(value);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1627,9 +1642,15 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
#[cfg(not(dyn_closure))]
|
||||
let mut map = map;
|
||||
|
||||
var_bind(self, other, move |value, _, other| {
|
||||
var_bind(self, other, move |value, args, other| {
|
||||
if let Some(value) = map(value) {
|
||||
let _ = other.set(value);
|
||||
let update = args.update;
|
||||
let _ = other.modify(move |vm| {
|
||||
vm.set(value);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1655,9 +1676,13 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
let is_from_other = args.downcast_tags::<BindMapBidiTag>().any(|&b| b == binding_tag);
|
||||
if !is_from_other {
|
||||
let value = map(value);
|
||||
let update = args.update;
|
||||
let _ = other.modify(move |vm| {
|
||||
vm.set(value);
|
||||
vm.push_tag(binding_tag);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1666,9 +1691,13 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
let is_from_self = args.downcast_tags::<BindMapBidiTag>().any(|&b| b == binding_tag);
|
||||
if !is_from_self {
|
||||
let value = map_back(value);
|
||||
let update = args.update;
|
||||
let _ = self_.modify(move |vm| {
|
||||
vm.set(value);
|
||||
vm.push_tag(binding_tag);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1696,9 +1725,13 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
let is_from_other = args.downcast_tags::<BindMapBidiTag>().any(|&b| b == binding_tag);
|
||||
if !is_from_other {
|
||||
if let Some(value) = map(value) {
|
||||
let update = args.update;
|
||||
let _ = other.modify(move |vm| {
|
||||
vm.set(value);
|
||||
vm.push_tag(binding_tag);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1708,9 +1741,13 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
let is_from_self = args.downcast_tags::<BindMapBidiTag>().any(|&b| b == binding_tag);
|
||||
if !is_from_self {
|
||||
if let Some(value) = map_back(value) {
|
||||
let update = args.update;
|
||||
let _ = self_.modify(move |vm| {
|
||||
vm.set(value);
|
||||
vm.push_tag(binding_tag);
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2039,9 +2076,12 @@ pub trait Var<T: VarValue>: IntoVar<T, Var = Self> + AnyVar + Clone {
|
|||
|
||||
let easing_fn = easing_fn.clone();
|
||||
let mut _anim_handle = animation::AnimationHandle::dummy();
|
||||
var_bind(&source, &easing_var, move |value, _, easing_var| {
|
||||
var_bind(&source, &easing_var, move |value, args, easing_var| {
|
||||
let easing_fn = easing_fn.clone();
|
||||
_anim_handle = easing_var.ease(value.clone(), duration, move |t| easing_fn(t));
|
||||
if args.update {
|
||||
easing_var.update();
|
||||
}
|
||||
})
|
||||
.perm();
|
||||
easing_var.read_only()
|
||||
|
|
|
@ -66,20 +66,20 @@ impl<T: VarValue, S: Var<T>> ArcCowVar<T, S> {
|
|||
|
||||
match data {
|
||||
Data::Source { source, hooks, .. } => {
|
||||
let (update, new_value, tags) = source.with(|val| {
|
||||
let (notify, new_value, update, tags) = source.with(|val| {
|
||||
let mut vm = VarModify::new(val);
|
||||
modify(&mut vm);
|
||||
vm.finish()
|
||||
});
|
||||
let value = new_value.unwrap_or_else(|| source.get());
|
||||
if update {
|
||||
let hook_args = VarHookArgs::new(&value, &tags);
|
||||
if notify {
|
||||
let hook_args = VarHookArgs::new(&value, update, &tags);
|
||||
hooks.retain(|h| h.call(&hook_args));
|
||||
UPDATES.update(None);
|
||||
}
|
||||
*data = Data::Owned {
|
||||
value,
|
||||
last_update: if update { VARS.update_id() } else { source.last_update() },
|
||||
last_update: if notify { VARS.update_id() } else { source.last_update() },
|
||||
hooks: mem::take(hooks),
|
||||
animation: VARS.current_modify(),
|
||||
};
|
||||
|
@ -98,18 +98,18 @@ impl<T: VarValue, S: Var<T>> ArcCowVar<T, S> {
|
|||
*animation = curr_anim;
|
||||
}
|
||||
|
||||
let (update, new_value, tags) = {
|
||||
let (notify, new_value, update, tags) = {
|
||||
let mut vm = VarModify::new(value);
|
||||
modify(&mut vm);
|
||||
vm.finish()
|
||||
};
|
||||
|
||||
if update {
|
||||
if notify {
|
||||
if let Some(nv) = new_value {
|
||||
*value = nv;
|
||||
}
|
||||
*last_update = VARS.update_id();
|
||||
let hook_args = VarHookArgs::new(value, &tags);
|
||||
let hook_args = VarHookArgs::new(value, update, &tags);
|
||||
hooks.retain(|h| h.call(&hook_args));
|
||||
UPDATES.update(None);
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ where
|
|||
data.var_handle = data.var.hook(ArcFlatMapVar::on_var_hook(weak_flat.clone()));
|
||||
data.last_update = VARS.update_id();
|
||||
data.var.with(|value| {
|
||||
let args = VarHookArgs::new(value, args.tags());
|
||||
let args = VarHookArgs::new(value, args.update(), args.tags());
|
||||
data.hooks.retain(|h| h.call(&args));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ impl<I: VarValue, O: VarValue, S: Var<I>> AnyVar for MapRef<I, O, S> {
|
|||
self.source.hook(Box::new(move |args| {
|
||||
if let Some(value) = args.downcast_value() {
|
||||
let value = map(value);
|
||||
pos_modify_action(&VarHookArgs::new(value, args.tags()))
|
||||
pos_modify_action(&VarHookArgs::new(value, args.update(), args.tags()))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ impl<I: VarValue, O: VarValue, S: Var<I>> AnyVar for MapRefBidi<I, O, S> {
|
|||
self.source.hook(Box::new(move |args| {
|
||||
if let Some(value) = args.downcast_value() {
|
||||
let value = map(value);
|
||||
pos_modify_action(&VarHookArgs::new(value, args.tags()))
|
||||
pos_modify_action(&VarHookArgs::new(value, args.update(), args.tags()))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -406,13 +406,15 @@ impl<I: VarValue, O: VarValue, S: Var<I>> Var<O> for MapRefBidi<I, O, S> {
|
|||
let map = self.map.clone();
|
||||
let map_mut = self.map_mut.clone();
|
||||
self.source.modify(move |vm| {
|
||||
let (update, new_value, tags) = {
|
||||
let (notify, new_value, update, tags) = {
|
||||
let mut vm = VarModify::new(map(vm.as_ref()));
|
||||
modify(&mut vm);
|
||||
vm.finish()
|
||||
};
|
||||
if update {
|
||||
vm.update();
|
||||
if notify {
|
||||
if update {
|
||||
vm.update();
|
||||
}
|
||||
if let Some(nv) = new_value {
|
||||
*map_mut(vm.to_mut()) = nv;
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ impl<T: VarValue> VarData<T> {
|
|||
meta.animation = curr_anim;
|
||||
}
|
||||
|
||||
let (notify, new_value, tags) = self.with(|value| {
|
||||
let (notify, new_value, update, tags) = self.with(|value| {
|
||||
let mut value = VarModify::new(value);
|
||||
modify(&mut value);
|
||||
value.finish()
|
||||
|
@ -334,7 +334,7 @@ impl<T: VarValue> VarData<T> {
|
|||
meta.last_update = VARS.update_id();
|
||||
|
||||
self.with(|val| {
|
||||
let args = VarHookArgs::new(val, &tags);
|
||||
let args = VarHookArgs::new(val, update, &tags);
|
||||
meta.hooks.retain(|h| h.call(&args));
|
||||
});
|
||||
UPDATES.update(None);
|
||||
|
|
|
@ -317,7 +317,7 @@ impl<T: VarValue> ArcWhenVar<T> {
|
|||
|
||||
if update {
|
||||
drop(data);
|
||||
VARS.schedule_update(ArcWhenVar::apply_update(rc_when, args.tags_vec()));
|
||||
VARS.schedule_update(ArcWhenVar::apply_update(rc_when, false, args.tags_vec()));
|
||||
}
|
||||
|
||||
true
|
||||
|
@ -333,7 +333,7 @@ impl<T: VarValue> ArcWhenVar<T> {
|
|||
let data = rc_when.w.lock();
|
||||
if data.active == i {
|
||||
drop(data);
|
||||
VARS.schedule_update(ArcWhenVar::apply_update(rc_when, args.tags_vec()));
|
||||
VARS.schedule_update(ArcWhenVar::apply_update(rc_when, args.update(), args.tags_vec()));
|
||||
}
|
||||
true
|
||||
} else {
|
||||
|
@ -342,7 +342,7 @@ impl<T: VarValue> ArcWhenVar<T> {
|
|||
})
|
||||
}
|
||||
|
||||
fn apply_update(rc_merge: Arc<Data<T>>, tags: Vec<Box<dyn AnyVarValue>>) -> VarUpdateFn {
|
||||
fn apply_update(rc_merge: Arc<Data<T>>, update: bool, tags: Vec<Box<dyn AnyVarValue>>) -> VarUpdateFn {
|
||||
Box::new(move || {
|
||||
let mut data = rc_merge.w.lock();
|
||||
let data = &mut *data;
|
||||
|
@ -363,7 +363,7 @@ impl<T: VarValue> ArcWhenVar<T> {
|
|||
};
|
||||
|
||||
active.with(|value| {
|
||||
let args = VarHookArgs::new(value, &tags);
|
||||
let args = VarHookArgs::new(value, update, &tags);
|
||||
data.hooks.retain(|h| h.call(&args));
|
||||
});
|
||||
UPDATES.update(None);
|
||||
|
|
Loading…
Reference in New Issue